summaryrefslogtreecommitdiffstats
path: root/contrib/gperf/src
diff options
context:
space:
mode:
authorbapt <bapt@FreeBSD.org>2011-11-28 12:29:16 +0000
committerbapt <bapt@FreeBSD.org>2011-11-28 12:29:16 +0000
commit1d0a25d803102d90071835783e60c1914af2349f (patch)
tree33fc0f3900f312a20608c032709c5153ef9a5f3d /contrib/gperf/src
parent1a5f36a1c63611877bb5908d3262c5a98ee288d1 (diff)
downloadFreeBSD-src-1d0a25d803102d90071835783e60c1914af2349f.zip
FreeBSD-src-1d0a25d803102d90071835783e60c1914af2349f.tar.gz
upgrade gperf to the last GPLv2 version (3.0.3)
Reviewed by: cognet Approved by: cognet
Diffstat (limited to 'contrib/gperf/src')
-rw-r--r--contrib/gperf/src/Makefile.in87
-rw-r--r--contrib/gperf/src/bool-array.cc46
-rw-r--r--contrib/gperf/src/bool-array.h83
-rw-r--r--contrib/gperf/src/bool-array.icc93
-rw-r--r--contrib/gperf/src/config.h.in27
-rw-r--r--contrib/gperf/src/config.h_vms20
-rwxr-xr-xcontrib/gperf/src/configure5243
-rw-r--r--contrib/gperf/src/configure.ac (renamed from contrib/gperf/src/configure.in)47
-rw-r--r--contrib/gperf/src/gen-perf.cc359
-rw-r--r--contrib/gperf/src/gen-perf.h50
-rw-r--r--contrib/gperf/src/hash-table.cc210
-rw-r--r--contrib/gperf/src/hash-table.h69
-rw-r--r--contrib/gperf/src/input.cc1005
-rw-r--r--contrib/gperf/src/input.h69
-rw-r--r--contrib/gperf/src/iterator.cc87
-rw-r--r--contrib/gperf/src/iterator.h51
-rw-r--r--contrib/gperf/src/key-list.cc2182
-rw-r--r--contrib/gperf/src/key-list.h96
-rw-r--r--contrib/gperf/src/keyword-list.cc175
-rw-r--r--contrib/gperf/src/keyword-list.h85
-rw-r--r--contrib/gperf/src/keyword-list.icc53
-rw-r--r--contrib/gperf/src/keyword.cc161
-rw-r--r--contrib/gperf/src/keyword.h116
-rw-r--r--contrib/gperf/src/keyword.icc42
-rw-r--r--contrib/gperf/src/list-node.cc102
-rw-r--r--contrib/gperf/src/list-node.h46
-rw-r--r--contrib/gperf/src/main.cc201
-rw-r--r--contrib/gperf/src/new.cc87
-rw-r--r--contrib/gperf/src/options.cc1120
-rw-r--r--contrib/gperf/src/options.h372
-rw-r--r--contrib/gperf/src/options.icc190
-rw-r--r--contrib/gperf/src/output.cc2100
-rw-r--r--contrib/gperf/src/output.h154
-rw-r--r--contrib/gperf/src/positions.cc177
-rw-r--r--contrib/gperf/src/positions.h175
-rw-r--r--contrib/gperf/src/positions.icc285
-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/search.cc1684
-rw-r--r--contrib/gperf/src/search.h165
-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.cc36
-rw-r--r--contrib/gperf/src/version.h30
47 files changed, 12246 insertions, 5468 deletions
diff --git a/contrib/gperf/src/Makefile.in b/contrib/gperf/src/Makefile.in
index 60f73c7..19defc4 100644
--- a/contrib/gperf/src/Makefile.in
+++ b/contrib/gperf/src/Makefile.in
@@ -1,13 +1,14 @@
# Makefile for gperf/src
-# Copyright (C) 1989, 1992, 1993, 1998, 2000 Free Software Foundation, Inc.
-# written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+# Copyright (C) 1989, 1992, 1993, 1998, 2000, 2002, 2006 Free Software Foundation, Inc.
+# Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+# and Bruno Haible <bruno@clisp.org>.
#
# 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)
+# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# GNU GPERF is distributed in the hope that it will be useful,
@@ -16,8 +17,9 @@
# 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.
+# along with this program; see the file COPYING.
+# If not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#### Start of system configuration section. ####
@@ -41,6 +43,8 @@ CXXFLAGS = @CXXFLAGS@
CXXCPP = @CXXCPP@
# Both C and C++ compiler
LDFLAGS = @LDFLAGS@
+OBJEXT = @OBJEXT@
+EXEEXT = @EXEEXT@
# Other
MV = mv
LN = ln
@@ -59,12 +63,12 @@ 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
+OBJECTS = version.$(OBJEXT) positions.$(OBJEXT) options.$(OBJEXT) keyword.$(OBJEXT) keyword-list.$(OBJEXT) \
+ input.$(OBJEXT) bool-array.$(OBJEXT) hash-table.$(OBJEXT) search.$(OBJEXT) output.$(OBJEXT) main.$(OBJEXT)
+LIBS = ../lib/libgp.a @GPERF_LIBM@
CPPFLAGS = -I. -I$(srcdir)/../lib
-TARGETPROG = gperf
+TARGETPROG = gperf$(EXEEXT)
all : $(TARGETPROG)
@@ -83,43 +87,38 @@ $(TARGETPROG): $(OBJECTS)
# 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)
+POSITIONS_H = positions.h positions.icc
+OPTIONS_H = options.h options.icc $(POSITIONS_H)
+KEYWORD_H = keyword.h keyword.icc
+KEYWORD_LIST_H = keyword-list.h keyword-list.icc $(KEYWORD_H)
+INPUT_H = input.h $(KEYWORD_LIST_H)
+BOOL_ARRAY_H = bool-array.h bool-array.icc $(OPTIONS_H)
+HASH_TABLE_H = hash-table.h $(KEYWORD_H)
+SEARCH_H = search.h $(KEYWORD_LIST_H) $(POSITIONS_H) $(BOOL_ARRAY_H)
+OUTPUT_H = output.h $(KEYWORD_LIST_H) $(POSITIONS_H)
+
+version.$(OBJEXT): version.cc $(VERSION_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/version.cc
+positions.$(OBJEXT): positions.cc $(POSITIONS_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/positions.cc
+options.$(OBJEXT): options.cc $(OPTIONS_H) $(VERSION_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/options.cc
+keyword.$(OBJEXT): keyword.cc $(KEYWORD_H) $(POSITIONS_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/keyword.cc
+keyword-list.$(OBJEXT): keyword-list.cc $(KEYWORD_LIST_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/keyword-list.cc
+input.$(OBJEXT): input.cc $(INPUT_H) $(OPTIONS_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/input.cc
+bool-array.$(OBJEXT): bool-array.cc $(BOOL_ARRAY_H) $(OPTIONS_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)
+hash-table.$(OBJEXT): hash-table.cc $(HASH_TABLE_H) $(OPTIONS_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)
+search.$(OBJEXT): search.cc $(SEARCH_H) $(OPTIONS_H) $(HASH_TABLE_H) $(CONFIG_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/search.cc
+output.$(OBJEXT): output.cc $(OUTPUT_H) $(OPTIONS_H) $(VERSION_H)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/output.cc
+main.$(OBJEXT): main.cc $(OPTIONS_H) $(INPUT_H) $(SEARCH_H) $(OUTPUT_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
$(MKINSTALLDIRS) $(DESTDIR)$(bindir)
@@ -136,7 +135,7 @@ check : all
mostlyclean : clean
clean : force
- $(RM) *~ *.s *.o *.a $(TARGETPROG) core
+ $(RM) *~ *.s *.$(OBJEXT) *.a $(TARGETPROG) core
distclean : clean
$(RM) config.status config.log config.cache Makefile config.h
diff --git a/contrib/gperf/src/bool-array.cc b/contrib/gperf/src/bool-array.cc
index 0774b2d..ca3c501 100644
--- a/contrib/gperf/src/bool-array.cc
+++ b/contrib/gperf/src/bool-array.cc
@@ -1,43 +1,41 @@
/* 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)
+ Copyright (C) 1989-1998, 2002 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
-This file is part of GNU GPERF.
+ 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 free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
-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.
+ 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. */
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+/* Specification. */
#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)
+/* Frees this object. */
+Bool_Array::~Bool_Array ()
{
- T (Trace t ("Bool_Array::~Bool_Array");)
+ /* Print out debugging diagnostics. */
if (option[DEBUG])
fprintf (stderr, "\ndumping boolean array information\n"
"size = %d\niteration number = %d\nend of array dump\n",
- size, iteration_number);
+ _size, _iteration_number);
+ delete[] const_cast<unsigned int *>(_storage_array);
}
#ifndef __OPTIMIZE__
diff --git a/contrib/gperf/src/bool-array.h b/contrib/gperf/src/bool-array.h
index 8330fcd..ddfbd869 100644
--- a/contrib/gperf/src/bool-array.h
+++ b/contrib/gperf/src/bool-array.h
@@ -2,54 +2,67 @@
/* 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)
+ Copyright (C) 1989-1998, 2002 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
-This file is part of GNU GPERF.
+ 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 free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
-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.
+ 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. */
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#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
+/* A Bool_Array instance is a bit array of fixed size, optimized for being
+ filled sparsely and cleared frequently. For example, when processing
+ tests/chill.gperf, the array will be:
+ - of size 15391,
+ - clear will be called 3509 times,
+ - set_bit will be called 300394 times.
+ With a conventional bit array implementation, clear would be too slow.
+ With a tree/hash based bit array implementation, set_bit would be slower. */
class Bool_Array
{
+public:
+ /* Initializes the bit array with room for SIZE bits, numbered from
+ 0 to SIZE-1. */
+ Bool_Array (unsigned int size);
+
+ /* Frees this object. */
+ ~Bool_Array ();
+
+ /* Resets all bits to zero. */
+ void clear ();
+
+ /* Sets the specified bit to true.
+ Returns its previous value (false or true). */
+ bool set_bit (unsigned int index);
+
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. */
+ /* Size of array. */
+ unsigned int const _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);
+ /* Current iteration number. Always nonzero. Starts out as 1, and is
+ incremented each time clear() is called. */
+ unsigned int _iteration_number;
+
+ /* For each index, we store in storage_array[index] the iteration_number at
+ the time set_bit(index) was last called. */
+ unsigned int * const _storage_array;
};
#ifdef __OPTIMIZE__ /* efficiency hack! */
diff --git a/contrib/gperf/src/bool-array.icc b/contrib/gperf/src/bool-array.icc
index 6de6f23..fba4a31 100644
--- a/contrib/gperf/src/bool-array.icc
+++ b/contrib/gperf/src/bool-array.icc
@@ -1,84 +1,77 @@
/* Inline Functions for bool-array.{h,cc}.
- Copyright (C) 1989-1998 Free Software Foundation, Inc.
- written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+ Copyright (C) 1989-1998, 2002 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
-This file is part of GNU GPERF.
+ 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 free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
-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.
+ 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. */
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
// This needs:
//#include <stdio.h>
//#include <string.h>
//#include "options.h"
-//#include "trace.h"
+/* Initializes the bit array with room for SIZE bits, numbered from
+ 0 to SIZE-1. */
INLINE
-Bool_Array::Bool_Array (void)
+Bool_Array::Bool_Array (unsigned int size)
+ : _size (size),
+ _iteration_number (1),
+ _storage_array (new unsigned int [size])
{
- 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));
+ memset (_storage_array, 0, size * sizeof (_storage_array[0]));
if (option[DEBUG])
fprintf (stderr, "\nbool array size = %d, total bytes = %d\n",
- size, (unsigned int) (size * sizeof (*storage_array)));
+ _size,
+ static_cast<unsigned int> (_size * sizeof (_storage_array[0])));
}
-INLINE int
-Bool_Array::find (int index)
+/* Sets the specified bit to true.
+ Returns its previous value (false or true). */
+INLINE bool
+Bool_Array::set_bit (unsigned int index)
{
- T (Trace t ("Bool_Array::find");)
- if (storage_array[index] == iteration_number)
- return 1;
+ if (_storage_array[index] == _iteration_number)
+ /* The bit was set since the last clear() call. */
+ return true;
else
{
- storage_array[index] = iteration_number;
- return 0;
+ /* The last operation on this bit was clear(). Set it now. */
+ _storage_array[index] = _iteration_number;
+ return false;
}
}
+/* Resets all bits to zero. */
INLINE void
-Bool_Array::reset (void)
+Bool_Array::clear ()
{
- 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! */
+ occurs once about every 2^32 iterations, so it will not happen more
+ frequently than once per second. */
- if (++iteration_number == 0)
+ if (++_iteration_number == 0)
{
+ _iteration_number = 1;
+ memset (_storage_array, 0, _size * sizeof (_storage_array[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");
+ fprintf (stderr, "(re-initialized bool_array)\n");
fflush (stderr);
}
}
diff --git a/contrib/gperf/src/config.h.in b/contrib/gperf/src/config.h.in
index 4d3d762..1f3dc58 100644
--- a/contrib/gperf/src/config.h.in
+++ b/contrib/gperf/src/config.h.in
@@ -1,19 +1,20 @@
-/* config.h.in. Generated automatically from configure.in by autoheader. */
+/* config.h.in. Generated from configure.ac by autoheader. */
-/* Define if the C++ compiler supports "throw ()" declarations. */
-#undef HAVE_THROW_DECL
+/* Define if the C++ compiler supports stack-allocated variable-size arrays.
+ */
+#undef HAVE_DYNAMIC_ARRAY
-/* Define if you have the getrlimit function. */
-#undef HAVE_GETRLIMIT
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
-/* Define if you have the setrlimit function. */
-#undef HAVE_SETRLIMIT
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
-/* Define if you have the <sys/resource.h> header file. */
-#undef HAVE_SYS_RESOURCE_H
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
-/* Define if you have the <sys/time.h> header file. */
-#undef HAVE_SYS_TIME_H
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
-/* Define if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
diff --git a/contrib/gperf/src/config.h_vms b/contrib/gperf/src/config.h_vms
new file mode 100644
index 0000000..1f3dc58
--- /dev/null
+++ b/contrib/gperf/src/config.h_vms
@@ -0,0 +1,20 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define if the C++ compiler supports stack-allocated variable-size arrays.
+ */
+#undef HAVE_DYNAMIC_ARRAY
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
diff --git a/contrib/gperf/src/configure b/contrib/gperf/src/configure
index edd1fd7..ab70481 100755
--- a/contrib/gperf/src/configure
+++ b/contrib/gperf/src/configure
@@ -1,26 +1,662 @@
#! /bin/sh
-
# Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.13
-# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+# Generated by GNU Autoconf 2.61.
#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+ if (eval ":") 2>/dev/null; then
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+
+ if test $as_have_required = yes && (eval ":
+(as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=\$LINENO
+ as_lineno_2=\$LINENO
+ test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+ test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+ :
+else
+ as_candidate_shells=
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ case $as_dir in
+ /*)
+ for as_base in sh bash ksh sh5; do
+ as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+ done;;
+ esac
+done
+IFS=$as_save_IFS
+
+
+ for as_shell in $as_candidate_shells $SHELL; do
+ # Try only shells that exist, to save several forks.
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+ CONFIG_SHELL=$as_shell
+ as_have_required=yes
+ if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+ (exit $1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+ break
+fi
+
+fi
+
+ done
+
+ if test "x$CONFIG_SHELL" != x; then
+ for as_var in BASH_ENV ENV
+ do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ done
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
-# Defaults:
-ac_help=
+ if test $as_have_required = no; then
+ echo This script requires a shell more modern than all the
+ echo shells that I found on your system. Please install a
+ echo modern shell, or manually run the script under such a
+ echo shell if you do have one.
+ { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+ echo No shell found that supports shell functions.
+ echo Please tell autoconf@gnu.org about your system,
+ echo including any error possibly output before this
+ echo message
+}
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
ac_default_prefix=/usr/local
-# Any additions from configure.in:
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="main.cc"
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+SET_MAKE
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+CPP
+CXX
+CXXFLAGS
+ac_ct_CXX
+CXXCPP
+INSTALL
+INSTALL_PROGRAM
+INSTALL_DATA
+GPERF_LIBM
+LIBOBJS
+LTLIBOBJS'
+ac_subst_files=''
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+CXX
+CXXFLAGS
+CCC
+CXXCPP'
+
# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
# The variables have the same names as the options, with
# dashes changed to underlines.
-build=NONE
-cache_file=./config.cache
+cache_file=/dev/null
exec_prefix=NONE
-host=NONE
no_create=
-nonopt=NONE
no_recursion=
prefix=NONE
program_prefix=NONE
@@ -29,94 +665,117 @@ program_transform_name=s,x,x,
silent=
site=
srcdir=
-target=NONE
verbose=
x_includes=NONE
x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
bindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
-datadir='${prefix}/share'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
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=
-SHELL=${CONFIG_SHELL-/bin/sh}
-# Maximum number of lines to put in a shell here document.
-ac_max_here_lines=12
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
ac_prev=
+ac_dashdash=
for ac_option
do
-
# If the previous option needs an argument, assign it.
if test -n "$ac_prev"; then
- eval "$ac_prev=\$ac_option"
+ 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= ;;
+ case $ac_option in
+ *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *) ac_optarg=yes ;;
esac
# Accept the important Cygnus configure options, so we can diagnose typos.
- case "$ac_option" in
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
-bindir | --bindir | --bindi | --bind | --bin | --bi)
ac_prev=bindir ;;
-bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
- bindir="$ac_optarg" ;;
+ bindir=$ac_optarg ;;
-build | --build | --buil | --bui | --bu)
- ac_prev=build ;;
+ ac_prev=build_alias ;;
-build=* | --build=* | --buil=* | --bui=* | --bu=*)
- build="$ac_optarg" ;;
+ build_alias=$ac_optarg ;;
-cache-file | --cache-file | --cache-fil | --cache-fi \
| --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
ac_prev=cache_file ;;
-cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
| --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
- cache_file="$ac_optarg" ;;
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
- -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ -datadir | --datadir | --datadi | --datad)
ac_prev=datadir ;;
- -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
- | --da=*)
- datadir="$ac_optarg" ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
-disable-* | --disable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ ac_feature=`expr "x$ac_option" : 'x-*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" ;;
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
-enable-* | --enable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# 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'" ;;
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=\$ac_optarg ;;
-exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
| --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
@@ -125,116 +784,77 @@ do
-exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
| --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
| --exec=* | --exe=* | --ex=*)
- exec_prefix="$ac_optarg" ;;
+ 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 ;;
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
-host | --host | --hos | --ho)
- ac_prev=host ;;
+ ac_prev=host_alias ;;
-host=* | --host=* | --hos=* | --ho=*)
- host="$ac_optarg" ;;
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$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" ;;
+ includedir=$ac_optarg ;;
-infodir | --infodir | --infodi | --infod | --info | --inf)
ac_prev=infodir ;;
-infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
- infodir="$ac_optarg" ;;
+ infodir=$ac_optarg ;;
-libdir | --libdir | --libdi | --libd)
ac_prev=libdir ;;
-libdir=* | --libdir=* | --libdi=* | --libd=*)
- libdir="$ac_optarg" ;;
+ 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" ;;
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
-localstatedir | --localstatedir | --localstatedi | --localstated \
- | --localstate | --localstat | --localsta | --localst \
- | --locals | --local | --loca | --loc | --lo)
+ | --localstate | --localstat | --localsta | --localst | --locals)
ac_prev=localstatedir ;;
-localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
- | --localstate=* | --localstat=* | --localsta=* | --localst=* \
- | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
- localstatedir="$ac_optarg" ;;
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
-mandir | --mandir | --mandi | --mand | --man | --ma | --m)
ac_prev=mandir ;;
-mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
- mandir="$ac_optarg" ;;
+ 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-cr | --no-c | -n)
no_create=yes ;;
-no-recursion | --no-recursion | --no-recursio | --no-recursi \
@@ -248,26 +868,26 @@ EOF
-oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
| --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
| --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
- oldincludedir="$ac_optarg" ;;
+ oldincludedir=$ac_optarg ;;
-prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
ac_prev=prefix ;;
-prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
- prefix="$ac_optarg" ;;
+ 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_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_suffix=$ac_optarg ;;
-program-transform-name | --program-transform-name \
| --program-transform-nam | --program-transform-na \
@@ -284,7 +904,17 @@ EOF
| --program-transfo=* | --program-transf=* \
| --program-trans=* | --program-tran=* \
| --progr-tra=* | --program-tr=* | --program-t=*)
- program_transform_name="$ac_optarg" ;;
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
@@ -294,7 +924,7 @@ EOF
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
| --sbi=* | --sb=*)
- sbindir="$ac_optarg" ;;
+ sbindir=$ac_optarg ;;
-sharedstatedir | --sharedstatedir | --sharedstatedi \
| --sharedstated | --sharedstate | --sharedstat | --sharedsta \
@@ -305,58 +935,53 @@ EOF
| --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
| --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
| --sha=* | --sh=*)
- sharedstatedir="$ac_optarg" ;;
+ sharedstatedir=$ac_optarg ;;
-site | --site | --sit)
ac_prev=site ;;
-site=* | --site=* | --sit=*)
- site="$ac_optarg" ;;
+ site=$ac_optarg ;;
-srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
ac_prev=srcdir ;;
-srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
- srcdir="$ac_optarg" ;;
+ 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" ;;
+ sysconfdir=$ac_optarg ;;
-target | --target | --targe | --targ | --tar | --ta | --t)
- ac_prev=target ;;
+ ac_prev=target_alias ;;
-target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
- target="$ac_optarg" ;;
+ target_alias=$ac_optarg ;;
-v | -verbose | --verbose | --verbos | --verbo | --verb)
verbose=yes ;;
- -version | --version | --versio | --versi | --vers)
- echo "configure generated by autoconf version 2.13"
- exit 0 ;;
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
-with-* | --with-*)
- ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# 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'" ;;
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=\$ac_optarg ;;
-without-* | --without-*)
- ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ ac_package=`expr "x$ac_option" : 'x-*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" ;;
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=no ;;
--x)
# Obsolete; use --with-x.
@@ -367,396 +992,1478 @@ EOF
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_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" ;;
+ x_libraries=$ac_optarg ;;
- -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
;;
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
*)
- 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"
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
;;
esac
done
if test -n "$ac_prev"; then
- { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
fi
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+# Be sure to have absolute directory names.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; }
+done
-# 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
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
fi
-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
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
-# 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
+test "$silent" = yes && exec 6>/dev/null
-# 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
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ { echo "$as_me: error: Working directory cannot be determined" >&2
+ { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ { echo "$as_me: error: pwd does not report name of working directory" >&2
+ { (exit 1); exit 1; }; }
-# 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=.
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
srcdir=$ac_confdir
- if test ! -r $srcdir/$ac_unique_file; then
+ 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
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+ { (exit 1); exit 1; }; }
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
fi
-srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ CXXCPP C++ preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" || continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args '$ac_arg'"
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
# Prefer explicitly selected file to automatically selected ones.
-if test -z "$CONFIG_SITE"; then
- if test "x$prefix" != xNONE; then
- CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
- else
- CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
- fi
+if test -n "$CONFIG_SITE"; then
+ set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+ set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+ set x "$ac_default_prefix/share/config.site" \
+ "$ac_default_prefix/etc/config.site"
fi
-for ac_site_file in $CONFIG_SITE; do
+shift
+for ac_site_file
+do
if test -r "$ac_site_file"; then
- echo "loading site script $ac_site_file"
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file"
fi
done
if test -r "$cache_file"; then
- echo "loading cache $cache_file"
- . $cache_file
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
else
- echo "creating cache $cache_file"
- > $cache_file
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$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${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-ac_exeext=
-ac_objext=o
-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=
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
fi
-else
- ac_n= ac_c='\c' ac_t=
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
fi
-echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:527: 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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; }
+set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftestmake <<\EOF
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
all:
- @echo 'ac_maketemp="${MAKE}"'
-EOF
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
# 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
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
fi
-if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
SET_MAKE=
else
- echo "$ac_t""no" 1>&6
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
SET_MAKE="MAKE=${MAKE-make}"
fi
-# Extract the first word of "gcc", so it can be a program name with args.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:556: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; 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"
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
fi
fi
-CC="$ac_cv_prog_CC"
+CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
else
- echo "$ac_t""no" 1>&6
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
fi
+
+ fi
+fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:586: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
ac_prog_rejected=no
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; 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"
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_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
+ if test $# != 0; then
# We chose a different compiler from the bogus one.
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
- set dummy "$ac_dir/$ac_word" "$@"
- shift
- ac_cv_prog_CC="$@"
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
fi
fi
fi
fi
-CC="$ac_cv_prog_CC"
+CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
else
- echo "$ac_t""no" 1>&6
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
fi
- if test -z "$CC"; then
- case "`uname -s`" in
- *win32* | *WIN32*)
- # Extract the first word of "cl", so it can be a program name with args.
-set dummy cl; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:637: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_CC="cl"
- break
- fi
- done
- IFS="$ac_save_ifs"
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
fi
fi
-CC="$ac_cv_prog_CC"
+CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
else
- echo "$ac_t""no" 1>&6
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
fi
- ;;
- esac
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
fi
- test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
fi
-echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:669: 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${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-cat > conftest.$ac_ext << EOF
-
-#line 680 "configure"
-#include "confdefs.h"
-
-main(){return(0);}
-EOF
-if { (eval echo configure:685: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; 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
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
else
- ac_cv_prog_cc_cross=yes
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort. b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions. Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- ac_cv_prog_cc_works=no
+ ac_file=''
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${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-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:711: 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:716: 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:725: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
- ac_cv_prog_gcc=yes
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
else
- ac_cv_prog_gcc=no
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
fi
-echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
-if test $ac_cv_prog_gcc = yes; then
- GCC=yes
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
else
- GCC=
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
fi
-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:744: 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
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
else
- echo 'void f(){}' > conftest.c
-if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_prog_cc_g=yes
else
- ac_cv_prog_cc_g=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
fi
-rm -f conftest*
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
if test "$ac_test_CFLAGS" = set; then
- CFLAGS="$ac_save_CFLAGS"
+ CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
CFLAGS="-g -O2"
@@ -770,216 +2477,702 @@ else
CFLAGS=
fi
fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_c89=$ac_arg
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+ xno)
+ { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
- echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:776: checking how to run the C preprocessor" >&5
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
fi
if test -z "$CPP"; then
-if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&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"
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
# On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp.
- cat > conftest.$ac_ext <<EOF
-#line 791 "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:797: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-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 808 "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:814: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
:
else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP="${CC-cc} -nologo -E"
- cat > conftest.$ac_ext <<EOF
-#line 825 "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:831: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- :
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP=/lib/cpp
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
fi
-rm -f conftest*
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
fi
-rm -f conftest*
+{ echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
fi
-rm -f conftest*
- ac_cv_prog_CPP="$CPP"
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
fi
- CPP="$ac_cv_prog_CPP"
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
else
- ac_cv_prog_CPP="$CPP"
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
fi
-echo "$ac_t""$CPP" 1>&6
- for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl
-do
-# Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:860: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$CXX"; then
ac_cv_prog_CXX="$CXX" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; 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"
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
fi
fi
-CXX="$ac_cv_prog_CXX"
+CXX=$ac_cv_prog_CXX
if test -n "$CXX"; then
- echo "$ac_t""$CXX" 1>&6
+ { echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6; }
else
- echo "$ac_t""no" 1>&6
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
fi
-test -n "$CXX" && break
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
done
-test -n "$CXX" || CXX="gcc"
+IFS=$as_save_IFS
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
-echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:892: 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${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cxx_cross
-
-cat > conftest.$ac_ext << EOF
-
-#line 903 "configure"
-#include "confdefs.h"
-
-int main(){return(0);}
-EOF
-if { (eval echo configure:908: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; 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
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
else
- ac_cv_prog_cxx_cross=yes
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
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${ac_exeext} $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:934: 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:939: 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;
+
+ fi
+fi
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
#endif
-EOF
-if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:948: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
- ac_cv_prog_gxx=yes
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
else
- ac_cv_prog_gxx=no
-fi
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
fi
-echo "$ac_t""$ac_cv_prog_gxx" 1>&6
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
-if test $ac_cv_prog_gxx = yes; then
- GXX=yes
-else
- GXX=
fi
-
-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:967: 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
+{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; }
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cxx_g=yes
else
- echo 'void f(){}' > conftest.cc
-if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CXXFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_prog_cxx_g=yes
else
- ac_cv_prog_cxx_g=no
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-rm -f conftest*
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; }
if test "$ac_test_CXXFLAGS" = set; then
- CXXFLAGS="$ac_save_CXXFLAGS"
+ CXXFLAGS=$ac_save_CXXFLAGS
elif test $ac_cv_prog_cxx_g = yes; then
if test "$GXX" = yes; then
CXXFLAGS="-g -O2"
@@ -993,49 +3186,237 @@ else
CXXFLAGS=
fi
fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
- echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6
-echo "configure:999: checking how to run the C++ preprocessor" >&5
+ ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5
+echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; }
if test -z "$CXXCPP"; then
-if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ if test "${ac_cv_prog_CXXCPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&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${ac_exeext} $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 1012 "configure"
-#include "confdefs.h"
-#include <stdlib.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1017: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
+ # Double quotes because CXXCPP needs to be expanded
+ for CXXCPP in "$CXX -E" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
:
else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CXXCPP=/lib/cpp
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
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${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+ CXXCPP=$ac_cv_prog_CXXCPP
+else
+ ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ echo "$as_me:$LINENO: result: $CXXCPP" >&5
+echo "${ECHO_T}$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
fi
-CXXCPP="$ac_cv_prog_CXXCPP"
-echo "$ac_t""$CXXCPP" 1>&6
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
# Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or
@@ -1047,11 +3428,11 @@ echo "$ac_t""$CXXCPP" 1>&6
# 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:1052: checking for a BSD compatible install" >&5
+{ echo "$as_me:$LINENO: checking for a BSD compatible install" >&5
+echo $ECHO_N "checking for a BSD compatible install... $ECHO_C" >&6; }
if test -z "$INSTALL"; then
-if eval "test \"`echo '$''{'cl_cv_path_install'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+if test "${cl_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
for ac_dir in $PATH; do
@@ -1089,7 +3470,8 @@ else
fi
INSTALL="$cl_cv_path_install"
fi
-echo "$ac_t""$INSTALL" 1>&6
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
# It thinks the first close brace ends the variable substitution.
test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='$(INSTALL)'
@@ -1100,561 +3482,1244 @@ if test -z "$INSTALL_DATA"; then
esac
fi
- echo $ac_n "checking for working throw()""... $ac_c" 1>&6
-echo "configure:1105: checking for working throw()" >&5
-if eval "test \"`echo '$''{'gp_cv_cxx_throw_decl'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ { echo "$as_me:$LINENO: checking for stack-allocated variable-size arrays" >&5
+echo $ECHO_N "checking for stack-allocated variable-size arrays... $ECHO_C" >&6; }
+
+if test "${gp_cv_cxx_dynamic_array+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
-
-ac_ext=C
-# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+
+ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cxx_cross
-
-cat > conftest.$ac_ext <<EOF
-#line 1119 "configure"
-#include "confdefs.h"
-#include <stdlib.h>
-void operator delete (void* ptr) throw() {}
-int main() {
-
-; return 0; }
-EOF
-if { (eval echo configure:1127: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- gp_cv_cxx_throw_decl=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- gp_cv_cxx_throw_decl=no
-fi
-rm -f conftest*
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+int func (int n) { int dynamic_array[n]; }
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ gp_cv_cxx_dynamic_array=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ gp_cv_cxx_dynamic_array=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
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${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
fi
-echo "$ac_t""$gp_cv_cxx_throw_decl" 1>&6
-if test $gp_cv_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:1158: 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 1163 "configure"
-#include "confdefs.h"
-#include <$ac_hdr>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1168: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-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
+{ echo "$as_me:$LINENO: result: $gp_cv_cxx_dynamic_array" >&5
+echo "${ECHO_T}$gp_cv_cxx_dynamic_array" >&6; }
+if test $gp_cv_cxx_dynamic_array = yes; then
- 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:1198: 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 1203 "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
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DYNAMIC_ARRAY 1
+_ACEOF
-; return 0; }
-EOF
-if { (eval echo configure:1226: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; 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
-
+{ echo "$as_me:$LINENO: checking for rand in -lm" >&5
+echo $ECHO_N "checking for rand in -lm... $ECHO_C" >&6; }
+if test "${ac_cv_lib_m_rand+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
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:1254: 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 1259 "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();
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
#endif
-
-; return 0; }
-EOF
-if { (eval echo configure:1282: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
+char rand ();
+int
+main ()
+{
+return rand ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_m_rand=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*
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_m_rand=no
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
-
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_m_rand" >&5
+echo "${ECHO_T}$ac_cv_lib_m_rand" >&6; }
+if test $ac_cv_lib_m_rand = yes; then
+ GPERF_LIBM="-lm"
else
- echo "$ac_t""no" 1>&6
+ GPERF_LIBM=""
fi
-done
- fi
-fi
-trap '' 1 2 15
-cat > confcache <<\EOF
+
+ac_config_files="$ac_config_files Makefile"
+
+cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
-# scripts and configure runs. It is not useful on other systems.
-# If it contains results you don't want to keep, you may remove or edit it.
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
#
-# 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.
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
#
-EOF
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
+# So, we kill variables containing newlines.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
-(set) 2>&1 |
- case `(ac_space=' '; set | grep ac_space) 2>&1` in
- *ac_space=\ *)
- # `set' does not quote correctly, so add quotes (double-quote substitution
- # turns \\\\ into \\, and sed turns \\ into \).
- sed -n \
- -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
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ test "x$cache_file" != "x/dev/null" &&
+ { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+ cat confcache >$cache_file
else
- echo "not updating unwritable cache $cache_file"
+ { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
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
+DEFS=-DHAVE_CONFIG_H
-trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
-DEFS=-DHAVE_CONFIG_H
+LTLIBOBJS=$ac_ltlibobjs
-# 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.
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
# Run this file to recreate the current configuration.
-# 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.
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
-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.13"
- exit 0 ;;
- -help | --help | --hel | --he | --h)
- echo "\$ac_cs_usage"; exit 0 ;;
- *) echo "\$ac_cs_usage"; exit 1 ;;
- esac
-done
+fi
-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%@SHELL@%$SHELL%g
-s%@CFLAGS@%$CFLAGS%g
-s%@CPPFLAGS@%$CPPFLAGS%g
-s%@CXXFLAGS@%$CXXFLAGS%g
-s%@FFLAGS@%$FFLAGS%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
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
else
- sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ PATH_SEPARATOR=:
fi
- if test ! -s conftest.s$ac_file; then
- ac_more_lines=false
- rm -f conftest.s$ac_file
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
else
- 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`
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
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.
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
- # 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'`
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
else
- ac_dir_suffix= ac_dots=
+ as_ls_L_option=
fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
- 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" ;;
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.61,
+ with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
esac
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ echo "$ac_cs_version"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1"
+ ac_need_defaults=false ;;
- 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
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ CONFIG_SHELL=$SHELL
+ export CONFIG_SHELL
+ exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
- 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" ;;
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+SET_MAKE!$SET_MAKE$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+CPP!$CPP$ac_delim
+CXX!$CXX$ac_delim
+CXXFLAGS!$CXXFLAGS$ac_delim
+ac_ct_CXX!$ac_ct_CXX$ac_delim
+CXXCPP!$CXXCPP$ac_delim
+INSTALL!$INSTALL$ac_delim
+INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
+INSTALL_DATA!$INSTALL_DATA$ac_delim
+GPERF_LIBM!$GPERF_LIBM$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 56; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+ ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+ ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+ { (exit 1); exit 1; }; };;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+ ac_file_inputs="$ac_file_inputs $ac_f"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input="Generated from "`IFS=:
+ echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ fi
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin";;
+ esac
+ ;;
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
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir="$ac_dir"
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out"; rm -f "$tmp/out";;
+ *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+ esac
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status. If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless. But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*'
+ac_dB='\\)[ (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+ sed -n '
+ t rset
+ :rset
+ s/^[ ]*#[ ]*define[ ][ ]*//
+ t ok
+ d
+ :ok
+ s/[\\&,]/\\&/g
+ s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+ s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+ ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #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
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[ #]*u.*,/* & */,' >>conftest.defines
-# Break up conftest.vals because some shells have a limit on
-# the size of here documents, and old seds have small limits too.
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
-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
+ # Write a here document:
+ cat >>$CONFIG_STATUS <<_ACEOF
+ # First, check the format of the line:
+ cat >"\$tmp/defines.sed" <<\\CEOF
+/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def
+/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def
+b
+:def
+_ACEOF
+ sed ${ac_max_sed_lines}q conftest.defines >>$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
+ sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+ ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+ sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+ grep . conftest.tail >/dev/null || break
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
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"
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+ if test x"$ac_file" != x-; then
+ echo "/* $configure_input */" >"$tmp/config.h"
+ cat "$ac_result" >>"$tmp/config.h"
+ if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f $ac_file
+ mv "$tmp/config.h" $ac_file
fi
- rm -f $ac_file
- mv conftest.h $ac_file
+ else
+ echo "/* $configure_input */"
+ cat "$ac_result"
fi
-fi; done
+ rm -f "$tmp/out12"
+ ;;
+
-EOF
-cat >> $CONFIG_STATUS <<EOF
+ esac
+
+done # for ac_tag
-EOF
-cat >> $CONFIG_STATUS <<\EOF
-exit 0
-EOF
+{ (exit 0); exit 0; }
+_ACEOF
chmod +x $CONFIG_STATUS
-rm -fr confdefs* $ac_clean_files
-test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
diff --git a/contrib/gperf/src/configure.in b/contrib/gperf/src/configure.ac
index e8880d5..b7b91a0 100644
--- a/contrib/gperf/src/configure.in
+++ b/contrib/gperf/src/configure.ac
@@ -1,13 +1,14 @@
dnl autoconf configuration for gperf/src
-dnl Copyright (C) 1998, 2000 Free Software Foundation, Inc.
-dnl written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+dnl Copyright (C) 1998, 2000, 2002-2003, 2007 Free Software Foundation, Inc.
+dnl Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+dnl and Bruno Haible <bruno@clisp.org>.
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 the Free Software Foundation; either version 2, or (at your option)
dnl any later version.
dnl
dnl GNU GPERF is distributed in the hope that it will be useful,
@@ -16,11 +17,12 @@ 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.
+dnl along with this program; see the file COPYING.
+dnl If not, write to the Free Software Foundation, Inc.,
+dnl 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-AC_INIT(gen-perf.cc)
+AC_PREREQ([2.60])
+AC_INIT(main.cc)
AC_CONFIG_HEADER(config.h)
AC_PROG_MAKE_SET
dnl
@@ -39,32 +41,27 @@ CL_PROG_INSTALL
dnl
dnl checks for compiler characteristics
dnl
-AC_MSG_CHECKING([for working throw()])
-AC_CACHE_VAL(gp_cv_cxx_throw_decl,[
+AC_MSG_CHECKING([for stack-allocated variable-size arrays])
+AC_CACHE_VAL(gp_cv_cxx_dynamic_array, [
AC_LANG_SAVE()
AC_LANG_CPLUSPLUS()
-AC_TRY_COMPILE([#include <stdlib.h>
-void operator delete (void* ptr) throw() {}], [],
-gp_cv_cxx_throw_decl=yes, gp_cv_cxx_throw_decl=no)
+AC_TRY_COMPILE([int func (int n) { int dynamic_array[n]; }], [],
+gp_cv_cxx_dynamic_array=yes, gp_cv_cxx_dynamic_array=no)
AC_LANG_RESTORE()
])
-AC_MSG_RESULT([$]gp_cv_cxx_throw_decl)
-if test [$]gp_cv_cxx_throw_decl = yes; then
- AC_DEFINE(HAVE_THROW_DECL)
+AC_MSG_RESULT($gp_cv_cxx_dynamic_array)
+if test $gp_cv_cxx_dynamic_array = yes; then
+ AC_DEFINE(HAVE_DYNAMIC_ARRAY, 1,
+ [Define if the C++ compiler supports stack-allocated variable-size arrays.])
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 checks for libraries
+dnl
+AC_CHECK_LIB(m, rand, GPERF_LIBM="-lm", GPERF_LIBM="")
+AC_SUBST(GPERF_LIBM)
dnl
dnl That's it.
dnl
diff --git a/contrib/gperf/src/gen-perf.cc b/contrib/gperf/src/gen-perf.cc
deleted file mode 100644
index 7cf9f06..0000000
--- a/contrib/gperf/src/gen-perf.cc
+++ /dev/null
@@ -1,359 +0,0 @@
-/* Provides high-level routines to manipulate the keywork list
- structures the code generation output.
- Copyright (C) 1989-1998, 2000 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, int size_1, const char *set_2, int size_2, char *set_3)
-{
- T (Trace t ("Gen_Perf::compute_disjoint_union");)
- char *base = set_3;
-
- while (size_1 > 0 && size_2 > 0)
- if (*set_1 == *set_2)
- set_1++, size_1--, set_2++, size_2--;
- else
- {
- char next;
- if (*set_1 < *set_2)
- next = *set_1++, size_1--;
- else
- next = *set_2++, size_2--;
- if (set_3 == base || next != set_3[-1])
- *set_3++ = next;
- }
-
- while (size_1 > 0)
- {
- char next;
- next = *set_1++, size_1--;
- if (set_3 == base || next != set_3[-1])
- *set_3++ = next;
- }
-
- while (size_2 > 0)
- {
- char next;
- next = *set_2++, size_2--;
- if (set_3 == base || next != set_3[-1])
- *set_3++ = next;
- }
- 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->key_length;
-
- const char *p = key_node->char_set;
- int i = key_node->char_set_length;
- for (; i > 0; p++, i--)
- sum += asso_values[(unsigned char)(*p)];
-
- 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;
- int union_set_length;
-
- if (!union_set)
- union_set = new char [2 * option.get_max_keysig_size ()];
-
- if (option[DEBUG])
- {
- fprintf (stderr, "collision on keyword #%d, prior = \"%.*s\", curr = \"%.*s\" hash = %d\n",
- num_done,
- prior->key_length, prior->key,
- curr->key_length, curr->key,
- curr->hash_value);
- fflush (stderr);
- }
- union_set_length = compute_disjoint_union (prior->char_set, prior->char_set_length, curr->char_set, curr->char_set_length, union_set);
- sort_set (union_set, union_set_length);
-
- /* Try changing some values, if change doesn't alter other values continue normal action. */
- fewest_collisions++;
-
- const char *p = union_set;
- int i = union_set_length;
- for (; i > 0; p++, i--)
- if (!affects_prev (*p, curr))
- {
- if (option[DEBUG])
- {
- fprintf (stderr, " by changing asso_value['%c'] (char #%td) to %d\n",
- *p, p - union_set + 1, asso_values[(unsigned char)(*p)]);
- 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
deleted file mode 100644
index 602d160..0000000
--- a/contrib/gperf/src/gen-perf.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* 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, 2000 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, int size_1, const char *set_2, int size_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
index a147674..d98d90a 100644
--- a/contrib/gperf/src/hash-table.cc
+++ b/contrib/gperf/src/hash-table.cc
@@ -1,95 +1,167 @@
/* Hash table for checking keyword links. Implemented using double hashing.
- Copyright (C) 1989-1998, 2000 Free Software Foundation, Inc.
- written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+ Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
-This file is part of GNU GPERF.
+ 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 free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
-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.
+ 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. */
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+/* Specification. */
#include "hash-table.h"
#include <stdio.h>
#include <string.h> /* declares memset(), strcmp() */
#include <hash.h>
#include "options.h"
-#include "trace.h"
-
-/* 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, int ignore_len):
- table (table_ptr), size (s), collisions (0), ignore_length (ignore_len)
-{
- T (Trace t ("Hash_Table::Hash_Table");)
- memset ((char *) table, 0, size * sizeof (*table));
-}
-Hash_Table::~Hash_Table (void)
+/* We use a hash table with double hashing. This is the simplest kind of
+ hash table, given that we always only insert and never remove entries
+ from the hash table. */
+
+/* To make double hashing efficient, there need to be enough spare entries. */
+static const int size_factor = 10;
+
+/* We make the size of the hash table a power of 2. This allows for two
+ optimizations: It eliminates the modulo instruction, and allows for an
+ easy secondary hashing function. */
+
+/* Constructor. */
+Hash_Table::Hash_Table (unsigned int size, bool ignore_length)
+ : _ignore_length (ignore_length),
+ _collisions (0)
{
- T (Trace t ("Hash_Table::~Hash_Table");)
- if (option[DEBUG])
+ /* There need to be enough spare entries. */
+ size = size * size_factor;
+
+ /* Find smallest power of 2 that is >= size. */
+ unsigned int shift = 0;
+ if ((size >> 16) > 0)
+ {
+ size = size >> 16;
+ shift += 16;
+ }
+ if ((size >> 8) > 0)
+ {
+ size = size >> 8;
+ shift += 8;
+ }
+ if ((size >> 4) > 0)
+ {
+ size = size >> 4;
+ shift += 4;
+ }
+ if ((size >> 2) > 0)
+ {
+ size = size >> 2;
+ shift += 2;
+ }
+ if ((size >> 1) > 0)
{
- 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_length, table[i]->char_set,
- table[i]->key_length, table[i]->key);
-
- fprintf (stderr, "\nend dumping hash table\n\n");
+ size = size >> 1;
+ shift += 1;
}
+ _log_size = shift;
+ _size = 1 << shift;
+
+ /* Allocate table. */
+ _table = new KeywordExt*[_size];
+ memset (_table, 0, _size * sizeof (*_table));
}
-/* 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. */
+/* Destructor. */
+Hash_Table::~Hash_Table ()
+{
+ delete[] _table;
+}
-List_Node *
-Hash_Table::insert (List_Node *item)
+/* Print the table's contents. */
+void
+Hash_Table::dump () const
{
- T (Trace t ("Hash_Table::operator()");)
- unsigned hash_val = hashpjw (item->char_set, item->char_set_length);
- int probe = hash_val & (size - 1);
- int increment = ((hash_val ^ item->key_length) | 1) & (size - 1);
+ int field_width;
+
+ field_width = 0;
+ {
+ for (int i = _size - 1; i >= 0; i--)
+ if (_table[i])
+ if (field_width < _table[i]->_selchars_length)
+ field_width = _table[i]->_selchars_length;
+ }
+
+ 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 * static_cast<unsigned int>(sizeof (*_table)),
+ _collisions, field_width, "keysig");
+
+ for (int i = _size - 1; i >= 0; i--)
+ if (_table[i])
+ {
+ fprintf (stderr, "%8d, ", i);
+ if (field_width > _table[i]->_selchars_length)
+ fprintf (stderr, "%*s", field_width - _table[i]->_selchars_length, "");
+ for (int j = 0; j < _table[i]->_selchars_length; j++)
+ putc (_table[i]->_selchars[j], stderr);
+ fprintf (stderr, ", %.*s\n",
+ _table[i]->_allchars_length, _table[i]->_allchars);
+ }
+
+ fprintf (stderr, "\nend dumping hash table\n\n");
+}
- while (table[probe])
+/* Compares two items. */
+inline bool
+Hash_Table::equal (KeywordExt *item1, KeywordExt *item2) const
+{
+ return item1->_selchars_length == item2->_selchars_length
+ && memcmp (item1->_selchars, item2->_selchars,
+ item2->_selchars_length * sizeof (unsigned int))
+ == 0
+ && (_ignore_length
+ || item1->_allchars_length == item2->_allchars_length);
+}
+
+/* Attempts to insert ITEM in the table. If there is already an equal
+ entry in it, returns it. Otherwise inserts ITEM and returns NULL. */
+KeywordExt *
+Hash_Table::insert (KeywordExt *item)
+{
+ unsigned hash_val =
+ hashpjw (reinterpret_cast<const unsigned char *>(item->_selchars),
+ item->_selchars_length * sizeof (unsigned int));
+ unsigned int probe = hash_val & (_size - 1);
+ unsigned int increment =
+ (((hash_val >> _log_size)
+ ^ (_ignore_length ? 0 : item->_allchars_length))
+ << 1) + 1;
+ /* Note that because _size is a power of 2 and increment is odd,
+ we have gcd(increment,_size) = 1, which guarantees that we'll find
+ an empty entry during the loop. */
+
+ while (_table[probe] != NULL)
{
- if (table[probe]->char_set_length == item->char_set_length
- && memcmp (table[probe]->char_set, item->char_set, item->char_set_length) == 0
- && (ignore_length || table[probe]->key_length == item->key_length))
- return table[probe];
+ if (equal (_table[probe], item))
+ return _table[probe];
- collisions++;
- probe = (probe + increment) & (size - 1);
+ _collisions++;
+ probe = (probe + increment) & (_size - 1);
}
- table[probe] = item;
- return (List_Node *) 0;
+ _table[probe] = item;
+ return NULL;
}
diff --git a/contrib/gperf/src/hash-table.h b/contrib/gperf/src/hash-table.h
index 86438d0..d6938eb 100644
--- a/contrib/gperf/src/hash-table.h
+++ b/contrib/gperf/src/hash-table.h
@@ -2,42 +2,65 @@
/* Hash table used to check for duplicate keyword entries.
- Copyright (C) 1989-1998, 2000 Free Software Foundation, Inc.
- written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+ Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
-This file is part of GNU GPERF.
+ 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 free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
-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.
+ 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. */
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef hash_table_h
#define hash_table_h 1
-#include "list-node.h"
+#include "keyword.h"
+
+/* Hash table of KeywordExt* entries.
+ Two entries are considered equal if their _selchars are the same and
+ - if !ignore_length - if their _allchars_length are the same. */
class Hash_Table
{
+public:
+ /* Constructor.
+ size is the maximum number of entries.
+ ignore_length determines a detail in the comparison function. */
+ Hash_Table (unsigned int size, bool ignore_length);
+ /* Destructor. */
+ ~Hash_Table ();
+ /* Attempts to insert ITEM in the table. If there is already an equal
+ entry in it, returns it. Otherwise inserts ITEM and returns NULL. */
+ KeywordExt * insert (KeywordExt *item);
+ /* Print the table's contents. */
+ void dump () const;
+
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! */
- int ignore_length;
+ /* Vector of entries. */
+ KeywordExt ** _table;
+ /* Size of the vector. */
+ unsigned int _size;
+ /* log2(_size). */
+ unsigned int _log_size;
+ /* A detail of the comparison function. */
+ bool const _ignore_length;
+ /* Statistics: Number of collisions so far. */
+ unsigned int _collisions;
-public:
- Hash_Table (List_Node **t, int s, int ignore_len);
- ~Hash_Table (void);
- List_Node *insert (List_Node *item);
+ /* Compares two items. */
+ bool equal (KeywordExt *item1, KeywordExt *item2) const;
};
#endif
diff --git a/contrib/gperf/src/input.cc b/contrib/gperf/src/input.cc
new file mode 100644
index 0000000..247b5a4
--- /dev/null
+++ b/contrib/gperf/src/input.cc
@@ -0,0 +1,1005 @@
+/* Input routines.
+ Copyright (C) 1989-1998, 2002-2004 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
+
+ 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 2, 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 this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Specification. */
+#include "input.h"
+
+#include <stdio.h>
+#include <stdlib.h> /* declares exit() */
+#include <string.h> /* declares strncpy(), strchr() */
+#include <limits.h> /* defines UCHAR_MAX etc. */
+#include "options.h"
+#include "getline.h"
+
+Input::Input (FILE *stream, Keyword_Factory *keyword_factory)
+ : _stream (stream), _factory (keyword_factory)
+{
+}
+
+/* Returns a pretty representation of the input file name, for error and
+ warning messages. */
+static const char *
+pretty_input_file_name ()
+{
+ if (option.get_input_file_name ())
+ return option.get_input_file_name ();
+ else
+ return "(standard input)";
+}
+
+/* Returns true if the given line contains a "%DECL" declaration. */
+static bool
+is_declaration (const char *line, const char *line_end, unsigned int lineno,
+ const char *decl)
+{
+ /* Skip '%'. */
+ line++;
+
+ /* Skip DECL. */
+ for (const char *d = decl; *d; d++)
+ {
+ if (!(line < line_end))
+ return false;
+ if (!(*line == *d || (*d == '-' && *line == '_')))
+ return false;
+ line++;
+ }
+ if (line < line_end
+ && ((*line >= 'A' && *line <= 'Z')
+ || (*line >= 'a' && *line <= 'z')
+ || *line == '-' || *line == '_'))
+ return false;
+
+ /* OK, found DECL. */
+
+ /* Skip whitespace. */
+ while (line < line_end && (*line == ' ' || *line == '\t'))
+ line++;
+
+ /* Expect end of line. */
+ if (line < line_end && *line != '\n')
+ {
+ fprintf (stderr, "%s:%u: junk after declaration\n",
+ pretty_input_file_name (), lineno);
+ exit (1);
+ }
+
+ return true;
+}
+
+/* Tests if the given line contains a "%DECL=ARG" declaration.
+ If yes, it sets *ARGP to the argument, and returns true.
+ Otherwise, it returns false. */
+static bool
+is_declaration_with_arg (const char *line, const char *line_end,
+ unsigned int lineno,
+ const char *decl, char **argp)
+{
+ /* Skip '%'. */
+ line++;
+
+ /* Skip DECL. */
+ for (const char *d = decl; *d; d++)
+ {
+ if (!(line < line_end))
+ return false;
+ if (!(*line == *d || (*d == '-' && *line == '_')))
+ return false;
+ line++;
+ }
+ if (line < line_end
+ && ((*line >= 'A' && *line <= 'Z')
+ || (*line >= 'a' && *line <= 'z')
+ || *line == '-' || *line == '_'))
+ return false;
+
+ /* OK, found DECL. */
+
+ /* Skip '='. */
+ if (!(line < line_end && *line == '='))
+ {
+ fprintf (stderr, "%s:%u: missing argument in %%%s=ARG declaration.\n",
+ pretty_input_file_name (), lineno, decl);
+ exit (1);
+ }
+ line++;
+
+ /* The next word is the argument. */
+ char *arg = new char[line_end - line + 1];
+ char *p = arg;
+ while (line < line_end && !(*line == ' ' || *line == '\t' || *line == '\n'))
+ *p++ = *line++;
+ *p = '\0';
+
+ /* Skip whitespace. */
+ while (line < line_end && (*line == ' ' || *line == '\t'))
+ line++;
+
+ /* Expect end of line. */
+ if (line < line_end && *line != '\n')
+ {
+ fprintf (stderr, "%s:%u: junk after declaration\n",
+ pretty_input_file_name (), lineno);
+ exit (1);
+ }
+
+ *argp = arg;
+ return true;
+}
+
+/* Tests if the given line contains a "%define DECL ARG" declaration.
+ If yes, it sets *ARGP to the argument, and returns true.
+ Otherwise, it returns false. */
+static bool
+is_define_declaration (const char *line, const char *line_end,
+ unsigned int lineno,
+ const char *decl, char **argp)
+{
+ /* Skip '%'. */
+ line++;
+
+ /* Skip "define". */
+ {
+ for (const char *d = "define"; *d; d++)
+ {
+ if (!(line < line_end))
+ return false;
+ if (!(*line == *d))
+ return false;
+ line++;
+ }
+ if (!(line < line_end && (*line == ' ' || *line == '\t')))
+ return false;
+ }
+
+ /* Skip whitespace. */
+ while (line < line_end && (*line == ' ' || *line == '\t'))
+ line++;
+
+ /* Skip DECL. */
+ for (const char *d = decl; *d; d++)
+ {
+ if (!(line < line_end))
+ return false;
+ if (!(*line == *d || (*d == '-' && *line == '_')))
+ return false;
+ line++;
+ }
+ if (line < line_end
+ && ((*line >= 'A' && *line <= 'Z')
+ || (*line >= 'a' && *line <= 'z')
+ || *line == '-' || *line == '_'))
+ return false;
+
+ /* OK, found DECL. */
+
+ /* Skip whitespace. */
+ if (!(line < line_end && (*line == ' ' || *line == '\t')))
+ {
+ fprintf (stderr, "%s:%u:"
+ " missing argument in %%define %s ARG declaration.\n",
+ pretty_input_file_name (), lineno, decl);
+ exit (1);
+ }
+ do
+ line++;
+ while (line < line_end && (*line == ' ' || *line == '\t'));
+
+ /* The next word is the argument. */
+ char *arg = new char[line_end - line + 1];
+ char *p = arg;
+ while (line < line_end && !(*line == ' ' || *line == '\t' || *line == '\n'))
+ *p++ = *line++;
+ *p = '\0';
+
+ /* Skip whitespace. */
+ while (line < line_end && (*line == ' ' || *line == '\t'))
+ line++;
+
+ /* Expect end of line. */
+ if (line < line_end && *line != '\n')
+ {
+ fprintf (stderr, "%s:%u: junk after declaration\n",
+ pretty_input_file_name (), lineno);
+ exit (1);
+ }
+
+ *argp = arg;
+ return true;
+}
+
+/* Reads the entire input file. */
+void
+Input::read_input ()
+{
+ /* The input file has the following structure:
+ DECLARATIONS
+ %%
+ KEYWORDS
+ %%
+ ADDITIONAL_CODE
+ Since the DECLARATIONS and the ADDITIONAL_CODE sections are optional,
+ we have to read the entire file in the case there is only one %%
+ separator line, in order to determine whether the structure is
+ DECLARATIONS
+ %%
+ KEYWORDS
+ or
+ KEYWORDS
+ %%
+ ADDITIONAL_CODE
+ When the option -t is given or when the first section contains
+ declaration lines starting with %, we go for the first interpretation,
+ otherwise for the second interpretation. */
+
+ char *input = NULL;
+ size_t input_size = 0;
+ int input_length = get_delim (&input, &input_size, EOF, _stream);
+ if (input_length < 0)
+ {
+ if (ferror (_stream))
+ fprintf (stderr, "%s: error while reading input file\n",
+ pretty_input_file_name ());
+ else
+ fprintf (stderr, "%s: The input file is empty!\n",
+ pretty_input_file_name ());
+ exit (1);
+ }
+
+ /* We use input_end as a limit, in order to cope with NUL bytes in the
+ input. But note that one trailing NUL byte has been added after
+ input_end, for convenience. */
+ char *input_end = input + input_length;
+
+ const char *declarations;
+ const char *declarations_end;
+ const char *keywords;
+ const char *keywords_end;
+ unsigned int keywords_lineno;
+
+ /* Break up the input into the three sections. */
+ {
+ const char *separator[2] = { NULL, NULL };
+ unsigned int separator_lineno[2] = { 0, 0 };
+ int separators = 0;
+ {
+ unsigned int lineno = 1;
+ for (const char *p = input; p < input_end; )
+ {
+ if (p[0] == '%' && p[1] == '%')
+ {
+ separator[separators] = p;
+ separator_lineno[separators] = lineno;
+ if (++separators == 2)
+ break;
+ }
+ lineno++;
+ p = (const char *) memchr (p, '\n', input_end - p);
+ if (p != NULL)
+ p++;
+ else
+ p = input_end;
+ }
+ }
+
+ bool has_declarations;
+ if (separators == 1)
+ {
+ if (option[TYPE])
+ has_declarations = true;
+ else
+ {
+ has_declarations = false;
+ for (const char *p = input; p < separator[0]; )
+ {
+ if (p[0] == '%')
+ {
+ has_declarations = true;
+ break;
+ }
+ p = (const char *) memchr (p, '\n', separator[0] - p);
+ if (p != NULL)
+ p++;
+ else
+ p = separator[0];
+ }
+ }
+ }
+ else
+ has_declarations = (separators > 0);
+
+ if (has_declarations)
+ {
+ declarations = input;
+ declarations_end = separator[0];
+ /* Give a warning if the separator line is nonempty. */
+ bool nonempty_line = false;
+ const char *p;
+ for (p = declarations_end + 2; p < input_end; )
+ {
+ if (*p == '\n')
+ {
+ p++;
+ break;
+ }
+ if (!(*p == ' ' || *p == '\t'))
+ nonempty_line = true;
+ p++;
+ }
+ if (nonempty_line)
+ fprintf (stderr, "%s:%u: warning: junk after %%%% is ignored\n",
+ pretty_input_file_name (), separator_lineno[0]);
+ keywords = p;
+ keywords_lineno = separator_lineno[0] + 1;
+ }
+ else
+ {
+ declarations = NULL;
+ declarations_end = NULL;
+ keywords = input;
+ keywords_lineno = 1;
+ }
+
+ if (separators > (has_declarations ? 1 : 0))
+ {
+ keywords_end = separator[separators-1];
+ _verbatim_code = separator[separators-1] + 2;
+ _verbatim_code_end = input_end;
+ _verbatim_code_lineno = separator_lineno[separators-1];
+ }
+ else
+ {
+ keywords_end = input_end;
+ _verbatim_code = NULL;
+ _verbatim_code_end = NULL;
+ _verbatim_code_lineno = 0;
+ }
+ }
+
+ /* Parse the declarations section. */
+
+ _verbatim_declarations = NULL;
+ _verbatim_declarations_end = NULL;
+ _verbatim_declarations_lineno = 0;
+ _struct_decl = NULL;
+ _struct_decl_lineno = 0;
+ _return_type = NULL;
+ _struct_tag = NULL;
+ {
+ unsigned int lineno = 1;
+ char *struct_decl = NULL;
+ unsigned int *struct_decl_linenos = NULL;
+ unsigned int struct_decl_linecount = 0;
+ for (const char *line = declarations; line < declarations_end; )
+ {
+ const char *line_end;
+ line_end = (const char *) memchr (line, '\n', declarations_end - line);
+ if (line_end != NULL)
+ line_end++;
+ else
+ line_end = declarations_end;
+
+ if (*line == '%')
+ {
+ if (line[1] == '{')
+ {
+ /* Handle %{. */
+ if (_verbatim_declarations != NULL)
+ {
+ fprintf (stderr, "%s:%u:\n%s:%u:"
+ " only one %%{...%%} section is allowed\n",
+ pretty_input_file_name (),
+ _verbatim_declarations_lineno,
+ pretty_input_file_name (), lineno);
+ exit (1);
+ }
+ _verbatim_declarations = line + 2;
+ _verbatim_declarations_lineno = lineno;
+ }
+ else if (line[1] == '}')
+ {
+ /* Handle %}. */
+ if (_verbatim_declarations == NULL)
+ {
+ fprintf (stderr, "%s:%u:"
+ " %%} outside of %%{...%%} section\n",
+ pretty_input_file_name (), lineno);
+ exit (1);
+ }
+ if (_verbatim_declarations_end != NULL)
+ {
+ fprintf (stderr, "%s:%u:"
+ " %%{...%%} section already closed\n",
+ pretty_input_file_name (), lineno);
+ exit (1);
+ }
+ _verbatim_declarations_end = line;
+ /* Give a warning if the rest of the line is nonempty. */
+ bool nonempty_line = false;
+ const char *q;
+ for (q = line + 2; q < line_end; q++)
+ {
+ if (*q == '\n')
+ {
+ q++;
+ break;
+ }
+ if (!(*q == ' ' || *q == '\t'))
+ nonempty_line = true;
+ }
+ if (nonempty_line)
+ fprintf (stderr, "%s:%u:"
+ " warning: junk after %%} is ignored\n",
+ pretty_input_file_name (), lineno);
+ }
+ else if (_verbatim_declarations != NULL
+ && _verbatim_declarations_end == NULL)
+ {
+ fprintf (stderr, "%s:%u:"
+ " warning: %% directives are ignored"
+ " inside the %%{...%%} section\n",
+ pretty_input_file_name (), lineno);
+ }
+ else
+ {
+ char *arg;
+
+ if (is_declaration_with_arg (line, line_end, lineno,
+ "delimiters", &arg))
+ option.set_delimiters (arg);
+ else
+
+ if (is_declaration (line, line_end, lineno, "struct-type"))
+ option.set (TYPE);
+ else
+
+ if (is_declaration (line, line_end, lineno, "ignore-case"))
+ option.set (UPPERLOWER);
+ else
+
+ if (is_declaration_with_arg (line, line_end, lineno,
+ "language", &arg))
+ option.set_language (arg);
+ else
+
+ if (is_define_declaration (line, line_end, lineno,
+ "slot-name", &arg))
+ option.set_slot_name (arg);
+ else
+
+ if (is_define_declaration (line, line_end, lineno,
+ "initializer-suffix", &arg))
+ option.set_initializer_suffix (arg);
+ else
+
+ if (is_define_declaration (line, line_end, lineno,
+ "hash-function-name", &arg))
+ option.set_hash_name (arg);
+ else
+
+ if (is_define_declaration (line, line_end, lineno,
+ "lookup-function-name", &arg))
+ option.set_function_name (arg);
+ else
+
+ if (is_define_declaration (line, line_end, lineno,
+ "class-name", &arg))
+ option.set_class_name (arg);
+ else
+
+ if (is_declaration (line, line_end, lineno, "7bit"))
+ option.set (SEVENBIT);
+ else
+
+ if (is_declaration (line, line_end, lineno, "compare-lengths"))
+ option.set (LENTABLE);
+ else
+
+ if (is_declaration (line, line_end, lineno, "compare-strncmp"))
+ option.set (COMP);
+ else
+
+ if (is_declaration (line, line_end, lineno, "readonly-tables"))
+ option.set (CONST);
+ else
+
+ if (is_declaration (line, line_end, lineno, "enum"))
+ option.set (ENUM);
+ else
+
+ if (is_declaration (line, line_end, lineno, "includes"))
+ option.set (INCLUDE);
+ else
+
+ if (is_declaration (line, line_end, lineno, "global-table"))
+ option.set (GLOBAL);
+ else
+
+ if (is_declaration (line, line_end, lineno, "pic"))
+ option.set (SHAREDLIB);
+ else
+
+ if (is_define_declaration (line, line_end, lineno,
+ "string-pool-name", &arg))
+ option.set_stringpool_name (arg);
+ else
+
+ if (is_declaration (line, line_end, lineno, "null-strings"))
+ option.set (NULLSTRINGS);
+ else
+
+ if (is_define_declaration (line, line_end, lineno,
+ "word-array-name", &arg))
+ option.set_wordlist_name (arg);
+ else
+
+ if (is_define_declaration (line, line_end, lineno,
+ "length-table-name", &arg))
+ option.set_lengthtable_name (arg);
+ else
+
+ if (is_declaration_with_arg (line, line_end, lineno,
+ "switch", &arg))
+ {
+ option.set_total_switches (atoi (arg));
+ if (option.get_total_switches () <= 0)
+ {
+ fprintf (stderr, "%s:%u: number of switches %s"
+ " must be a positive number\n",
+ pretty_input_file_name (), lineno, arg);
+ exit (1);
+ }
+ }
+ else
+
+ if (is_declaration (line, line_end, lineno, "omit-struct-type"))
+ option.set (NOTYPE);
+ else
+
+ {
+ fprintf (stderr, "%s:%u: unrecognized %% directive\n",
+ pretty_input_file_name (), lineno);
+ exit (1);
+ }
+ }
+ }
+ else if (!(_verbatim_declarations != NULL
+ && _verbatim_declarations_end == NULL))
+ {
+ /* Append the line to struct_decl. */
+ size_t old_len = (struct_decl ? strlen (struct_decl) : 0);
+ size_t line_len = line_end - line;
+ size_t new_len = old_len + line_len + 1;
+ char *new_struct_decl = new char[new_len];
+ if (old_len > 0)
+ memcpy (new_struct_decl, struct_decl, old_len);
+ memcpy (new_struct_decl + old_len, line, line_len);
+ new_struct_decl[old_len + line_len] = '\0';
+ if (struct_decl)
+ delete[] struct_decl;
+ struct_decl = new_struct_decl;
+ /* Append the lineno to struct_decl_linenos. */
+ unsigned int *new_struct_decl_linenos =
+ new unsigned int[struct_decl_linecount + 1];
+ if (struct_decl_linecount > 0)
+ memcpy (new_struct_decl_linenos, struct_decl_linenos,
+ struct_decl_linecount * sizeof (unsigned int));
+ new_struct_decl_linenos[struct_decl_linecount] = lineno;
+ if (struct_decl_linenos)
+ delete[] struct_decl_linenos;
+ struct_decl_linenos = new_struct_decl_linenos;
+ /* Increment struct_decl_linecount. */
+ struct_decl_linecount++;
+ }
+ lineno++;
+ line = line_end;
+ }
+ if (_verbatim_declarations != NULL && _verbatim_declarations_end == NULL)
+ {
+ fprintf (stderr, "%s:%u: unterminated %%{ section\n",
+ pretty_input_file_name (), _verbatim_declarations_lineno);
+ exit (1);
+ }
+
+ /* Determine _struct_decl, _return_type, _struct_tag. */
+ if (option[TYPE])
+ {
+ if (struct_decl)
+ {
+ /* Drop leading whitespace and comments. */
+ {
+ char *p = struct_decl;
+ unsigned int *l = struct_decl_linenos;
+ for (;;)
+ {
+ if (p[0] == ' ' || p[0] == '\t')
+ {
+ p++;
+ continue;
+ }
+ if (p[0] == '\n')
+ {
+ l++;
+ p++;
+ continue;
+ }
+ if (p[0] == '/')
+ {
+ if (p[1] == '*')
+ {
+ /* Skip over ANSI C style comment. */
+ p += 2;
+ while (p[0] != '\0')
+ {
+ if (p[0] == '*' && p[1] == '/')
+ {
+ p += 2;
+ break;
+ }
+ if (p[0] == '\n')
+ l++;
+ p++;
+ }
+ continue;
+ }
+ if (p[1] == '/')
+ {
+ /* Skip over ISO C99 or C++ style comment. */
+ p += 2;
+ while (p[0] != '\0' && p[0] != '\n')
+ p++;
+ if (p[0] == '\n')
+ {
+ l++;
+ p++;
+ }
+ continue;
+ }
+ }
+ break;
+ }
+ if (p != struct_decl)
+ {
+ size_t len = strlen (p);
+ char *new_struct_decl = new char[len + 1];
+ memcpy (new_struct_decl, p, len + 1);
+ delete[] struct_decl;
+ struct_decl = new_struct_decl;
+ }
+ _struct_decl_lineno = *l;
+ }
+ /* Drop trailing whitespace. */
+ for (char *p = struct_decl + strlen (struct_decl); p > struct_decl;)
+ if (p[-1] == '\n' || p[-1] == ' ' || p[-1] == '\t')
+ *--p = '\0';
+ else
+ break;
+ }
+ if (struct_decl == NULL || struct_decl[0] == '\0')
+ {
+ fprintf (stderr, "%s: missing struct declaration"
+ " for option --struct-type\n",
+ pretty_input_file_name ());
+ exit (1);
+ }
+ {
+ /* Ensure trailing semicolon. */
+ size_t old_len = strlen (struct_decl);
+ if (struct_decl[old_len - 1] != ';')
+ {
+ char *new_struct_decl = new char[old_len + 2];
+ memcpy (new_struct_decl, struct_decl, old_len);
+ new_struct_decl[old_len] = ';';
+ new_struct_decl[old_len + 1] = '\0';
+ delete[] struct_decl;
+ struct_decl = new_struct_decl;
+ }
+ }
+ /* Set _struct_decl to the entire declaration. */
+ _struct_decl = struct_decl;
+ /* Set _struct_tag to the naked "struct something". */
+ const char *p;
+ for (p = struct_decl; *p && *p != '{' && *p != ';' && *p != '\n'; p++)
+ ;
+ for (; p > struct_decl;)
+ if (p[-1] == '\n' || p[-1] == ' ' || p[-1] == '\t')
+ --p;
+ else
+ break;
+ size_t struct_tag_length = p - struct_decl;
+ char *struct_tag = new char[struct_tag_length + 1];
+ memcpy (struct_tag, struct_decl, struct_tag_length);
+ struct_tag[struct_tag_length] = '\0';
+ _struct_tag = struct_tag;
+ /* 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 *return_type = new char[struct_tag_length + 3];
+ memcpy (return_type, struct_decl, struct_tag_length);
+ return_type[struct_tag_length] = ' ';
+ return_type[struct_tag_length + 1] = '*';
+ return_type[struct_tag_length + 2] = '\0';
+ _return_type = return_type;
+ }
+
+ if (struct_decl_linenos)
+ delete[] struct_decl_linenos;
+ }
+
+ /* Parse the keywords section. */
+ {
+ Keyword_List **list_tail = &_head;
+ const char *delimiters = option.get_delimiters ();
+ unsigned int lineno = keywords_lineno;
+ bool charset_dependent = false;
+ for (const char *line = keywords; line < keywords_end; )
+ {
+ const char *line_end;
+ line_end = (const char *) memchr (line, '\n', keywords_end - line);
+ if (line_end != NULL)
+ line_end++;
+ else
+ line_end = keywords_end;
+
+ if (line[0] == '#')
+ ; /* Comment line. */
+ else if (line[0] == '%')
+ {
+ fprintf (stderr, "%s:%u:"
+ " declarations are not allowed in the keywords section.\n"
+ "To declare a keyword starting with %%, enclose it in"
+ " double-quotes.\n",
+ pretty_input_file_name (), lineno);
+ exit (1);
+ }
+ else
+ {
+ /* An input line carrying a keyword. */
+ const char *keyword;
+ size_t keyword_length;
+ const char *rest;
+
+ if (line[0] == '"')
+ {
+ /* Parse a string in ANSI C syntax. */
+ char *kp = new char[line_end-line];
+ keyword = kp;
+ const char *lp = line + 1;
+
+ for (;;)
+ {
+ if (lp == line_end)
+ {
+ fprintf (stderr, "%s:%u: unterminated string\n",
+ pretty_input_file_name (), lineno);
+ exit (1);
+ }
+
+ char c = *lp;
+ if (c == '\\')
+ {
+ c = *++lp;
+ switch (c)
+ {
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ {
+ int code = 0;
+ int count = 0;
+ while (count < 3 && *lp >= '0' && *lp <= '7')
+ {
+ code = (code << 3) + (*lp - '0');
+ lp++;
+ count++;
+ }
+ if (code > UCHAR_MAX)
+ fprintf (stderr,
+ "%s:%u: octal escape out of range\n",
+ pretty_input_file_name (), lineno);
+ *kp = static_cast<char>(code);
+ break;
+ }
+ case 'x':
+ {
+ int code = 0;
+ int count = 0;
+ lp++;
+ while ((*lp >= '0' && *lp <= '9')
+ || (*lp >= 'A' && *lp <= 'F')
+ || (*lp >= 'a' && *lp <= 'f'))
+ {
+ code = (code << 4)
+ + (*lp >= 'A' && *lp <= 'F'
+ ? *lp - 'A' + 10 :
+ *lp >= 'a' && *lp <= 'f'
+ ? *lp - 'a' + 10 :
+ *lp - '0');
+ lp++;
+ count++;
+ }
+ if (count == 0)
+ fprintf (stderr, "%s:%u: hexadecimal escape"
+ " without any hex digits\n",
+ pretty_input_file_name (), lineno);
+ if (code > UCHAR_MAX)
+ fprintf (stderr, "%s:%u: hexadecimal escape"
+ " out of range\n",
+ pretty_input_file_name (), lineno);
+ *kp = static_cast<char>(code);
+ break;
+ }
+ case '\\': case '\'': case '"':
+ *kp = c;
+ lp++;
+ charset_dependent = true;
+ break;
+ case 'n':
+ *kp = '\n';
+ lp++;
+ charset_dependent = true;
+ break;
+ case 't':
+ *kp = '\t';
+ lp++;
+ charset_dependent = true;
+ break;
+ case 'r':
+ *kp = '\r';
+ lp++;
+ charset_dependent = true;
+ break;
+ case 'f':
+ *kp = '\f';
+ lp++;
+ charset_dependent = true;
+ break;
+ case 'b':
+ *kp = '\b';
+ lp++;
+ charset_dependent = true;
+ break;
+ case 'a':
+ *kp = '\a';
+ lp++;
+ charset_dependent = true;
+ break;
+ case 'v':
+ *kp = '\v';
+ lp++;
+ charset_dependent = true;
+ break;
+ default:
+ fprintf (stderr, "%s:%u: invalid escape sequence"
+ " in string\n",
+ pretty_input_file_name (), lineno);
+ exit (1);
+ }
+ }
+ else if (c == '"')
+ break;
+ else
+ {
+ *kp = c;
+ lp++;
+ charset_dependent = true;
+ }
+ kp++;
+ }
+ lp++;
+ if (lp < line_end && *lp != '\n')
+ {
+ if (strchr (delimiters, *lp) == NULL)
+ {
+ fprintf (stderr, "%s:%u: string not followed"
+ " by delimiter\n",
+ pretty_input_file_name (), lineno);
+ exit (1);
+ }
+ lp++;
+ }
+ keyword_length = kp - keyword;
+ if (option[TYPE])
+ {
+ char *line_rest = new char[line_end - lp + 1];
+ memcpy (line_rest, lp, line_end - lp);
+ line_rest[line_end - lp -
+ (line_end > lp && line_end[-1] == '\n' ? 1 : 0)]
+ = '\0';
+ rest = line_rest;
+ }
+ else
+ rest = empty_string;
+ }
+ else
+ {
+ /* Not a string. Look for the delimiter. */
+ const char *lp = line;
+ for (;;)
+ {
+ if (!(lp < line_end && *lp != '\n'))
+ {
+ keyword = line;
+ keyword_length = lp - line;
+ rest = empty_string;
+ break;
+ }
+ if (strchr (delimiters, *lp) != NULL)
+ {
+ keyword = line;
+ keyword_length = lp - line;
+ lp++;
+ if (option[TYPE])
+ {
+ char *line_rest = new char[line_end - lp + 1];
+ memcpy (line_rest, lp, line_end - lp);
+ line_rest[line_end - lp -
+ (line_end > lp && line_end[-1] == '\n'
+ ? 1 : 0)]
+ = '\0';
+ rest = line_rest;
+ }
+ else
+ rest = empty_string;
+ break;
+ }
+ lp++;
+ }
+ if (keyword_length > 0)
+ charset_dependent = true;
+ }
+
+ /* Allocate Keyword and add it to the list. */
+ Keyword *new_kw = _factory->create_keyword (keyword, keyword_length,
+ rest);
+ new_kw->_lineno = lineno;
+ *list_tail = new Keyword_List (new_kw);
+ list_tail = &(*list_tail)->rest();
+ }
+
+ lineno++;
+ line = line_end;
+ }
+ *list_tail = NULL;
+
+ if (_head == NULL)
+ {
+ fprintf (stderr, "%s: No keywords in input file!\n",
+ pretty_input_file_name ());
+ exit (1);
+ }
+
+ _charset_dependent = charset_dependent;
+ }
+
+ /* To be freed in the destructor. */
+ _input = input;
+ _input_end = input_end;
+}
+
+Input::~Input ()
+{
+ /* Free allocated memory. */
+ delete[] const_cast<char*>(_return_type);
+ delete[] const_cast<char*>(_struct_tag);
+ delete[] const_cast<char*>(_struct_decl);
+ delete[] _input;
+}
diff --git a/contrib/gperf/src/input.h b/contrib/gperf/src/input.h
new file mode 100644
index 0000000..76ba012
--- /dev/null
+++ b/contrib/gperf/src/input.h
@@ -0,0 +1,69 @@
+/* This may look like C code, but it is really -*- C++ -*- */
+
+/* Input routines.
+
+ Copyright (C) 1989-1998, 2002-2003 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
+
+ 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 2, 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 this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef input_h
+#define input_h 1
+
+#include <stdio.h>
+#include "keyword-list.h"
+
+class Input
+{
+public:
+ Input (FILE *stream, Keyword_Factory *keyword_factory);
+ ~Input ();
+ void read_input ();
+private:
+ /* Input stream. */
+ FILE * _stream;
+ /* Creates the keywords. */
+ Keyword_Factory * const _factory;
+public:
+ /* Memory block containing the entire input. */
+ char * _input;
+ char * _input_end;
+ /* The C code from the declarations section. */
+ const char * _verbatim_declarations;
+ const char * _verbatim_declarations_end;
+ unsigned int _verbatim_declarations_lineno;
+ /* The C code from the end of the file. */
+ const char * _verbatim_code;
+ const char * _verbatim_code_end;
+ unsigned int _verbatim_code_lineno;
+ /* Declaration of struct type for a keyword and its attributes. */
+ const char * _struct_decl;
+ unsigned int _struct_decl_lineno;
+ /* Return type of the lookup function. */
+ const char * _return_type;
+ /* Shorthand for user-defined struct tag type. */
+ const char * _struct_tag;
+ /* List of all keywords. */
+ Keyword_List * _head;
+ /* Whether the keyword chars would have different values in a different
+ character set. */
+ bool _charset_dependent;
+};
+
+#endif
diff --git a/contrib/gperf/src/iterator.cc b/contrib/gperf/src/iterator.cc
deleted file mode 100644
index ca66bbb..0000000
--- a/contrib/gperf/src/iterator.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-/* Provides an Iterator for keyword characters.
- Copyright (C) 1989-1998, 2000 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 <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
deleted file mode 100644
index d5138ab..0000000
--- a/contrib/gperf/src/iterator.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* This may look like C code, but it is really -*- C++ -*- */
-
-/* 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-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.
- This is used to decode the user's key position requests. For example:
- "-k 1,2,5-10,$" will return 1, 2, 5, 6, 7, 8, 9, 10, and 0 ( representing
- the abstract ``last character of the key'' on successive calls to the
- member function operator ().
- 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 1
-
-class Iterator
-{
-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. */
-
-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
deleted file mode 100644
index 11292bc..0000000
--- a/contrib/gperf/src/key-list.cc
+++ /dev/null
@@ -1,2182 +0,0 @@
-/* Routines for building, ordering, and printing the keyword list.
- Copyright (C) 1989-1998, 2000 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 <ctype.h> /* declares isprint() */
-#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;
- }
-}
-
-/* Extracts a key from an input line and creates a new List_Node for it. */
-
-static List_Node *
-parse_line (const char *line, const char *delimiters)
-{
- if (*line == '"')
- {
- /* Parse a string in ANSI C syntax. */
- char *key = new char[strlen(line)];
- char *kp = key;
- const char *lp = line + 1;
-
- for (; *lp;)
- {
- char c = *lp;
-
- if (c == '\0')
- {
- fprintf (stderr, "unterminated string: %s\n", line);
- exit (1);
- }
- else if (c == '\\')
- {
- c = *++lp;
- switch (c)
- {
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- {
- int code = 0;
- int count = 0;
- while (count < 3 && *lp >= '0' && *lp <= '7')
- {
- code = (code << 3) + (*lp - '0');
- lp++;
- count++;
- }
- if (code > UCHAR_MAX)
- fprintf (stderr, "octal escape out of range: %s\n", line);
- *kp = (char) code;
- break;
- }
- case 'x':
- {
- int code = 0;
- int count = 0;
- lp++;
- while ((*lp >= '0' && *lp <= '9')
- || (*lp >= 'A' && *lp <= 'F')
- || (*lp >= 'a' && *lp <= 'f'))
- {
- code = (code << 4)
- + (*lp >= 'A' && *lp <= 'F' ? *lp - 'A' + 10 :
- *lp >= 'a' && *lp <= 'f' ? *lp - 'a' + 10 :
- *lp - '0');
- lp++;
- count++;
- }
- if (count == 0)
- fprintf (stderr, "hexadecimal escape without any hex digits: %s\n", line);
- if (code > UCHAR_MAX)
- fprintf (stderr, "hexadecimal escape out of range: %s\n", line);
- *kp = (char) code;
- break;
- }
- case '\\': case '\'': case '"':
- *kp = c;
- lp++;
- break;
- case 'n':
- *kp = '\n';
- lp++;
- break;
- case 't':
- *kp = '\t';
- lp++;
- break;
- case 'r':
- *kp = '\r';
- lp++;
- break;
- case 'f':
- *kp = '\f';
- lp++;
- break;
- case 'b':
- *kp = '\b';
- lp++;
- break;
- case 'a':
- *kp = '\a';
- lp++;
- break;
- case 'v':
- *kp = '\v';
- lp++;
- break;
- default:
- fprintf (stderr, "invalid escape sequence in string: %s\n", line);
- exit (1);
- }
- }
- else if (c == '"')
- break;
- else
- {
- *kp = c;
- lp++;
- }
- kp++;
- }
- lp++;
- if (*lp != '\0')
- {
- if (strchr (delimiters, *lp) == NULL)
- {
- fprintf (stderr, "string not followed by delimiter: %s\n", line);
- exit (1);
- }
- lp++;
- }
- return new List_Node (key, kp - key, option[TYPE] ? lp : "");
- }
- else
- {
- /* Not a string. Look for the delimiter. */
- int len = strcspn (line, delimiters);
- const char *rest;
-
- if (line[len] == '\0')
- rest = "";
- else
- /* Skip the first delimiter. */
- rest = &line[len + 1];
- return new List_Node (line, len, option[TYPE] ? rest : "");
- }
-}
-
-/* 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 = parse_line (ptr, delimiter);
-
- for (temp = head;
- (ptr = Read_Line::get_line ()) && strcmp (ptr, "%%");
- temp = temp->next)
- {
- temp->next = parse_line (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, option[NOLENGTH]);
-
- /* 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.insert (temp);
-
- /* 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_length, temp->key,
- ptr->key_length, ptr->key,
- temp->char_set_length, temp->char_set);
- }
- else
- trail = temp;
-
- /* Update minimum and maximum keyword length, if needed. */
- if (max_key_len < temp->key_length)
- max_key_len = temp->key_length;
- if (min_key_len > temp->key_length)
- min_key_len = temp->key_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);
- }
- }
- /* Exit program if an empty string is used as key, since the comparison
- expressions don't work correctly for looking up an empty string. */
- if (min_key_len == 0)
- {
- fprintf (stderr, "Empty input key is not allowed.\nTo recognize an empty input key, your code should check for\nlen == 0 before calling the gperf generated lookup function.\n");
- 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;
-
- const char *p = ptr->char_set;
- unsigned int i = ptr->char_set_length;
- for (; i > 0; p++, i--)
- value += occurrences[(unsigned char)(*p)];
-
- 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");)
-
- const char *p = ptr->char_set;
- unsigned int i = ptr->char_set_length;
- for (; i > 0; p++, i--)
- determined[(unsigned char)(*p)] = 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;
-
- const char *p = ptr->char_set;
- unsigned int i = ptr->char_set_length;
- for (; is_determined && i > 0; p++, i--)
- is_determined = determined[(unsigned char)(*p)];
-
- 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, double quote and unprintable characters. */
-
-static void
-output_string (const char *key, int len)
-{
- T (Trace t ("output_string");)
-
- putchar ('"');
- for (; len > 0; len--)
- {
- unsigned char c = (unsigned char) *key++;
- if (isprint (c))
- {
- if (c == '"' || c == '\\')
- putchar ('\\');
- putchar (c);
- }
- else
- {
- /* Use octal escapes, not hexadecimal escapes, because some old
- C compilers didn't understand hexadecimal escapes, and because
- hexadecimal escapes are not limited to 2 digits, thus needing
- special care if the following character happens to be a digit. */
- putchar ('\\');
- putchar ('0' + ((c >> 6) & 7));
- putchar ('0' + ((c >> 3) & 7));
- putchar ('0' + (c & 7));
- }
- }
- 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) && ");
- expr2.output_expr ();
- printf ("[len] == '\\0'");
-}
-
-/* This class outputs a comparison using memcmp.
- Note that the length of expr1 (available through the local variable `len')
- must be verified to be equal to the length of expr2 prior to this
- comparison. */
-
-struct Output_Compare_Memcmp : public Output_Compare
-{
- virtual void output_comparison (const Output_Expr& expr1,
- const Output_Expr& expr2) const;
- Output_Compare_Memcmp () {}
- virtual ~Output_Compare_Memcmp () {}
-};
-
-void Output_Compare_Memcmp::output_comparison (const Output_Expr& expr1,
- const Output_Expr& expr2) const
-{
- T (Trace t ("Output_Compare_Memcmp::output_comparison");)
- printf ("*");
- expr1.output_expr ();
- printf (" == *");
- expr2.output_expr ();
- printf (" && !memcmp (");
- 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"
- "#else\n"
- "#ifdef __cplusplus\n"
- "inline\n"
- "#endif\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 ());
- if (option[KRC] || option[C] || option [ANSIC] || option[CPLUSPLUS])
- 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" :
- "(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->key_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->key_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, temp->key_length);
- if (option[TYPE])
- {
- if (strlen (temp->rest) > 0)
- printf (",%s", temp->rest);
- printf ("}");
- }
- 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)
-{
- int columns;
- if (option[TYPE])
- {
- columns = 58 / (6 + strlen (option.get_initializer_suffix()));
- if (columns == 0)
- columns = 1;
- }
- else
- {
- 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 ("{\"\"%s}", option.get_initializer_suffix());
- 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_length, 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_length, 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_length, temp->key, temp->index);
- }
- assert (dup_ptr->count >= 2);
- dup_ptr++;
- }
- }
-
- while (dup_ptr > duplicates)
- {
- dup_ptr--;
-
- if (option[DEBUG])
- fprintf (stderr,
- "dup_ptr[%td]: 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_length, 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->key_length,
- indent, "");
- indent += 4;
- }
- printf ("%*sresword = ",
- indent, "");
- if (option[TYPE])
- printf ("&%s[%d]", option.get_wordlist_name (), list->index);
- else
- output_string (list->key, list->key_length);
- 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, "");
- }
- if (total_duplicates > 0)
- {
- 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",
- indent, "", indent, "", indent, "");
- }
- printf ("%*s}\n",
- 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 ());
- if (option[KRC] || option[C] || option[ANSIC] || option[CPLUSPLUS])
- 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" :
- "(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[LENTABLE])
- output_lookup_function_body (Output_Compare_Memcmp ());
- else
- {
- 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->key_length, ptr->index,
- field_width, ptr->char_set_length, ptr->char_set,
- ptr->key_length, 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
deleted file mode 100644
index 98b8fa5..0000000
--- a/contrib/gperf/src/key-list.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* 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/keyword-list.cc b/contrib/gperf/src/keyword-list.cc
new file mode 100644
index 0000000..ac559f7
--- /dev/null
+++ b/contrib/gperf/src/keyword-list.cc
@@ -0,0 +1,175 @@
+/* Keyword list.
+
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>.
+
+ 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 2, 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 this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Specification. */
+#include "keyword-list.h"
+
+#include <stddef.h>
+
+/* -------------------------- Keyword_List class --------------------------- */
+
+/* Constructor. */
+Keyword_List::Keyword_List (Keyword *car)
+ : _cdr (NULL), _car (car)
+{
+}
+
+/* ------------------------- KeywordExt_List class ------------------------- */
+
+/* Constructor. */
+KeywordExt_List::KeywordExt_List (KeywordExt *car)
+ : Keyword_List (car)
+{
+}
+
+/* ------------------------ Keyword_List functions ------------------------- */
+
+/* Copies a linear list, sharing the list elements. */
+Keyword_List *
+copy_list (Keyword_List *list)
+{
+ Keyword_List *result;
+ Keyword_List **lastp = &result;
+ while (list != NULL)
+ {
+ Keyword_List *new_cons = new Keyword_List (list->first());
+ *lastp = new_cons;
+ lastp = &new_cons->rest();
+ list = list->rest();
+ }
+ *lastp = NULL;
+ return result;
+}
+
+/* Copies a linear list, sharing the list elements. */
+KeywordExt_List *
+copy_list (KeywordExt_List *list)
+{
+ return static_cast<KeywordExt_List *> (copy_list (static_cast<Keyword_List *> (list)));
+}
+
+/* Deletes a linear list, keeping the list elements in memory. */
+void
+delete_list (Keyword_List *list)
+{
+ while (list != NULL)
+ {
+ Keyword_List *rest = list->rest();
+ delete list;
+ list = rest;
+ }
+}
+
+/* Type of a comparison function. */
+typedef bool (*Keyword_Comparison) (Keyword *keyword1, Keyword *keyword2);
+
+/* Merges two sorted lists together to form one sorted list. */
+static Keyword_List *
+merge (Keyword_List *list1, Keyword_List *list2, Keyword_Comparison less)
+{
+ Keyword_List *result;
+ Keyword_List **resultp = &result;
+ for (;;)
+ {
+ if (!list1)
+ {
+ *resultp = list2;
+ break;
+ }
+ if (!list2)
+ {
+ *resultp = list1;
+ break;
+ }
+ if (less (list2->first(), list1->first()))
+ {
+ *resultp = list2;
+ resultp = &list2->rest();
+ /* We would have a stable sorting if the next line would read:
+ list2 = *resultp; */
+ list2 = list1; list1 = *resultp;
+ }
+ else
+ {
+ *resultp = list1;
+ resultp = &list1->rest();
+ list1 = *resultp;
+ }
+ }
+ return result;
+}
+
+/* Sorts a linear list, given a comparison function.
+ Note: This uses a variant of mergesort that is *not* a stable sorting
+ algorithm. */
+Keyword_List *
+mergesort_list (Keyword_List *list, Keyword_Comparison less)
+{
+ if (list == NULL || list->rest() == NULL)
+ /* List of length 0 or 1. Nothing to do. */
+ return list;
+ else
+ {
+ /* Determine a list node in the middle. */
+ Keyword_List *middle = list;
+ for (Keyword_List *temp = list->rest();;)
+ {
+ temp = temp->rest();
+ if (temp == NULL)
+ break;
+ temp = temp->rest();
+ middle = middle->rest();
+ if (temp == NULL)
+ break;
+ }
+
+ /* Cut the list into two halves.
+ If the list has n elements, the left half has ceiling(n/2) elements
+ and the right half has floor(n/2) elements. */
+ Keyword_List *right_half = middle->rest();
+ middle->rest() = NULL;
+
+ /* Sort the two halves, then merge them. */
+ return merge (mergesort_list (list, less),
+ mergesort_list (right_half, less),
+ less);
+ }
+}
+
+KeywordExt_List *
+mergesort_list (KeywordExt_List *list,
+ bool (*less) (KeywordExt *keyword1, KeywordExt *keyword2))
+{
+ return
+ static_cast<KeywordExt_List *>
+ (mergesort_list (static_cast<Keyword_List *> (list),
+ reinterpret_cast<Keyword_Comparison> (less)));
+}
+
+
+#ifndef __OPTIMIZE__
+
+#define INLINE /* not inline */
+#include "keyword-list.icc"
+#undef INLINE
+
+#endif /* not defined __OPTIMIZE__ */
diff --git a/contrib/gperf/src/keyword-list.h b/contrib/gperf/src/keyword-list.h
new file mode 100644
index 0000000..a15b3b4
--- /dev/null
+++ b/contrib/gperf/src/keyword-list.h
@@ -0,0 +1,85 @@
+/* This may look like C code, but it is really -*- C++ -*- */
+
+/* Keyword list.
+
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>.
+
+ 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 2, 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 this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef keyword_list_h
+#define keyword_list_h 1
+
+#include "keyword.h"
+
+/* List node of a linear list of Keyword. */
+class Keyword_List
+{
+public:
+ /* Constructor. */
+ Keyword_List (Keyword *car);
+
+ /* Access to first element of list. */
+ Keyword * first () const;
+ /* Access to next element of list. */
+ Keyword_List *& rest ();
+
+protected:
+ Keyword_List * _cdr;
+ Keyword * const _car;
+};
+
+/* List node of a linear list of KeywordExt. */
+class KeywordExt_List : public Keyword_List
+{
+public:
+ /* Constructor. */
+ KeywordExt_List (KeywordExt *car);
+
+ /* Access to first element of list. */
+ KeywordExt * first () const;
+ /* Access to next element of list. */
+ KeywordExt_List *& rest ();
+};
+
+/* Copies a linear list, sharing the list elements. */
+extern Keyword_List * copy_list (Keyword_List *list);
+extern KeywordExt_List * copy_list (KeywordExt_List *list);
+
+/* Deletes a linear list, keeping the list elements in memory. */
+extern void delete_list (Keyword_List *list);
+
+/* Sorts a linear list, given a comparison function.
+ Note: This uses a variant of mergesort that is *not* a stable sorting
+ algorithm. */
+extern Keyword_List * mergesort_list (Keyword_List *list,
+ bool (*less) (Keyword *keyword1,
+ Keyword *keyword2));
+extern KeywordExt_List * mergesort_list (KeywordExt_List *list,
+ bool (*less) (KeywordExt *keyword1,
+ KeywordExt *keyword2));
+
+#ifdef __OPTIMIZE__
+
+#define INLINE inline
+#include "keyword-list.icc"
+#undef INLINE
+
+#endif
+
+#endif
diff --git a/contrib/gperf/src/keyword-list.icc b/contrib/gperf/src/keyword-list.icc
new file mode 100644
index 0000000..7fbdaac
--- /dev/null
+++ b/contrib/gperf/src/keyword-list.icc
@@ -0,0 +1,53 @@
+/* Inline Functions for keyword-list.{h,cc}.
+
+ Copyright (C) 2002-2003 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>.
+
+ 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 2, 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 this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* -------------------------- Keyword_List class --------------------------- */
+
+/* Access to first element of list. */
+INLINE Keyword *
+Keyword_List::first () const
+{
+ return _car;
+}
+
+/* Access to next element of list. */
+INLINE Keyword_List *&
+Keyword_List::rest ()
+{
+ return _cdr;
+}
+
+/* ------------------------- KeywordExt_List class ------------------------- */
+
+/* Access to first element of list. */
+INLINE KeywordExt *
+KeywordExt_List::first () const
+{
+ return static_cast<KeywordExt*>(_car);
+}
+
+/* Access to next element of list. */
+INLINE KeywordExt_List *&
+KeywordExt_List::rest ()
+{
+ return *reinterpret_cast<KeywordExt_List**>(&_cdr);
+}
diff --git a/contrib/gperf/src/keyword.cc b/contrib/gperf/src/keyword.cc
new file mode 100644
index 0000000..ae53bcc
--- /dev/null
+++ b/contrib/gperf/src/keyword.cc
@@ -0,0 +1,161 @@
+/* Keyword data.
+ Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
+
+ 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 2, 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 this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Specification. */
+#include "keyword.h"
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "positions.h"
+
+
+/* --------------------------- KeywordExt class --------------------------- */
+
+/* Sort a small set of 'unsigned int', base[0..len-1], in place. */
+static inline void sort_char_set (unsigned int *base, int len)
+{
+ /* Bubble sort is sufficient here. */
+ for (int i = 1; i < len; i++)
+ {
+ int j;
+ unsigned int tmp;
+
+ for (j = i, tmp = base[j]; j > 0 && tmp < base[j - 1]; j--)
+ base[j] = base[j - 1];
+
+ base[j] = tmp;
+ }
+}
+
+/* Initializes selchars and selchars_length.
+
+ General idea:
+ The hash function will be computed as
+ asso_values[allchars[key_pos[0]]] +
+ asso_values[allchars[key_pos[1]]] + ...
+ We compute selchars as the multiset
+ { allchars[key_pos[0]], allchars[key_pos[1]], ... }
+ so that the hash function becomes
+ asso_values[selchars[0]] + asso_values[selchars[1]] + ...
+ Furthermore we sort the selchars array, to ease detection of duplicates
+ later.
+
+ More in detail: The arguments alpha_unify (used for case-insensitive
+ hash functions) and alpha_inc (used to disambiguate permutations)
+ apply slight modifications. The hash function will be computed as
+ sum (j=0,1,...: k = key_pos[j]:
+ asso_values[alpha_unify[allchars[k]+alpha_inc[k]]])
+ + (allchars_length if !option[NOLENGTH], 0 otherwise).
+ We compute selchars as the multiset
+ { alpha_unify[allchars[k]+alpha_inc[k]] : j=0,1,..., k = key_pos[j] }
+ so that the hash function becomes
+ asso_values[selchars[0]] + asso_values[selchars[1]] + ...
+ + (allchars_length if !option[NOLENGTH], 0 otherwise).
+ */
+
+unsigned int *
+KeywordExt::init_selchars_low (const Positions& positions, const unsigned int *alpha_unify, const unsigned int *alpha_inc)
+{
+ /* Iterate through the list of positions, initializing selchars
+ (via ptr). */
+ PositionIterator iter = positions.iterator(_allchars_length);
+
+ unsigned int *key_set = new unsigned int[iter.remaining()];
+ unsigned int *ptr = key_set;
+
+ for (int i; (i = iter.next ()) != PositionIterator::EOS; )
+ {
+ unsigned int c;
+ if (i == Positions::LASTCHAR)
+ /* Special notation for last KEY position, i.e. '$'. */
+ c = static_cast<unsigned char>(_allchars[_allchars_length - 1]);
+ else if (i < _allchars_length)
+ {
+ /* Within range of KEY length, so we'll keep it. */
+ c = static_cast<unsigned char>(_allchars[i]);
+ if (alpha_inc)
+ c += alpha_inc[i];
+ }
+ else
+ /* Out of range of KEY length, the iterator should not have
+ produced this. */
+ abort ();
+ if (alpha_unify)
+ c = alpha_unify[c];
+ *ptr = c;
+ ptr++;
+ }
+
+ _selchars = key_set;
+ _selchars_length = ptr - key_set;
+
+ return key_set;
+}
+
+void
+KeywordExt::init_selchars_tuple (const Positions& positions, const unsigned int *alpha_unify)
+{
+ init_selchars_low (positions, alpha_unify, NULL);
+}
+
+void
+KeywordExt::init_selchars_multiset (const Positions& positions, const unsigned int *alpha_unify, const unsigned int *alpha_inc)
+{
+ unsigned int *selchars =
+ init_selchars_low (positions, alpha_unify, alpha_inc);
+
+ /* Sort the selchars elements alphabetically. */
+ sort_char_set (selchars, _selchars_length);
+}
+
+/* Deletes selchars. */
+void
+KeywordExt::delete_selchars ()
+{
+ delete[] const_cast<unsigned int *>(_selchars);
+}
+
+
+/* ------------------------- Keyword_Factory class ------------------------- */
+
+Keyword_Factory::Keyword_Factory ()
+{
+}
+
+Keyword_Factory::~Keyword_Factory ()
+{
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+char empty_string[1] = "";
+
+
+#ifndef __OPTIMIZE__
+
+#define INLINE /* not inline */
+#include "keyword.icc"
+#undef INLINE
+
+#endif /* not defined __OPTIMIZE__ */
diff --git a/contrib/gperf/src/keyword.h b/contrib/gperf/src/keyword.h
new file mode 100644
index 0000000..8824350
--- /dev/null
+++ b/contrib/gperf/src/keyword.h
@@ -0,0 +1,116 @@
+/* This may look like C code, but it is really -*- C++ -*- */
+
+/* Keyword data.
+
+ Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
+
+ 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 2, 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 this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef keyword_h
+#define keyword_h 1
+
+/* Class defined in "positions.h". */
+class Positions;
+
+/* An instance of this class is a keyword, as specified in the input file. */
+
+struct Keyword
+{
+ /* Constructor. */
+ Keyword (const char *allchars, int allchars_length,
+ const char *rest);
+
+ /* Data members defined immediately by the input file. */
+ /* The keyword as a string, possibly containing NUL bytes. */
+ const char *const _allchars;
+ int const _allchars_length;
+ /* Additional stuff seen on the same line of the input file. */
+ const char *const _rest;
+ /* Line number of this keyword in the input file. */
+ unsigned int _lineno;
+};
+
+/* A keyword, in the context of a given keyposition list. */
+
+struct KeywordExt : public Keyword
+{
+ /* Constructor. */
+ KeywordExt (const char *allchars, int allchars_length,
+ const char *rest);
+
+ /* Data members depending on the keyposition list. */
+ /* The selected characters that participate for the hash function,
+ selected according to the keyposition list, as a canonically reordered
+ multiset. */
+ const unsigned int * _selchars;
+ int _selchars_length;
+ /* Chained list of keywords having the same _selchars and
+ - if !option[NOLENGTH] - also the same _allchars_length.
+ Note that these duplicates are not members of the main keyword list. */
+ KeywordExt * _duplicate_link;
+
+ /* Methods depending on the keyposition list. */
+ /* Initializes selchars and selchars_length, without reordering. */
+ void init_selchars_tuple (const Positions& positions, const unsigned int *alpha_unify);
+ /* Initializes selchars and selchars_length, with reordering. */
+ void init_selchars_multiset (const Positions& positions, const unsigned int *alpha_unify, const unsigned int *alpha_inc);
+ /* Deletes selchars. */
+ void delete_selchars ();
+
+ /* Data members used by the algorithm. */
+ int _hash_value; /* Hash value for the keyword. */
+
+ /* Data members used by the output routines. */
+ int _final_index;
+
+private:
+ unsigned int * init_selchars_low (const Positions& positions, const unsigned int *alpha_unify, const unsigned int *alpha_inc);
+};
+
+/* An abstract factory for creating Keyword instances.
+ This factory is used to make the Input class independent of the concrete
+ class KeywordExt. */
+
+class Keyword_Factory
+{
+public:
+ /* Constructor. */
+ Keyword_Factory ();
+ /* Destructor. */
+ virtual ~Keyword_Factory ();
+
+ /* Creates a new Keyword. */
+ virtual /*abstract*/ Keyword *
+ create_keyword (const char *allchars, int allchars_length,
+ const char *rest) = 0;
+};
+
+/* A statically allocated empty string. */
+extern char empty_string[1];
+
+#ifdef __OPTIMIZE__
+
+#define INLINE inline
+#include "keyword.icc"
+#undef INLINE
+
+#endif
+
+#endif
diff --git a/contrib/gperf/src/keyword.icc b/contrib/gperf/src/keyword.icc
new file mode 100644
index 0000000..ba0bb56
--- /dev/null
+++ b/contrib/gperf/src/keyword.icc
@@ -0,0 +1,42 @@
+/* Inline Functions for keyword.{h,cc}.
+
+ Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
+
+ 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 2, 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 this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* ----------------------------- Keyword class ----------------------------- */
+
+/* Constructor. */
+INLINE
+Keyword::Keyword (const char *allchars, int allchars_length, const char *rest)
+ : _allchars (allchars), _allchars_length (allchars_length), _rest (rest)
+{
+}
+
+
+/* --------------------------- KeywordExt class --------------------------- */
+
+/* Constructor. */
+INLINE
+KeywordExt::KeywordExt (const char *allchars, int allchars_length, const char *rest)
+ : Keyword (allchars, allchars_length, rest),
+ _final_index (-1)
+{
+}
diff --git a/contrib/gperf/src/list-node.cc b/contrib/gperf/src/list-node.cc
deleted file mode 100644
index 57a04a0..0000000
--- a/contrib/gperf/src/list-node.cc
+++ /dev/null
@@ -1,102 +0,0 @@
-/* Creates and initializes a new list node.
- Copyright (C) 1989-1998, 2000 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 (const char *k, int len, const char *r):
- link (0), next (0), key (k), key_length (len), rest (r), index (0)
-{
- T (Trace t ("List_Node::List_Node");)
- char *key_set = new char[(option[ALLCHARS] ? len : option.get_max_keysig_size ())];
- char *ptr = key_set;
- int i;
-
- if (option[ALLCHARS]) /* Use all the character positions in the KEY. */
- for (i = len; i > 0; k++, ptr++, i--)
- ++occurrences[(unsigned char)(*ptr = *k)];
- else /* Only use those character positions specified by the user. */
- {
- /* Iterate through 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_length, key);
- exit (1);
- }
- }
-
- /* Sort the KEY_SET items alphabetically. */
- set_sort (key_set, ptr - key_set);
-
- char_set = key_set;
- char_set_length = ptr - key_set;
-}
diff --git a/contrib/gperf/src/list-node.h b/contrib/gperf/src/list-node.h
deleted file mode 100644
index 3bd21b3..0000000
--- a/contrib/gperf/src/list-node.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* 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, 2000 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. */
- int key_length; /* Length of the key. */
- const char *rest; /* Additional information for building hash function. */
- const char *char_set; /* Set of characters to hash, specified by user. */
- int char_set_length; /* Length of char_set. */
- 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 (const char *key, int len, const char *rest);
- static void set_sort (char *base, int len);
-};
-
-#endif
diff --git a/contrib/gperf/src/main.cc b/contrib/gperf/src/main.cc
index 03b6c7e..577708b 100644
--- a/contrib/gperf/src/main.cc
+++ b/contrib/gperf/src/main.cc
@@ -1,76 +1,155 @@
-/* Driver program for the Gen_Perf hash function generator
- Copyright (C) 1989-1998, 2000 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
+/* Driver program for the hash function generator
+ Copyright (C) 1989-1998, 2000, 2002-2003 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
+
+ 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 2, 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 this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include "options.h"
-#include "gen-perf.h"
-#include "trace.h"
+#include "input.h"
+#include "search.h"
+#include "output.h"
+
+
+/* ------------------------------------------------------------------------- */
+
+/* This Keyword factory produces KeywordExt instances. */
+
+class KeywordExt_Factory : public Keyword_Factory
+{
+virtual Keyword * create_keyword (const char *allchars, int allchars_length,
+ const char *rest);
+};
+
+Keyword *
+KeywordExt_Factory::create_keyword (const char *allchars, int allchars_length, const char *rest)
+{
+ return new KeywordExt (allchars, allchars_length, rest);
+}
+
+/* ------------------------------------------------------------------------- */
int
main (int argc, char *argv[])
{
- T (Trace t ("main");)
+ int exitcode;
+
+ /* Set the Options. Open the input file and assign stdin to it. */
+ option.parse_options (argc, argv);
+
+ /* Open the input file. */
+ if (option.get_input_file_name ())
+ if (!freopen (option.get_input_file_name (), "r", stdin))
+ {
+ fprintf (stderr, "Cannot open input file '%s'\n",
+ option.get_input_file_name ());
+ exit (1);
+ }
-#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 */
+ /* Initialize the keyword list. */
+ KeywordExt_Factory factory;
+ Input inputter (stdin, &factory);
+ inputter.read_input ();
+ /* We can cast the keyword list to KeywordExt_List* because its list
+ elements were created by KeywordExt_Factory. */
+ KeywordExt_List* list = static_cast<KeywordExt_List*>(inputter._head);
+
+ {
+ /* Search for a good hash function. */
+ Search searcher (list);
+ searcher.optimize ();
+ list = searcher._head;
+
+ /* Open the output file. */
+ if (option.get_output_file_name ())
+ if (strcmp (option.get_output_file_name (), "-") != 0)
+ if (!freopen (option.get_output_file_name (), "w", stdout))
+ {
+ fprintf (stderr, "Cannot open output file '%s'\n",
+ option.get_output_file_name ());
+ exit (1);
+ }
- /* Sets the Options. */
- option (argc, argv);
+ {
+ /* Output the hash function code. */
+ Output outputter (searcher._head,
+ inputter._struct_decl,
+ inputter._struct_decl_lineno,
+ inputter._return_type,
+ inputter._struct_tag,
+ inputter._verbatim_declarations,
+ inputter._verbatim_declarations_end,
+ inputter._verbatim_declarations_lineno,
+ inputter._verbatim_code,
+ inputter._verbatim_code_end,
+ inputter._verbatim_code_lineno,
+ inputter._charset_dependent,
+ searcher._total_keys,
+ searcher._max_key_len,
+ searcher._min_key_len,
+ searcher._key_positions,
+ searcher._alpha_inc,
+ searcher._total_duplicates,
+ searcher._alpha_size,
+ searcher._asso_values);
+ outputter.output ();
- /* Initializes the key word list. */
- Gen_Perf generate_table;
+ /* Check for write error on stdout. */
+ exitcode = 0;
+ if (fflush (stdout) || ferror (stdout))
+ {
+ fprintf (stderr, "error while writing output file\n");
+ exitcode = 1;
+ }
- /* Generates and prints the Gen_Perf hash table. */
- int status = generate_table ();
+ /* Here we run the Output destructor. */
+ }
+ /* Here we run the Search destructor. */
+ }
- /* Check for write error on stdout. */
- if (fflush (stdout) || ferror (stdout))
- status = 1;
+ /* Also delete the list that was allocated inside Input and reordered
+ inside Search. */
+ for (KeywordExt_List *ptr = list; ptr; ptr = ptr->rest())
+ {
+ KeywordExt *keyword = ptr->first();
+ do
+ {
+ KeywordExt *next_keyword = keyword->_duplicate_link;
+ delete[] const_cast<unsigned int *>(keyword->_selchars);
+ if (keyword->_rest != empty_string)
+ delete[] const_cast<char*>(keyword->_rest);
+ if (!(keyword->_allchars >= inputter._input
+ && keyword->_allchars < inputter._input_end))
+ delete[] const_cast<char*>(keyword->_allchars);
+ delete keyword;
+ keyword = next_keyword;
+ }
+ while (keyword != NULL);
+ }
+ delete_list (list);
+
+ /* Here we run the Input destructor. */
+ }
- /* Don't use exit() here, it skips the destructors. */
- return status;
+ /* Don't use exit() here, it skips the destructors. */
+ return exitcode;
}
diff --git a/contrib/gperf/src/new.cc b/contrib/gperf/src/new.cc
deleted file mode 100644
index 8c6728e..0000000
--- a/contrib/gperf/src/new.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-/* 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
index 7706848..a86432e 100644
--- a/contrib/gperf/src/options.cc
+++ b/contrib/gperf/src/options.cc
@@ -1,151 +1,192 @@
/* Handles parsing the Options provided to the user.
- Copyright (C) 1989-1998, 2000 Free Software Foundation, Inc.
- written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+ Copyright (C) 1989-1998, 2000, 2002-2004, 2006-2007 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
-This file is part of GNU GPERF.
+ 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 free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
-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.
+ 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. */
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Specification. */
+#include "options.h"
#include <stdio.h>
#include <stdlib.h> /* declares atoi(), abs(), exit() */
#include <string.h> /* declares strcmp() */
+#include <ctype.h> /* declares isdigit() */
+#include <limits.h> /* defines CHAR_MAX */
#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. */
+/* Global option coordinator for the entire program. */
Options option;
-/* Records the program name. */
+/* Records the program name. */
const char *program_name;
-/* Size to jump on a collision. */
+/* 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 generated lookup function. */
+static const char *const DEFAULT_FUNCTION_NAME = "in_word_set";
-/* Default name for the key component. */
-static const char *const DEFAULT_KEY = "name";
+/* Default name for the key component. */
+static const char *const DEFAULT_SLOT_NAME = "name";
-/* Default struct initializer suffix. */
+/* Default struct initializer suffix. */
static const char *const DEFAULT_INITIALIZER_SUFFIX = "";
-/* Default name for the generated class. */
+/* Default name for the generated class. */
static const char *const DEFAULT_CLASS_NAME = "Perfect_Hash";
-/* Default name for generated hash function. */
+/* Default name for generated hash function. */
static const char *const DEFAULT_HASH_NAME = "hash";
-/* Default name for generated hash table array. */
+/* 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::initializer_suffix;
-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. */
+/* Default name for generated length table array. */
+static const char *const DEFAULT_LENGTHTABLE_NAME = "lengthtable";
+
+/* Default name for string pool. */
+static const char *const DEFAULT_STRINGPOOL_NAME = "stringpool";
+
+/* Default delimiters that separate keywords from their attributes. */
+static const char *const DEFAULT_DELIMITERS = ",";
+
+/* Prints program usage to given stream. */
void
-Options::short_usage (FILE * strm)
+Options::short_usage (FILE * stream)
{
- T (Trace t ("Options::short_usage");)
- fprintf (strm, "Usage: %s [-cCdDef[num]F<initializers>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);
+ fprintf (stream,
+ "Try '%s --help' for more information.\n", program_name);
}
void
-Options::long_usage (FILE * strm)
+Options::long_usage (FILE * stream)
{
- T (Trace t ("Options::long_usage");)
- fprintf (strm,
- "GNU `gperf' generates perfect hash functions.\n"
- "\n"
- "Usage: %s [OPTION]... [INPUT-FILE]\n"
- "\n"
+ fprintf (stream,
+ "GNU 'gperf' generates perfect hash functions.\n");
+ fprintf (stream, "\n");
+ fprintf (stream,
+ "Usage: %s [OPTION]... [INPUT-FILE]\n",
+ program_name);
+ fprintf (stream, "\n");
+ fprintf (stream,
"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"
+ "for the equivalent short option also.\n");
+ fprintf (stream, "\n");
+ fprintf (stream,
+ "Output file location:\n");
+ fprintf (stream,
+ " --output-file=FILE Write output to specified file.\n");
+ fprintf (stream,
+ "The results are written to standard output if no output file is specified\n"
+ "or if it is -.\n");
+ fprintf (stream, "\n");
+ fprintf (stream,
+ "Input file interpretation:\n");
+ fprintf (stream,
" -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"
+ " Default is \",\".\n");
+ fprintf (stream,
" -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"
+ " group of fields per line.\n");
+ fprintf (stream,
+ " --ignore-case Consider upper and lower case ASCII characters as\n"
+ " equivalent. Note that locale dependent case mappings\n"
+ " are ignored.\n");
+ fprintf (stream, "\n");
+ fprintf (stream,
+ "Language for the output code:\n");
+ fprintf (stream,
" -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"
+ " default is C.\n");
+ fprintf (stream, "\n");
+ fprintf (stream,
+ "Details in the output code:\n");
+ fprintf (stream,
" -K, --slot-name=NAME Select name of the keyword component in the keyword\n"
- " structure.\n"
+ " structure.\n");
+ fprintf (stream,
" -F, --initializer-suffix=INITIALIZERS\n"
" Initializers for additional components in the keyword\n"
- " structure.\n"
- " -H, --hash-fn-name=NAME\n"
+ " structure.\n");
+ fprintf (stream,
+ " -H, --hash-function-name=NAME\n"
" Specify name of generated hash function. Default is\n"
- " `hash'.\n"
- " -N, --lookup-fn-name=NAME\n"
+ " 'hash'.\n");
+ fprintf (stream,
+ " -N, --lookup-function-name=NAME\n"
" Specify name of generated lookup function. Default\n"
- " name is `in_word_set'.\n"
+ " name is 'in_word_set'.\n");
+ fprintf (stream,
" -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"
+ " 'Perfect_Hash'.\n");
+ fprintf (stream,
+ " -7, --seven-bit Assume 7-bit characters.\n");
+ fprintf (stream,
+ " -l, --compare-lengths Compare key lengths before trying a string\n"
+ " comparison. This is necessary if the keywords\n"
+ " contain NUL bytes. It also helps cut down on the\n"
+ " number of string comparisons made during the lookup.\n");
+ fprintf (stream,
" -c, --compare-strncmp Generate comparison code using strncmp rather than\n"
- " strcmp.\n"
+ " strcmp.\n");
+ fprintf (stream,
" -C, --readonly-tables Make the contents of generated lookup tables\n"
- " constant, i.e., readonly.\n"
+ " constant, i.e., readonly.\n");
+ fprintf (stream,
" -E, --enum Define constant values using an enum local to the\n"
- " lookup function rather than with defines.\n"
+ " lookup function rather than with defines.\n");
+ fprintf (stream,
" -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"
+ " at the beginning of the code.\n");
+ fprintf (stream,
+ " -G, --global-table 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"
+ " lookup function (which is the default behavior).\n");
+ fprintf (stream,
+ " -P, --pic Optimize the generated table for inclusion in shared\n"
+ " libraries. This reduces the startup time of programs\n"
+ " using a shared library containing the generated code.\n");
+ fprintf (stream,
+ " -Q, --string-pool-name=NAME\n"
+ " Specify name of string pool generated by option --pic.\n"
+ " Default name is 'stringpool'.\n");
+ fprintf (stream,
+ " --null-strings Use NULL strings instead of empty strings for empty\n"
+ " keyword table entries.\n");
+ fprintf (stream,
" -W, --word-array-name=NAME\n"
" Specify name of word list array. Default name is\n"
- " `wordlist'.\n"
+ " 'wordlist'.\n");
+ fprintf (stream,
+ " --length-table-name=NAME\n"
+ " Specify name of length table array. Default name is\n"
+ " 'lengthtable'.\n");
+ fprintf (stream,
" -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"
@@ -155,13 +196,16 @@ Options::long_usage (FILE * strm)
" 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"
+ " binary search.\n");
+ fprintf (stream,
" -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"
+ " defined elsewhere.\n");
+ fprintf (stream, "\n");
+ fprintf (stream,
+ "Algorithm employed by gperf:\n");
+ fprintf (stream,
" -k, --key-positions=KEYS\n"
" Select the key positions used in the hash function.\n"
" The allowable choices range between 1-%d, inclusive.\n"
@@ -169,79 +213,93 @@ Options::long_usage (FILE * strm)
" 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"
+ " indicates the \"final character\" of a key, e.g.,\n"
+ " $,1,2,4,6-10.\n",
+ Positions::MAX_KEY_POS);
+ fprintf (stream,
" -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"
+ " is useful for certain highly redundant keyword sets.\n");
+ fprintf (stream,
+ " -m, --multiple-iterations=ITERATIONS\n"
+ " Perform multiple choices of the -i and -j values,\n"
+ " and choose the best results. This increases the\n"
+ " running time by a factor of ITERATIONS but does a\n"
+ " good job minimizing the generated table size.\n");
+ fprintf (stream,
" -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"
+ " inflate the size of the final table.\n");
+ fprintf (stream,
+ " -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"
+ " be an odd number, default is %d.\n",
+ DEFAULT_JUMP_VALUE);
+ fprintf (stream,
" -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"
+ " computing the hash function.\n");
+ fprintf (stream,
" -r, --random Utilizes randomness to initialize the associated\n"
- " values table.\n"
+ " values table.\n");
+ fprintf (stream,
" -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"
+ " 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"
+ " 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"
+ " keys\". Conversely, a value of 1/3 means \"make the\n"
" maximum associated value about 3 times smaller than\n"
- " the number of input keys. A larger table should\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"
+ " value is 1.\n");
+ fprintf (stream, "\n");
+ fprintf (stream,
"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 to the standard error).\n");
+ fprintf (stream, "\n");
+ fprintf (stream,
+ "Report bugs to <bug-gnu-gperf@gnu.org>.\n");
}
-/* Output command-line Options. */
+/* Prints the given options. */
void
-Options::print_options (void)
+Options::print_options () const
{
- T (Trace t ("Options::print_options");)
- int i;
-
printf ("/* Command-line: ");
- for (i = 0; i < argument_count; i++)
+ for (int i = 0; i < _argument_count; i++)
{
- const char *arg = argument_vector[i];
+ const char *arg = _argument_vector[i];
- /* Escape arg if it contains shell metacharacters. */
+ /* Escape arg if it contains shell metacharacters. */
if (*arg == '-')
{
putchar (*arg);
arg++;
- if ((*arg >= 'A' && *arg <= 'Z') || (*arg >= 'a' && *arg <= 'z'))
+ if (*arg >= 'A' && *arg <= 'Z' || *arg >= 'a' && *arg <= 'z')
{
putchar (*arg);
arg++;
}
+ else if (*arg == '-')
+ {
+ do
+ {
+ putchar (*arg);
+ arg++;
+ }
+ while (*arg >= 'A' && *arg <= 'Z' || *arg >= 'a' && *arg <= 'z' || *arg == '-');
+ if (*arg == '=')
+ {
+ putchar (*arg);
+ arg++;
+ }
+ }
}
if (strpbrk (arg, "\t\n !\"#$&'()*;<>?[\\]`{|}~") != NULL)
{
@@ -250,7 +308,7 @@ Options::print_options (void)
putchar ('"');
for (; *arg; arg++)
{
- if (*arg == '\"' || *arg == '\\' || *arg == '$')
+ if (*arg == '\"' || *arg == '\\' || *arg == '$' || *arg == '`')
putchar ('\\');
putchar (*arg);
}
@@ -277,389 +335,653 @@ Options::print_options (void)
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)
+/* Parses a string denoting key positions. */
+
+class PositionStringParser
{
- T (Trace t ("Options::key_sort");)
- int i, j;
+public:
+ /* Initializes a key position string parser for string STR. */
+ PositionStringParser (const char *str,
+ int low_bound, int high_bound,
+ int end_word_marker, int error_value, int end_marker);
+ /* Returns the next key position from the given string. */
+ int nextPosition ();
+private:
+ /* A pointer to the string provided by the user. */
+ const char * _str;
+ /* Smallest possible value, inclusive. */
+ int const _low_bound;
+ /* Greatest possible value, inclusive. */
+ int const _high_bound;
+ /* A value marking the abstract "end of word" ( usually '$'). */
+ int const _end_word_marker;
+ /* Error value returned when input is syntactically erroneous. */
+ int const _error_value;
+ /* Value returned after last key is processed. */
+ int const _end_marker;
+ /* Intermediate state for producing a range of positions. */
+ bool _in_range; /* True while producing a range of positions. */
+ int _range_upper_bound; /* Upper bound (inclusive) of the range. */
+ int _range_curr_value; /* Last value returned. */
+};
+
+/* Initializes a key position strng parser for string STR. */
+PositionStringParser::PositionStringParser (const char *str,
+ int low_bound, int high_bound,
+ int end_word_marker, int error_value, int end_marker)
+ : _str (str),
+ _low_bound (low_bound),
+ _high_bound (high_bound),
+ _end_word_marker (end_word_marker),
+ _error_value (error_value),
+ _end_marker (end_marker),
+ _in_range (false)
+{
+}
- for (i = 0, j = len - 1; i < j; i++)
+/* Returns the next key position from the given string. */
+int
+PositionStringParser::nextPosition ()
+{
+ if (_in_range)
+ {
+ /* We are inside a range. Return the next value from the range. */
+ if (++_range_curr_value >= _range_upper_bound)
+ _in_range = false;
+ return _range_curr_value;
+ }
+ else
{
- int curr, tmp;
+ /* Continue parsing the given string. */
+ while (*_str)
+ switch (*_str)
+ {
+ case ',':
+ /* Skip the comma. */
+ _str++;
+ break;
+ case '$':
+ /* Valid key position. */
+ _str++;
+ return _end_word_marker;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ /* Valid key position. */
+ {
+ int curr_value;
+ for (curr_value = 0; isdigit (static_cast<unsigned char>(*_str)); _str++)
+ curr_value = curr_value * 10 + (*_str - '0');
- 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;
+ if (*_str == '-')
+ {
+ _str++;
+ /* Starting a range of key positions. */
+ _in_range = true;
- base[curr] = tmp;
- }
+ for (_range_upper_bound = 0;
+ isdigit (static_cast<unsigned char>(*_str));
+ _str++)
+ _range_upper_bound = _range_upper_bound * 10 + (*_str - '0');
+
+ /* Verify range's upper bound. */
+ if (!(_range_upper_bound > curr_value && _range_upper_bound <= _high_bound))
+ return _error_value;
+ _range_curr_value = curr_value;
+ }
- return 1;
+ /* Verify range's lower bound. */
+ if (!(curr_value >= _low_bound && curr_value <= _high_bound))
+ return _error_value;
+ return curr_value;
+ }
+ default:
+ /* Invalid syntax. */
+ return _error_value;
+ }
+
+ return _end_marker;
+ }
}
-/* Sets the default Options. */
+/* ------------------------------------------------------------------------- */
+
+/* Sets the default Options. */
-Options::Options (void)
+Options::Options ()
+ : _option_word (C),
+ _input_file_name (NULL),
+ _output_file_name (NULL),
+ _language (NULL),
+ _jump (DEFAULT_JUMP_VALUE),
+ _initial_asso_value (0),
+ _asso_iterations (0),
+ _total_switches (1),
+ _size_multiple (1),
+ _function_name (DEFAULT_FUNCTION_NAME),
+ _slot_name (DEFAULT_SLOT_NAME),
+ _initializer_suffix (DEFAULT_INITIALIZER_SUFFIX),
+ _class_name (DEFAULT_CLASS_NAME),
+ _hash_name (DEFAULT_HASH_NAME),
+ _wordlist_name (DEFAULT_WORDLIST_NAME),
+ _lengthtable_name (DEFAULT_LENGTHTABLE_NAME),
+ _stringpool_name (DEFAULT_STRINGPOOL_NAME),
+ _delimiters (DEFAULT_DELIMITERS),
+ _key_positions ()
{
- 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;
- initializer_suffix = DEFAULT_INITIALIZER_SUFFIX;
- 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. */
+/* Dumps option status when debugging is enabled. */
-Options::~Options (void)
+Options::~Options ()
{
- T (Trace t ("Options::~Options");)
- if (option_word & DEBUG)
+ 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"
+ "\nUPPERLOWER is..: %s"
"\nKRC is.........: %s"
"\nC is...........: %s"
"\nANSIC is.......: %s"
"\nCPLUSPLUS is...: %s"
+ "\nSEVENBIT is....: %s"
+ "\nLENTABLE is....: %s"
+ "\nCOMP is........: %s"
+ "\nCONST is.......: %s"
"\nENUM is........: %s"
"\nINCLUDE is.....: %s"
- "\nSEVENBIT is....: %s"
- "\niterations = %d"
+ "\nGLOBAL is......: %s"
+ "\nNULLSTRINGS is.: %s"
+ "\nSHAREDLIB is...: %s"
+ "\nSWITCH is......: %s"
+ "\nNOTYPE is......: %s"
+ "\nDUP is.........: %s"
+ "\nNOLENGTH is....: %s"
+ "\nRANDOM is......: %s"
+ "\nDEBUG is.......: %s"
"\nlookup function name = %s"
"\nhash function name = %s"
"\nword list name = %s"
- "\nkey name = %s"
+ "\nlength table name = %s"
+ "\nstring pool name = %s"
+ "\nslot name = %s"
"\ninitializer suffix = %s"
+ "\nasso_values iterations = %d"
"\njump value = %d"
- "\nmax associated value = %d"
+ "\nhash table size multiplier = %g"
"\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,
- initializer_suffix, jump, size - 1, initial_asso_value,
- delimiters, total_switches);
- if (option_word & ALLCHARS)
+ _option_word & TYPE ? "enabled" : "disabled",
+ _option_word & UPPERLOWER ? "enabled" : "disabled",
+ _option_word & KRC ? "enabled" : "disabled",
+ _option_word & C ? "enabled" : "disabled",
+ _option_word & ANSIC ? "enabled" : "disabled",
+ _option_word & CPLUSPLUS ? "enabled" : "disabled",
+ _option_word & SEVENBIT ? "enabled" : "disabled",
+ _option_word & LENTABLE ? "enabled" : "disabled",
+ _option_word & COMP ? "enabled" : "disabled",
+ _option_word & CONST ? "enabled" : "disabled",
+ _option_word & ENUM ? "enabled" : "disabled",
+ _option_word & INCLUDE ? "enabled" : "disabled",
+ _option_word & GLOBAL ? "enabled" : "disabled",
+ _option_word & NULLSTRINGS ? "enabled" : "disabled",
+ _option_word & SHAREDLIB ? "enabled" : "disabled",
+ _option_word & SWITCH ? "enabled" : "disabled",
+ _option_word & NOTYPE ? "enabled" : "disabled",
+ _option_word & DUP ? "enabled" : "disabled",
+ _option_word & NOLENGTH ? "enabled" : "disabled",
+ _option_word & RANDOM ? "enabled" : "disabled",
+ _option_word & DEBUG ? "enabled" : "disabled",
+ _function_name, _hash_name, _wordlist_name, _lengthtable_name,
+ _stringpool_name, _slot_name, _initializer_suffix,
+ _asso_iterations, _jump, _size_multiple, _initial_asso_value,
+ _delimiters, _total_switches);
+ if (_key_positions.is_useall())
fprintf (stderr, "all characters are used in the hash function\n");
+ else
+ {
+ fprintf (stderr, "maximum keysig size = %d\nkey positions are: \n",
+ _key_positions.get_size());
- 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);
+ PositionIterator iter = _key_positions.iterator();
+ for (int pos; (pos = iter.next()) != PositionIterator::EOS; )
+ if (pos == Positions::LASTCHAR)
+ fprintf (stderr, "$\n");
+ else
+ fprintf (stderr, "%d\n", pos + 1);
+ }
fprintf (stderr, "finished dumping Options\n");
}
}
-/* Parses the command line Options and sets appropriate flags in option_word. */
+/* Sets the output language, if not already set. */
+void
+Options::set_language (const char *language)
+{
+ if (_language == NULL)
+ {
+ _language = language;
+ _option_word &= ~(KRC | C | ANSIC | CPLUSPLUS);
+ if (!strcmp (language, "KR-C"))
+ _option_word |= KRC;
+ else if (!strcmp (language, "C"))
+ _option_word |= C;
+ else if (!strcmp (language, "ANSI-C"))
+ _option_word |= ANSIC;
+ else if (!strcmp (language, "C++"))
+ _option_word |= CPLUSPLUS;
+ else
+ {
+ fprintf (stderr, "unsupported language option %s, defaulting to C\n",
+ language);
+ _option_word |= C;
+ }
+ }
+}
+
+/* Sets the total number of switch statements, if not already set. */
+void
+Options::set_total_switches (int total_switches)
+{
+ if (!(_option_word & SWITCH))
+ {
+ _option_word |= SWITCH;
+ _total_switches = total_switches;
+ }
+}
+
+/* Sets the generated function name, if not already set. */
+void
+Options::set_function_name (const char *name)
+{
+ if (_function_name == DEFAULT_FUNCTION_NAME)
+ _function_name = name;
+}
+
+/* Sets the keyword key name, if not already set. */
+void
+Options::set_slot_name (const char *name)
+{
+ if (_slot_name == DEFAULT_SLOT_NAME)
+ _slot_name = name;
+}
+
+/* Sets the struct initializer suffix, if not already set. */
+void
+Options::set_initializer_suffix (const char *initializers)
+{
+ if (_initializer_suffix == DEFAULT_INITIALIZER_SUFFIX)
+ _initializer_suffix = initializers;
+}
+
+/* Sets the generated class name, if not already set. */
+void
+Options::set_class_name (const char *name)
+{
+ if (_class_name == DEFAULT_CLASS_NAME)
+ _class_name = name;
+}
+
+/* Sets the hash function name, if not already set. */
+void
+Options::set_hash_name (const char *name)
+{
+ if (_hash_name == DEFAULT_HASH_NAME)
+ _hash_name = name;
+}
+
+/* Sets the hash table array name, if not already set. */
+void
+Options::set_wordlist_name (const char *name)
+{
+ if (_wordlist_name == DEFAULT_WORDLIST_NAME)
+ _wordlist_name = name;
+}
+
+/* Sets the length table array name, if not already set. */
+void
+Options::set_lengthtable_name (const char *name)
+{
+ if (_lengthtable_name == DEFAULT_LENGTHTABLE_NAME)
+ _lengthtable_name = name;
+}
+
+/* Sets the string pool name, if not already set. */
+void
+Options::set_stringpool_name (const char *name)
+{
+ if (_stringpool_name == DEFAULT_STRINGPOOL_NAME)
+ _stringpool_name = name;
+}
+
+/* Sets the delimiters string, if not already set. */
+void
+Options::set_delimiters (const char *delimiters)
+{
+ if (_delimiters == DEFAULT_DELIMITERS)
+ _delimiters = delimiters;
+}
+
+
+/* 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' },
- { "initializer-suffix", required_argument, 0, 'F' },
- { "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 }
+ { "output-file", required_argument, NULL, CHAR_MAX + 1 },
+ { "ignore-case", no_argument, NULL, CHAR_MAX + 2 },
+ { "delimiters", required_argument, NULL, 'e' },
+ { "struct-type", no_argument, NULL, 't' },
+ { "language", required_argument, NULL, 'L' },
+ { "slot-name", required_argument, NULL, 'K' },
+ { "initializer-suffix", required_argument, NULL, 'F' },
+ { "hash-fn-name", required_argument, NULL, 'H' }, /* backward compatibility */
+ { "hash-function-name", required_argument, NULL, 'H' },
+ { "lookup-fn-name", required_argument, NULL, 'N' }, /* backward compatibility */
+ { "lookup-function-name", required_argument, NULL, 'N' },
+ { "class-name", required_argument, NULL, 'Z' },
+ { "seven-bit", no_argument, NULL, '7' },
+ { "compare-strncmp", no_argument, NULL, 'c' },
+ { "readonly-tables", no_argument, NULL, 'C' },
+ { "enum", no_argument, NULL, 'E' },
+ { "includes", no_argument, NULL, 'I' },
+ { "global-table", no_argument, NULL, 'G' },
+ { "word-array-name", required_argument, NULL, 'W' },
+ { "length-table-name", required_argument, NULL, CHAR_MAX + 4 },
+ { "switch", required_argument, NULL, 'S' },
+ { "omit-struct-type", no_argument, NULL, 'T' },
+ { "key-positions", required_argument, NULL, 'k' },
+ { "compare-strlen", no_argument, NULL, 'l' }, /* backward compatibility */
+ { "compare-lengths", no_argument, NULL, 'l' },
+ { "duplicates", no_argument, NULL, 'D' },
+ { "fast", required_argument, NULL, 'f' },
+ { "initial-asso", required_argument, NULL, 'i' },
+ { "jump", required_argument, NULL, 'j' },
+ { "multiple-iterations", required_argument, NULL, 'm' },
+ { "no-strlen", no_argument, NULL, 'n' },
+ { "occurrence-sort", no_argument, NULL, 'o' },
+ { "optimized-collision-resolution", no_argument, NULL, 'O' },
+ { "pic", no_argument, NULL, 'P' },
+ { "string-pool-name", required_argument, NULL, 'Q' },
+ { "null-strings", no_argument, NULL, CHAR_MAX + 3 },
+ { "random", no_argument, NULL, 'r' },
+ { "size-multiple", required_argument, NULL, 's' },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'v' },
+ { "debug", no_argument, NULL, 'd' },
+ { NULL, no_argument, NULL, 0 }
};
void
-Options::operator() (int argc, char *argv[])
+Options::parse_options (int argc, char *argv[])
{
- T (Trace t ("Options::operator()");)
- int option_char;
+ int option_char;
program_name = argv[0];
- argument_count = argc;
- argument_vector = argv;
+ _argument_count = argc;
+ _argument_vector = argv;
while ((option_char =
- getopt_long (argument_count, argument_vector,
- "adcCDe:Ef:F:gGhH:i:Ij:k:K:lL:nN:oprs:S:tTvW:Z:7",
- long_options, (int *)0))
+ getopt_long (_argument_count, _argument_vector,
+ "acCdDe:Ef:F:gGhH:i:Ij:k:K:lL:m:nN:oOpPQ:rs:S:tTvW:Z:7",
+ long_options, NULL))
!= -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. */
+ 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;
+ _option_word |= COMP;
break;
}
- case 'C': /* Make the generated tables readonly (const). */
+ case 'C': /* Make the generated tables readonly (const). */
{
- option_word |= CONST;
+ _option_word |= CONST;
break;
}
- case 'd': /* Enable debugging option. */
+ case 'd': /* Enable debugging option. */
{
- option_word |= DEBUG;
+ _option_word |= DEBUG;
fprintf (stderr, "Starting program %s, version %s, with debugging on.\n",
program_name, version_string);
break;
}
- case 'D': /* Enable duplicate option. */
+ case 'D': /* Enable duplicate option. */
{
- option_word |= DUP;
+ _option_word |= DUP;
break;
}
- case 'e': /* Allows user to provide keyword/attribute separator */
+ case 'e': /* Specify keyword/attribute separator */
{
- option.delimiters = /*getopt*/optarg;
+ _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;
- }
+ _option_word |= ENUM;
break;
}
+ case 'f': /* Generate the hash table "fast". */
+ break; /* Not needed any more. */
case 'F':
{
- initializer_suffix = /*getopt*/optarg;
+ _initializer_suffix = /*getopt*/optarg;
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. */
+ 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;
+ _option_word |= GLOBAL;
break;
}
- case 'h': /* Displays a list of helpful Options to the user. */
+ 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 */
+ case 'H': /* Sets the name for the hash function. */
{
- hash_name = /*getopt*/optarg;
+ _hash_name = /*getopt*/optarg;
break;
}
- case 'i': /* Sets the initial value for the associated values array. */
+ 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 ((_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. */
+ case 'I': /* Enable #include statements. */
{
- option_word |= INCLUDE;
+ _option_word |= INCLUDE;
break;
}
- case 'j': /* Sets the jump value, must be odd for later algorithms. */
+ case 'j': /* Sets the jump value, must be odd for later algorithms. */
{
- if ((jump = atoi (/*getopt*/optarg)) < 0)
+ if ((_jump = atoi (/*getopt*/optarg)) < 0)
{
- fprintf (stderr, "Jump value %d must be a positive number.\n", jump);
+ 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++);
+ 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. */
+ case 'k': /* Sets key positions used for hash function. */
{
- const int BAD_VALUE = -1;
+ _option_word |= POSITIONS;
+ const int BAD_VALUE = -3;
+ const int EOS = PositionIterator::EOS;
int value;
- Iterator expand (/*getopt*/optarg, 1, MAX_KEY_POS - 1, WORD_END, BAD_VALUE, EOS);
+ PositionStringParser sparser (/*getopt*/optarg, 1, Positions::MAX_KEY_POS, Positions::LASTCHAR, BAD_VALUE, EOS);
if (/*getopt*/optarg [0] == '*') /* Use all the characters for hashing!!!! */
- option_word = (option_word & ~DEFAULTCHARS) | ALLCHARS;
+ _key_positions.set_useall(true);
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)))
+ _key_positions.set_useall(false);
+ int *key_positions = _key_positions.pointer();
+ int *key_pos;
+
+ for (key_pos = key_positions; (value = sparser.nextPosition()) != EOS; key_pos++)
{
- fprintf (stderr, "No keys selected.\n");
+ if (value == BAD_VALUE)
+ {
+ fprintf (stderr, "Invalid position value or range, use 1,2,3-%d,'$' or '*'.\n",
+ Positions::MAX_KEY_POS);
+ short_usage (stderr);
+ exit (1);
+ }
+ if (key_pos - key_positions == Positions::MAX_SIZE)
+ {
+ /* More than Positions::MAX_SIZE key positions.
+ Since all key positions are in the range
+ 0..Positions::MAX_KEY_POS-1 or == Positions::LASTCHAR,
+ there must be duplicates. */
+ fprintf (stderr, "Duplicate key positions selected\n");
+ short_usage (stderr);
+ exit (1);
+ }
+ if (value != Positions::LASTCHAR)
+ /* We use 0-based indices in the class Positions. */
+ value = value - 1;
+ *key_pos = value;
+ }
+
+ unsigned int total_keysig_size = key_pos - key_positions;
+ if (total_keysig_size == 0)
+ {
+ fprintf (stderr, "No key positions selected.\n");
short_usage (stderr);
exit (1);
}
- else if (! key_sort (key_positions, total_keysig_size))
+ _key_positions.set_size (total_keysig_size);
+
+ /* Sorts the key positions *IN REVERSE ORDER!!*
+ This makes further routines more efficient. Especially
+ when generating code. */
+ if (! _key_positions.sort())
{
- fprintf (stderr, "Duplicate keys selected\n");
+ fprintf (stderr, "Duplicate key positions 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. */
+ case 'K': /* Make this the keyname for the keyword component field. */
{
- key_name = /*getopt*/optarg;
+ _slot_name = /*getopt*/optarg;
break;
}
- case 'l': /* Create length table to avoid extra string compares. */
+ case 'l': /* Create length table to avoid extra string compares. */
{
- option_word |= LENTABLE;
+ _option_word |= LENTABLE;
break;
}
- case 'L': /* Deal with different generated languages. */
+ 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
+ _language = NULL;
+ set_language (/*getopt*/optarg);
+ break;
+ }
+ case 'm': /* Multiple iterations for finding good asso_values. */
+ {
+ if ((_asso_iterations = atoi (/*getopt*/optarg)) < 0)
{
- fprintf (stderr, "unsupported language option %s, defaulting to C\n", /*getopt*/optarg);
- option_word |= C;
+ fprintf (stderr, "asso_iterations value must not be negative, assuming 0\n");
+ _asso_iterations = 0;
}
break;
}
- case 'n': /* Don't include the length when computing hash function. */
+ case 'n': /* Don't include the length when computing hash function. */
{
- option_word |= NOLENGTH;
+ _option_word |= NOLENGTH;
break;
}
- case 'N': /* Make generated lookup function name be optarg */
+ case 'N': /* Make generated lookup function name be optarg. */
{
- function_name = /*getopt*/optarg;
+ _function_name = /*getopt*/optarg;
break;
}
- case 'o': /* Order input by frequency of key set occurrence. */
+ case 'o': /* Order input by frequency of key set occurrence. */
+ break; /* Not needed any more. */
+ case 'O': /* Optimized choice during collision resolution. */
+ break; /* Not needed any more. */
+ case 'p': /* Generated lookup function a pointer instead of int. */
+ break; /* This is now the default. */
+ case 'P': /* Optimize for position-independent code. */
{
- option_word |= ORDER;
+ _option_word |= SHAREDLIB;
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. */
+ case 'Q': /* Sets the name for the string pool. */
{
- option_word |= RANDOM;
- if (option.initial_asso_value != 0)
- fprintf (stderr, "warning, -r option superceeds -i, disabling -i option and continuing\n");
+ _stringpool_name = /*getopt*/optarg;
break;
}
- case 's': /* Range of associated values, determines size of final table. */
+ case 'r': /* Utilize randomness to initialize the associated values 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);
+ _option_word |= RANDOM;
+ if (_initial_asso_value != 0)
+ fprintf (stderr, "warning, -r option supersedes -i, disabling -i option and continuing\n");
break;
}
- case 'S': /* Generate switch statement output, rather than lookup table. */
+ case 's': /* Range of associated values, determines size of final table. */
{
- option_word |= SWITCH;
- if ((option.total_switches = atoi (/*getopt*/optarg)) <= 0)
+ float numerator;
+ float denominator = 1;
+ bool invalid = false;
+ char *endptr;
+
+ numerator = strtod (/*getopt*/optarg, &endptr);
+ if (endptr == /*getopt*/optarg)
+ invalid = true;
+ else if (*endptr != '\0')
+ {
+ if (*endptr == '/')
+ {
+ char *denomptr = endptr + 1;
+ denominator = strtod (denomptr, &endptr);
+ if (endptr == denomptr || *endptr != '\0')
+ invalid = true;
+ }
+ else
+ invalid = true;
+ }
+ if (invalid)
+ {
+ fprintf (stderr, "Invalid value for option -s.\n");
+ short_usage (stderr);
+ exit (1);
+ }
+ _size_multiple = numerator / denominator;
+ /* Backward compatibility: -3 means 1/3. */
+ if (_size_multiple < 0)
+ _size_multiple = 1 / (-_size_multiple);
+ /* Catch stupid users. */
+ if (_size_multiple == 0)
+ _size_multiple = 1;
+ /* Warnings. */
+ if (_size_multiple > 50)
+ fprintf (stderr, "Size multiple %g is excessive, did you really mean this?! (try '%s --help' for help)\n", _size_multiple, program_name);
+ else if (_size_multiple < 0.01f)
+ fprintf (stderr, "Size multiple %g is extremely small, did you really mean this?! (try '%s --help' for help)\n", _size_multiple, program_name);
+ break;
+ }
+ case 'S': /* Generate switch statement output, rather than lookup table. */
+ {
+ _option_word |= SWITCH;
+ _total_switches = atoi (/*getopt*/optarg);
+ if (_total_switches <= 0)
{
fprintf (stderr, "number of switches %s must be a positive number\n", /*getopt*/optarg);
short_usage (stderr);
@@ -667,33 +989,59 @@ Options::operator() (int argc, char *argv[])
}
break;
}
- case 't': /* Enable the TYPE mode, allowing arbitrary user structures. */
+ case 't': /* Enable the TYPE mode, allowing arbitrary user structures. */
{
- option_word |= TYPE;
+ _option_word |= TYPE;
break;
}
- case 'T': /* Don't print structure definition. */
+ case 'T': /* Don't print structure definition. */
{
- option_word |= NOTYPE;
+ _option_word |= NOTYPE;
break;
}
- case 'v': /* Print out the version and quit. */
+ case 'v': /* Print out the version and quit. */
fprintf (stdout, "GNU gperf %s\n", version_string);
+ fprintf (stdout, "Copyright (C) %s Free Software Foundation, Inc.\n\
+This is free software; see the source for copying conditions. There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
+",
+ "1989-1998, 2000-2004, 2006-2007");
+ fprintf (stdout, "Written by %s and %s.\n",
+ "Douglas C. Schmidt", "Bruno Haible");
exit (0);
- case 'W': /* Sets the name for the hash table array */
+ case 'W': /* Sets the name for the hash table array. */
+ {
+ _wordlist_name = /*getopt*/optarg;
+ break;
+ }
+ case 'Z': /* Set the class name. */
{
- wordlist_name = /*getopt*/optarg;
+ _class_name = /*getopt*/optarg;
break;
}
- case 'Z': /* Set the class name. */
+ case '7': /* Assume 7-bit characters. */
{
- class_name = /*getopt*/optarg;
+ _option_word |= SEVENBIT;
break;
}
- case '7': /* Assume 7-bit characters. */
+ case CHAR_MAX + 1: /* Set the output file name. */
{
- option_word |= SEVENBIT;
- Vectors::ALPHA_SIZE = 128;
+ _output_file_name = /*getopt*/optarg;
+ break;
+ }
+ case CHAR_MAX + 2: /* Case insignificant. */
+ {
+ _option_word |= UPPERLOWER;
+ break;
+ }
+ case CHAR_MAX + 3: /* Use NULL instead of "". */
+ {
+ _option_word |= NULLSTRINGS;
+ break;
+ }
+ case CHAR_MAX + 4: /* Sets the name for the length table array. */
+ {
+ _lengthtable_name = /*getopt*/optarg;
break;
}
default:
@@ -703,14 +1051,10 @@ Options::operator() (int argc, char *argv[])
}
- 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)
+ _input_file_name = argv[/*getopt*/optind++];
- if (++/*getopt*/optind < argc)
+ if (/*getopt*/optind < argc)
{
fprintf (stderr, "Extra trailing arguments to %s.\n", program_name);
short_usage (stderr);
@@ -718,6 +1062,8 @@ Options::operator() (int argc, char *argv[])
}
}
+/* ------------------------------------------------------------------------- */
+
#ifndef __OPTIMIZE__
#define INLINE /* not inline */
diff --git a/contrib/gperf/src/options.h b/contrib/gperf/src/options.h
index 9025c86..bda7f0c 100644
--- a/contrib/gperf/src/options.h
+++ b/contrib/gperf/src/options.h
@@ -2,154 +2,292 @@
/* Handles parsing the Options provided to the user.
- Copyright (C) 1989-1998, 2000 Free Software Foundation, Inc.
- written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+ Copyright (C) 1989-1998, 2000, 2002-2004 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
-This file is part of GNU GPERF.
+ 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 free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
-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.
+ 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. */
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* 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. */
+ to a user of the gperf hash function generator. */
#ifndef options_h
#define options_h 1
#include <stdio.h>
+#include "positions.h"
-/* Enumerate the potential debugging Options. */
+/* Enumeration of the possible boolean options. */
enum Option_Type
{
- DEBUG = 01, /* Enable debugging (prints diagnostics to stderr). */
- ORDER = 02, /* Apply ordering heuristic to speed-up search time. */
- 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. */
-};
+ /* --- Input file interpretation --- */
-/* 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... ;-( */
+ /* Handle user-defined type structured keyword input. */
+ TYPE = 1 << 0,
-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. */
+ /* Ignore case of ASCII characters. */
+ UPPERLOWER = 1 << 1,
+
+ /* --- Language for the output code --- */
+
+ /* Generate K&R C code: no prototypes, no const. */
+ KRC = 1 << 2,
+
+ /* Generate C code: no prototypes, but const (user can #define it away). */
+ C = 1 << 3,
+
+ /* Generate ISO/ANSI C code: prototypes and const, but no class. */
+ ANSIC = 1 << 4,
+
+ /* Generate C++ code: prototypes, const, class, inline, enum. */
+ CPLUSPLUS = 1 << 5,
+
+ /* --- Details in the output code --- */
+
+ /* Assume 7-bit, not 8-bit, characters. */
+ SEVENBIT = 1 << 6,
+
+ /* Generate a length table for string comparison. */
+ LENTABLE = 1 << 7,
+
+ /* Generate strncmp rather than strcmp. */
+ COMP = 1 << 8,
+
+ /* Make the generated tables readonly (const). */
+ CONST = 1 << 9,
+
+ /* Use enum for constants. */
+ ENUM = 1 << 10,
+
+ /* Generate #include statements. */
+ INCLUDE = 1 << 11,
+
+ /* Make the keyword table a global variable. */
+ GLOBAL = 1 << 12,
+
+ /* Use NULL strings instead of empty strings for empty table entries. */
+ NULLSTRINGS = 1 << 13,
+
+ /* Optimize for position-independent code. */
+ SHAREDLIB = 1 << 14,
+
+ /* Generate switch output to save space. */
+ SWITCH = 1 << 15,
+
+ /* Don't include user-defined type definition in output -- it's already
+ defined elsewhere. */
+ NOTYPE = 1 << 16,
+
+ /* --- Algorithm employed by gperf --- */
+
+ /* Use the given key positions. */
+ POSITIONS = 1 << 17,
+
+ /* Handle duplicate hash values for keywords. */
+ DUP = 1 << 18,
+
+ /* Don't include keyword length in hash computations. */
+ NOLENGTH = 1 << 19,
+
+ /* Randomly initialize the associated values table. */
+ RANDOM = 1 << 20,
+
+ /* --- Informative output --- */
+
+ /* Enable debugging (prints diagnostics to stderr). */
+ DEBUG = 1 << 21
};
-/* Class manager for gperf program Options. */
+/* Class manager for gperf program Options. */
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_initializer_suffix (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);
+ /* Constructor. */
+ Options ();
+
+ /* Destructor. */
+ ~Options ();
+
+ /* Parses the options given in the command-line arguments. */
+ void parse_options (int argc, char *argv[]);
+
+ /* Prints the given options. */
+ void print_options () const;
+
+ /* Accessors. */
+
+ /* Tests a given boolean option. Returns true if set, false otherwise. */
+ bool operator[] (Option_Type option) const;
+ /* Sets a given boolean option. */
+ void set (Option_Type option);
+
+ /* Returns the input file name. */
+ const char * get_input_file_name () const;
+
+ /* Returns the output file name. */
+ const char * get_output_file_name () const;
+
+ /* Sets the output language, if not already set. */
+ void set_language (const char *language);
+
+ /* Returns the jump value. */
+ int get_jump () const;
+
+ /* Returns the initial associated character value. */
+ int get_initial_asso_value () const;
+
+ /* Returns the number of iterations for finding good asso_values. */
+ int get_asso_iterations () const;
+
+ /* Returns the total number of switch statements to generate. */
+ int get_total_switches () const;
+ /* Sets the total number of switch statements, if not already set. */
+ void set_total_switches (int total_switches);
+
+ /* Returns the factor by which to multiply the generated table's size. */
+ float get_size_multiple () const;
+
+ /* Returns the generated function name. */
+ const char * get_function_name () const;
+ /* Sets the generated function name, if not already set. */
+ void set_function_name (const char *name);
+
+ /* Returns the keyword key name. */
+ const char * get_slot_name () const;
+ /* Sets the keyword key name, if not already set. */
+ void set_slot_name (const char *name);
+
+ /* Returns the struct initializer suffix. */
+ const char * get_initializer_suffix () const;
+ /* Sets the struct initializer suffix, if not already set. */
+ void set_initializer_suffix (const char *initializers);
+
+ /* Returns the generated class name. */
+ const char * get_class_name () const;
+ /* Sets the generated class name, if not already set. */
+ void set_class_name (const char *name);
+
+ /* Returns the hash function name. */
+ const char * get_hash_name () const;
+ /* Sets the hash function name, if not already set. */
+ void set_hash_name (const char *name);
+
+ /* Returns the hash table array name. */
+ const char * get_wordlist_name () const;
+ /* Sets the hash table array name, if not already set. */
+ void set_wordlist_name (const char *name);
+
+ /* Returns the length table array name. */
+ const char * get_lengthtable_name () const;
+ /* Sets the length table array name, if not already set. */
+ void set_lengthtable_name (const char *name);
+
+ /* Returns the string pool name. */
+ const char * get_stringpool_name () const;
+ /* Sets the string pool name, if not already set. */
+ void set_stringpool_name (const char *name);
+
+ /* Returns the string used to delimit keywords from other attributes. */
+ const char * get_delimiters () const;
+ /* Sets the delimiters string, if not already set. */
+ void set_delimiters (const char *delimiters);
+
+ /* Returns key positions. */
+ const Positions& get_key_positions () const;
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 *initializer_suffix; /* Suffix for empty struct initializers. */
- 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. */
-};
+ /* Prints program usage to given stream. */
+ static void short_usage (FILE * stream);
-/* Global option coordinator for the entire program. */
-extern Options option;
+ /* Prints program usage to given stream. */
+ static void long_usage (FILE * stream);
-/* 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
+ /* Records count of command-line arguments. */
+ int _argument_count;
-/* Set to 1 if the stack is large enough for holding a text line. */
-#ifndef LARGE_STACK
-#define LARGE_STACK 1
-#endif
+ /* Stores a pointer to command-line argument vector. */
+ char ** _argument_vector;
+
+ /* Holds the boolean options. */
+ int _option_word;
+
+ /* Name of input file. */
+ char * _input_file_name;
+
+ /* Name of output file. */
+ char * _output_file_name;
+
+ /* The output language. */
+ const char * _language;
+
+ /* Jump length when trying alternative values. */
+ int _jump;
+
+ /* Initial value for asso_values table. */
+ int _initial_asso_value;
+
+ /* Number of attempts at finding good asso_values. */
+ int _asso_iterations;
+
+ /* Number of switch statements to generate. */
+ int _total_switches;
+
+ /* Factor by which to multiply the generated table's size. */
+ float _size_multiple;
+
+ /* Names used for generated lookup function. */
+ const char * _function_name;
+
+ /* Name used for keyword key. */
+ const char * _slot_name;
+
+ /* Suffix for empty struct initializers. */
+ const char * _initializer_suffix;
+
+ /* Name used for generated C++ class. */
+ const char * _class_name;
+
+ /* Name used for generated hash function. */
+ const char * _hash_name;
+
+ /* Name used for hash table array. */
+ const char * _wordlist_name;
+
+ /* Name used for length table array. */
+ const char * _lengthtable_name;
+
+ /* Name used for the string pool. */
+ const char * _stringpool_name;
+
+ /* Separates keywords from other attributes. */
+ const char * _delimiters;
+
+ /* Contains user-specified key choices. */
+ Positions _key_positions;
+};
+
+/* Global option coordinator for the entire program. */
+extern Options option;
#ifdef __OPTIMIZE__
-#include "trace.h"
#define INLINE inline
#include "options.icc"
#undef INLINE
diff --git a/contrib/gperf/src/options.icc b/contrib/gperf/src/options.icc
index 82fe537..4188ddc 100644
--- a/contrib/gperf/src/options.icc
+++ b/contrib/gperf/src/options.icc
@@ -1,183 +1,157 @@
/* Inline Functions for options.{h,cc}.
- Copyright (C) 1989-1998, 2000 Free Software Foundation, Inc.
- written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+ Copyright (C) 1989-1998, 2000, 2002-2004 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
-This file is part of GNU GPERF.
+ 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 free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
-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.
+ 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. */
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-// This needs:
-//#include "trace.h"
+/* ----------------------------- Class Options ----------------------------- */
-/* TRUE if option enable, else FALSE. */
-INLINE int
-Options::operator[] (Option_Type option)
+/* Tests a given boolean option. Returns true if set, false otherwise. */
+INLINE bool
+Options::operator[] (Option_Type option) const
{
- T (Trace t ("Options::operator[]");)
- return option_word & option;
+ return _option_word & option;
}
-/* Enables option OPT. */
+/* Sets a given boolean option. */
INLINE void
-Options::operator = (enum Option_Type opt)
+Options::set (Option_Type option)
{
- T (Trace t ("Options::operator=");)
- option_word |= opt;
+ _option_word |= option;
}
-/* Disables option OPT. */
-INLINE void
-Options::operator != (enum Option_Type opt)
+/* Returns the input file name. */
+INLINE const char *
+Options::get_input_file_name () const
{
- T (Trace t ("Options::operator!=");)
- option_word &= ~opt;
+ return _input_file_name;
}
-/* Initializes the key Iterator. */
-INLINE void
-Options::reset (void)
+/* Returns the output file name. */
+INLINE const char *
+Options::get_output_file_name () const
{
- T (Trace t ("Options::reset");)
- key_pos = 0;
+ return _output_file_name;
}
-/* Returns current key_position and advance index. */
+/* Returns the jump value. */
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)
+Options::get_jump () const
{
- T (Trace t ("Options::set_asso_max");)
- size = r;
+ return _jump;
}
-/* Returns the size of the table size. */
+/* Returns the initial associated character value. */
INLINE int
-Options::get_asso_max (void)
+Options::get_initial_asso_value () const
{
- T (Trace t ("Options::get_asso_max");)
- return size;
+ return _initial_asso_value;
}
-/* Returns total distinct key positions. */
+/* Returns the number of iterations for finding finding good asso_values. */
INLINE int
-Options::get_max_keysig_size (void)
+Options::get_asso_iterations () const
{
- T (Trace t ("Options::get_max_keysig_size");)
- return total_keysig_size;
+ return _asso_iterations;
}
-/* Sets total distinct key positions. */
-INLINE void
-Options::set_keysig_size (int size)
+/* Returns the total number of switch statements to generate. */
+INLINE int
+Options::get_total_switches () const
{
- T (Trace t ("Options::set_keysig_size");)
- total_keysig_size = size;
+ return _total_switches;
}
-/* Returns the jump value. */
-INLINE int
-Options::get_jump (void)
+/* Returns the factor by which to multiply the generated table's size. */
+INLINE float
+Options::get_size_multiple () const
{
- T (Trace t ("Options::get_jump");)
- return jump;
+ return _size_multiple;
}
-/* Returns the generated function name. */
+/* Returns the generated function name. */
INLINE const char *
-Options::get_function_name (void)
+Options::get_function_name () const
{
- T (Trace t ("Options::get_function_name");)
- return function_name;
+ return _function_name;
}
-/* Returns the keyword key name. */
+/* Returns the keyword key name. */
INLINE const char *
-Options::get_key_name (void)
+Options::get_slot_name () const
{
- T (Trace t ("Options::get_key_name");)
- return key_name;
+ return _slot_name;
}
-/* Returns the struct initializer suffix. */
+/* Returns the struct initializer suffix. */
INLINE const char *
-Options::get_initializer_suffix (void)
+Options::get_initializer_suffix () const
{
- T (Trace t ("Options::get_initializer_suffix");)
- return initializer_suffix;
+ return _initializer_suffix;
}
-/* Returns the hash function name. */
+/* Returns the generated class name. */
INLINE const char *
-Options::get_hash_name (void)
+Options::get_class_name () const
{
- T (Trace t ("Options::get_hash_name");)
- return hash_name;
+ return _class_name;
}
-/* Returns the hash table array name. */
+/* Returns the hash function name. */
INLINE const char *
-Options::get_wordlist_name (void)
+Options::get_hash_name () const
{
- T (Trace t ("Options::get_wordlist_name");)
- return wordlist_name;
+ return _hash_name;
}
-/* Returns the generated class name. */
+/* Returns the hash table array name. */
INLINE const char *
-Options::get_class_name (void)
+Options::get_wordlist_name () const
{
- T (Trace t ("Options::get_class_name");)
- return class_name;
+ return _wordlist_name;
}
-/* Returns the initial associated character value. */
-INLINE int
-Options::initial_value (void)
+/* Returns the length table array name. */
+INLINE const char *
+Options::get_lengthtable_name () const
{
- T (Trace t ("Options::initial_value");)
- return initial_asso_value;
+ return _lengthtable_name;
}
-/* Returns the iterations value. */
-INLINE int
-Options::get_iterations (void)
+/* Returns the string pool name. */
+INLINE const char *
+Options::get_stringpool_name () const
{
- T (Trace t ("Options::get_iterations");)
- return iterations;
+ return _stringpool_name;
}
-/* Returns the string used to delimit keywords from other attributes. */
+/* Returns the string used to delimit keywords from other attributes. */
INLINE const char *
-Options::get_delimiter ()
+Options::get_delimiters () const
{
- T (Trace t ("Options::get_delimiter");)
- return delimiters;
+ return _delimiters;
}
-/* Gets the total number of switch statements to generate. */
-INLINE int
-Options::get_total_switches ()
+/* Returns key positions. */
+INLINE const Positions&
+Options::get_key_positions () const
{
- T (Trace t ("Options::get_total_switches");)
- return total_switches;
+ return _key_positions;
}
diff --git a/contrib/gperf/src/output.cc b/contrib/gperf/src/output.cc
new file mode 100644
index 0000000..c0c8e6c
--- /dev/null
+++ b/contrib/gperf/src/output.cc
@@ -0,0 +1,2100 @@
+/* Output routines.
+ Copyright (C) 1989-1998, 2000, 2002-2004, 2006-2007 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
+
+ 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 2, 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 this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Specification. */
+#include "output.h"
+
+#include <stdio.h>
+#include <string.h> /* declares strncpy(), strchr() */
+#include <ctype.h> /* declares isprint() */
+#include <assert.h> /* defines assert() */
+#include <limits.h> /* defines SCHAR_MAX etc. */
+#include "options.h"
+#include "version.h"
+
+/* 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";
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Constructor.
+ Note about the keyword list starting at head:
+ - The list is ordered by increasing _hash_value. This has been achieved
+ by Search::sort().
+ - Duplicates, i.e. keywords with the same _selchars set, are chained
+ through the _duplicate_link pointer. Only one representative per
+ duplicate equivalence class remains on the linear keyword list.
+ - Accidental duplicates, i.e. keywords for which the _asso_values[] search
+ couldn't achieve different hash values, cannot occur on the linear
+ keyword list. Search::optimize would catch this mistake.
+ */
+Output::Output (KeywordExt_List *head, const char *struct_decl,
+ unsigned int struct_decl_lineno, const char *return_type,
+ const char *struct_tag, const char *verbatim_declarations,
+ const char *verbatim_declarations_end,
+ unsigned int verbatim_declarations_lineno,
+ const char *verbatim_code, const char *verbatim_code_end,
+ unsigned int verbatim_code_lineno, bool charset_dependent,
+ int total_keys, int max_key_len, int min_key_len,
+ const Positions& positions, const unsigned int *alpha_inc,
+ int total_duplicates, unsigned int alpha_size,
+ const int *asso_values)
+ : _head (head), _struct_decl (struct_decl),
+ _struct_decl_lineno (struct_decl_lineno), _return_type (return_type),
+ _struct_tag (struct_tag),
+ _verbatim_declarations (verbatim_declarations),
+ _verbatim_declarations_end (verbatim_declarations_end),
+ _verbatim_declarations_lineno (verbatim_declarations_lineno),
+ _verbatim_code (verbatim_code),
+ _verbatim_code_end (verbatim_code_end),
+ _verbatim_code_lineno (verbatim_code_lineno),
+ _charset_dependent (charset_dependent),
+ _total_keys (total_keys),
+ _max_key_len (max_key_len), _min_key_len (min_key_len),
+ _key_positions (positions), _alpha_inc (alpha_inc),
+ _total_duplicates (total_duplicates), _alpha_size (alpha_size),
+ _asso_values (asso_values)
+{
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Computes the minimum and maximum hash values, and stores them
+ in _min_hash_value and _max_hash_value. */
+
+void
+Output::compute_min_max ()
+{
+ /* Since the list is already sorted by hash value all we need to do is
+ to look at the first and the last element of the list. */
+
+ _min_hash_value = _head->first()->_hash_value;
+
+ KeywordExt_List *temp;
+ for (temp = _head; temp->rest(); temp = temp->rest())
+ ;
+ _max_hash_value = temp->first()->_hash_value;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Returns the number of different hash values. */
+
+int
+Output::num_hash_values () const
+{
+ /* Since the list is already sorted by hash value and doesn't contain
+ duplicates, we can simply count the number of keywords on the list. */
+ int count = 0;
+ for (KeywordExt_List *temp = _head; temp; temp = temp->rest())
+ 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 ()
+{
+ printf ("\n");
+}
+
+void Output_Defines::output_item (const char *name, int value)
+{
+ printf ("#define %s %d\n", name, value);
+}
+
+void 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;
+ bool _pending_comma;
+};
+
+void Output_Enum::output_start ()
+{
+ printf ("%senum\n"
+ "%s {\n",
+ _indentation, _indentation);
+ _pending_comma = false;
+}
+
+void Output_Enum::output_item (const char *name, int value)
+{
+ if (_pending_comma)
+ printf (",\n");
+ printf ("%s %s = %d", _indentation, name, value);
+ _pending_comma = true;
+}
+
+void Output_Enum::output_end ()
+{
+ if (_pending_comma)
+ printf ("\n");
+ printf ("%s };\n\n", _indentation);
+}
+
+/* Outputs the maximum and minimum hash values etc. */
+
+void
+Output::output_constants (struct Output_Constants& style) const
+{
+ 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 ();
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* We use a downcase table because when called repeatedly, the code
+ gperf_downcase[c]
+ is faster than
+ if (c >= 'A' && c <= 'Z')
+ c += 'a' - 'A';
+ */
+#define USE_DOWNCASE_TABLE 1
+
+#if USE_DOWNCASE_TABLE
+
+/* Output gperf's ASCII-downcase table. */
+
+static void
+output_upperlower_table ()
+{
+ unsigned int c;
+
+ printf ("#ifndef GPERF_DOWNCASE\n"
+ "#define GPERF_DOWNCASE 1\n"
+ "static unsigned char gperf_downcase[256] =\n"
+ " {");
+ for (c = 0; c < 256; c++)
+ {
+ if ((c % 15) == 0)
+ printf ("\n ");
+ printf (" %3d", c >= 'A' && c <= 'Z' ? c + 'a' - 'A' : c);
+ if (c < 255)
+ printf (",");
+ }
+ printf ("\n"
+ " };\n"
+ "#endif\n\n");
+}
+
+#endif
+
+/* Output gperf's ASCII-case insensitive strcmp replacement. */
+
+static void
+output_upperlower_strcmp ()
+{
+ printf ("#ifndef GPERF_CASE_STRCMP\n"
+ "#define GPERF_CASE_STRCMP 1\n"
+ "static int\n"
+ "gperf_case_strcmp ");
+ printf (option[KRC] ?
+ "(s1, s2)\n"
+ " register char *s1;\n"
+ " register char *s2;\n" :
+ option[C] ?
+ "(s1, s2)\n"
+ " register const char *s1;\n"
+ " register const char *s2;\n" :
+ option[ANSIC] | option[CPLUSPLUS] ?
+ "(register const char *s1, register const char *s2)\n" :
+ "");
+ #if USE_DOWNCASE_TABLE
+ printf ("{\n"
+ " for (;;)\n"
+ " {\n"
+ " unsigned char c1 = gperf_downcase[(unsigned char)*s1++];\n"
+ " unsigned char c2 = gperf_downcase[(unsigned char)*s2++];\n"
+ " if (c1 != 0 && c1 == c2)\n"
+ " continue;\n"
+ " return (int)c1 - (int)c2;\n"
+ " }\n"
+ "}\n");
+ #else
+ printf ("{\n"
+ " for (;;)\n"
+ " {\n"
+ " unsigned char c1 = *s1++;\n"
+ " unsigned char c2 = *s2++;\n"
+ " if (c1 >= 'A' && c1 <= 'Z')\n"
+ " c1 += 'a' - 'A';\n"
+ " if (c2 >= 'A' && c2 <= 'Z')\n"
+ " c2 += 'a' - 'A';\n"
+ " if (c1 != 0 && c1 == c2)\n"
+ " continue;\n"
+ " return (int)c1 - (int)c2;\n"
+ " }\n"
+ "}\n");
+ #endif
+ printf ("#endif\n\n");
+}
+
+/* Output gperf's ASCII-case insensitive strncmp replacement. */
+
+static void
+output_upperlower_strncmp ()
+{
+ printf ("#ifndef GPERF_CASE_STRNCMP\n"
+ "#define GPERF_CASE_STRNCMP 1\n"
+ "static int\n"
+ "gperf_case_strncmp ");
+ printf (option[KRC] ?
+ "(s1, s2, n)\n"
+ " register char *s1;\n"
+ " register char *s2;\n"
+ " register unsigned int n;\n" :
+ option[C] ?
+ "(s1, s2, n)\n"
+ " register const char *s1;\n"
+ " register const char *s2;\n"
+ " register unsigned int n;\n" :
+ option[ANSIC] | option[CPLUSPLUS] ?
+ "(register const char *s1, register const char *s2, register unsigned int n)\n" :
+ "");
+ #if USE_DOWNCASE_TABLE
+ printf ("{\n"
+ " for (; n > 0;)\n"
+ " {\n"
+ " unsigned char c1 = gperf_downcase[(unsigned char)*s1++];\n"
+ " unsigned char c2 = gperf_downcase[(unsigned char)*s2++];\n"
+ " if (c1 != 0 && c1 == c2)\n"
+ " {\n"
+ " n--;\n"
+ " continue;\n"
+ " }\n"
+ " return (int)c1 - (int)c2;\n"
+ " }\n"
+ " return 0;\n"
+ "}\n");
+ #else
+ printf ("{\n"
+ " for (; n > 0;)\n"
+ " {\n"
+ " unsigned char c1 = *s1++;\n"
+ " unsigned char c2 = *s2++;\n"
+ " if (c1 >= 'A' && c1 <= 'Z')\n"
+ " c1 += 'a' - 'A';\n"
+ " if (c2 >= 'A' && c2 <= 'Z')\n"
+ " c2 += 'a' - 'A';\n"
+ " if (c1 != 0 && c1 == c2)\n"
+ " {\n"
+ " n--;\n"
+ " continue;\n"
+ " }\n"
+ " return (int)c1 - (int)c2;\n"
+ " }\n"
+ " return 0;\n"
+ "}\n");
+ #endif
+ printf ("#endif\n\n");
+}
+
+/* Output gperf's ASCII-case insensitive memcmp replacement. */
+
+static void
+output_upperlower_memcmp ()
+{
+ printf ("#ifndef GPERF_CASE_MEMCMP\n"
+ "#define GPERF_CASE_MEMCMP 1\n"
+ "static int\n"
+ "gperf_case_memcmp ");
+ printf (option[KRC] ?
+ "(s1, s2, n)\n"
+ " register char *s1;\n"
+ " register char *s2;\n"
+ " register unsigned int n;\n" :
+ option[C] ?
+ "(s1, s2, n)\n"
+ " register const char *s1;\n"
+ " register const char *s2;\n"
+ " register unsigned int n;\n" :
+ option[ANSIC] | option[CPLUSPLUS] ?
+ "(register const char *s1, register const char *s2, register unsigned int n)\n" :
+ "");
+ #if USE_DOWNCASE_TABLE
+ printf ("{\n"
+ " for (; n > 0;)\n"
+ " {\n"
+ " unsigned char c1 = gperf_downcase[(unsigned char)*s1++];\n"
+ " unsigned char c2 = gperf_downcase[(unsigned char)*s2++];\n"
+ " if (c1 == c2)\n"
+ " {\n"
+ " n--;\n"
+ " continue;\n"
+ " }\n"
+ " return (int)c1 - (int)c2;\n"
+ " }\n"
+ " return 0;\n"
+ "}\n");
+ #else
+ printf ("{\n"
+ " for (; n > 0;)\n"
+ " {\n"
+ " unsigned char c1 = *s1++;\n"
+ " unsigned char c2 = *s2++;\n"
+ " if (c1 >= 'A' && c1 <= 'Z')\n"
+ " c1 += 'a' - 'A';\n"
+ " if (c2 >= 'A' && c2 <= 'Z')\n"
+ " c2 += 'a' - 'A';\n"
+ " if (c1 == c2)\n"
+ " {\n"
+ " n--;\n"
+ " continue;\n"
+ " }\n"
+ " return (int)c1 - (int)c2;\n"
+ " }\n"
+ " return 0;\n"
+ "}\n");
+ #endif
+ printf ("#endif\n\n");
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Outputs a keyword, as a string: enclosed in double quotes, escaping
+ backslashes, double quote and unprintable characters. */
+
+static void
+output_string (const char *key, int len)
+{
+ putchar ('"');
+ for (; len > 0; len--)
+ {
+ unsigned char c = static_cast<unsigned char>(*key++);
+ if (isprint (c))
+ {
+ if (c == '"' || c == '\\')
+ putchar ('\\');
+ putchar (c);
+ }
+ else
+ {
+ /* Use octal escapes, not hexadecimal escapes, because some old
+ C compilers didn't understand hexadecimal escapes, and because
+ hexadecimal escapes are not limited to 2 digits, thus needing
+ special care if the following character happens to be a digit. */
+ putchar ('\\');
+ putchar ('0' + ((c >> 6) & 7));
+ putchar ('0' + ((c >> 3) & 7));
+ putchar ('0' + (c & 7));
+ }
+ }
+ putchar ('"');
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Outputs a #line directive, referring to the given line number. */
+
+static void
+output_line_directive (unsigned int lineno)
+{
+ const char *file_name = option.get_input_file_name ();
+ if (file_name != NULL)
+ {
+ printf ("#line %u ", lineno);
+ output_string (file_name, strlen (file_name));
+ printf ("\n");
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Outputs a type and a const specifier (i.e. "const " or "").
+ 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] == '*')
+ /* For pointer types, put the 'const' after the type. */
+ printf ("%s %s", type_string, const_string);
+ else
+ /* For scalar or struct types, put the 'const' before the type. */
+ 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
+{
+ 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
+{
+ printf ("%s%s", _p1, _p2);
+}
+
+#endif
+
+/* --------------------- Output_Compare and subclasses --------------------- */
+
+/* This class outputs a comparison expression. */
+
+struct Output_Compare
+{
+ /* Outputs the comparison expression.
+ expr1 outputs a simple expression of type 'const char *' referring to
+ the string being looked up. expr2 outputs a simple expression of type
+ 'const char *' referring to the constant string stored in the gperf
+ generated hash table. */
+ virtual void output_comparison (const Output_Expr& expr1,
+ const Output_Expr& expr2) const = 0;
+ /* Outputs the comparison expression for the first byte.
+ Returns true if the this comparison is complete. */
+ bool output_firstchar_comparison (const Output_Expr& expr1,
+ const Output_Expr& expr2) const;
+ Output_Compare () {}
+ virtual ~Output_Compare () {}
+};
+
+bool Output_Compare::output_firstchar_comparison (const Output_Expr& expr1,
+ const Output_Expr& expr2) const
+{
+ /* First, we emit a comparison of the first byte of the two strings.
+ This catches most cases where the string being looked up is not in the
+ hash table but happens to have the same hash code as an element of the
+ hash table. */
+ if (option[UPPERLOWER])
+ {
+ /* Incomplete comparison, just for speedup. */
+ printf ("(((unsigned char)*");
+ expr1.output_expr ();
+ printf (" ^ (unsigned char)*");
+ expr2.output_expr ();
+ printf (") & ~32) == 0");
+ return false;
+ }
+ else
+ {
+ /* Complete comparison. */
+ printf ("*");
+ expr1.output_expr ();
+ printf (" == *");
+ expr2.output_expr ();
+ return true;
+ }
+}
+
+/* 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
+{
+ bool firstchar_done = output_firstchar_comparison (expr1, expr2);
+ printf (" && !");
+ if (option[UPPERLOWER])
+ printf ("gperf_case_");
+ printf ("strcmp (");
+ if (firstchar_done)
+ {
+ expr1.output_expr ();
+ printf (" + 1, ");
+ expr2.output_expr ();
+ printf (" + 1");
+ }
+ else
+ {
+ expr1.output_expr ();
+ printf (", ");
+ expr2.output_expr ();
+ }
+ printf (")");
+}
+
+/* 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
+{
+ bool firstchar_done = output_firstchar_comparison (expr1, expr2);
+ printf (" && !");
+ if (option[UPPERLOWER])
+ printf ("gperf_case_");
+ printf ("strncmp (");
+ if (firstchar_done)
+ {
+ expr1.output_expr ();
+ printf (" + 1, ");
+ expr2.output_expr ();
+ printf (" + 1, len - 1");
+ }
+ else
+ {
+ expr1.output_expr ();
+ printf (", ");
+ expr2.output_expr ();
+ printf (", len");
+ }
+ printf (") && ");
+ expr2.output_expr ();
+ printf ("[len] == '\\0'");
+}
+
+/* This class outputs a comparison using memcmp.
+ Note that the length of expr1 (available through the local variable 'len')
+ must be verified to be equal to the length of expr2 prior to this
+ comparison. */
+
+struct Output_Compare_Memcmp : public Output_Compare
+{
+ virtual void output_comparison (const Output_Expr& expr1,
+ const Output_Expr& expr2) const;
+ Output_Compare_Memcmp () {}
+ virtual ~Output_Compare_Memcmp () {}
+};
+
+void Output_Compare_Memcmp::output_comparison (const Output_Expr& expr1,
+ const Output_Expr& expr2) const
+{
+ bool firstchar_done = output_firstchar_comparison (expr1, expr2);
+ printf (" && !");
+ if (option[UPPERLOWER])
+ printf ("gperf_case_");
+ printf ("memcmp (");
+ if (firstchar_done)
+ {
+ expr1.output_expr ();
+ printf (" + 1, ");
+ expr2.output_expr ();
+ printf (" + 1, len - 1");
+ }
+ else
+ {
+ expr1.output_expr ();
+ printf (", ");
+ expr2.output_expr ();
+ printf (", len");
+ }
+ printf (")");
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Generates a C expression for an asso_values[] reference. */
+
+void
+Output::output_asso_values_ref (int pos) const
+{
+ printf ("asso_values[");
+ /* Always cast to unsigned char. This is necessary when the alpha_inc
+ is nonzero, and also avoids a gcc warning "subscript has type 'char'". */
+ printf ("(unsigned char)");
+ if (pos == Positions::LASTCHAR)
+ printf ("str[len - 1]");
+ else
+ {
+ printf ("str[%d]", pos);
+ if (_alpha_inc[pos])
+ printf ("+%u", _alpha_inc[pos]);
+ }
+ printf ("]");
+}
+
+/* Generates C code for the hash function that returns the
+ proper encoding for each keyword.
+ The hash function has the signature
+ unsigned int <hash> (const char *str, unsigned int len). */
+
+void
+Output::output_hash_function () const
+{
+ /* Output the function's head. */
+ if (option[CPLUSPLUS])
+ printf ("inline ");
+ else if (option[KRC] | option[C] | option[ANSIC])
+ printf ("#ifdef __GNUC__\n"
+ "__inline\n"
+ "#else\n"
+ "#ifdef __cplusplus\n"
+ "inline\n"
+ "#endif\n"
+ "#endif\n");
+
+ if (/* The function does not use the 'str' argument? */
+ _key_positions.get_size() == 0
+ || /* The function uses 'str', but not the 'len' argument? */
+ (option[NOLENGTH]
+ && _key_positions[0] < _min_key_len
+ && _key_positions[_key_positions.get_size() - 1] != Positions::LASTCHAR))
+ /* Pacify lint. */
+ printf ("/*ARGSUSED*/\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. */
+ if (_key_positions.get_size() > 0)
+ {
+ printf (" static %s%s asso_values[] =\n"
+ " {",
+ const_readonly_array,
+ smallest_integral_type (_max_hash_value + 1));
+
+ const int columns = 10;
+
+ /* Calculate maximum number of digits required for MAX_HASH_VALUE. */
+ int field_width = 2;
+ for (int trunc = _max_hash_value; (trunc /= 10) > 0;)
+ field_width++;
+
+ for (unsigned int count = 0; count < _alpha_size; count++)
+ {
+ if (count > 0)
+ printf (",");
+ if ((count % columns) == 0)
+ printf ("\n ");
+ printf ("%*d", field_width, _asso_values[count]);
+ }
+
+ printf ("\n"
+ " };\n");
+ }
+
+ if (_key_positions.get_size() == 0)
+ {
+ /* Trivial case: No key positions at all. */
+ printf (" return %s;\n",
+ option[NOLENGTH] ? "0" : "len");
+ }
+ else
+ {
+ /* Iterate through the key positions. Remember that Positions::sort()
+ has sorted them in decreasing order, with Positions::LASTCHAR coming
+ last. */
+ PositionIterator iter = _key_positions.iterator(_max_key_len);
+ int key_pos;
+
+ /* Get the highest key position. */
+ key_pos = iter.next ();
+
+ if (key_pos == Positions::LASTCHAR || 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 + ");
+
+ if (_key_positions.get_size() == 2
+ && _key_positions[0] == 0
+ && _key_positions[1] == Positions::LASTCHAR)
+ /* Optimize special case of "-k 1,$". */
+ {
+ output_asso_values_ref (Positions::LASTCHAR);
+ printf (" + ");
+ output_asso_values_ref (0);
+ }
+ else
+ {
+ for (; key_pos != Positions::LASTCHAR; )
+ {
+ output_asso_values_ref (key_pos);
+ if ((key_pos = iter.next ()) != PositionIterator::EOS)
+ printf (" + ");
+ else
+ break;
+ }
+
+ if (key_pos == Positions::LASTCHAR)
+ output_asso_values_ref (Positions::LASTCHAR);
+ }
+
+ 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");
+
+ while (key_pos != Positions::LASTCHAR && key_pos >= _max_key_len)
+ if ((key_pos = iter.next ()) == PositionIterator::EOS)
+ break;
+
+ if (key_pos != PositionIterator::EOS && key_pos != Positions::LASTCHAR)
+ {
+ int i = key_pos;
+ do
+ {
+ if (i > key_pos)
+ printf (" /*FALLTHROUGH*/\n"); /* Pacify lint. */
+ for ( ; i > key_pos; i--)
+ printf (" case %d:\n", i);
+
+ printf (" hval += ");
+ output_asso_values_ref (key_pos);
+ printf (";\n");
+
+ key_pos = iter.next ();
+ }
+ while (key_pos != PositionIterator::EOS && key_pos != Positions::LASTCHAR);
+
+ if (i >= _min_key_len)
+ printf (" /*FALLTHROUGH*/\n"); /* Pacify lint. */
+ for ( ; i >= _min_key_len; i--)
+ printf (" case %d:\n", i);
+ }
+
+ printf (" break;\n"
+ " }\n"
+ " return hval");
+ if (key_pos == Positions::LASTCHAR)
+ {
+ printf (" + ");
+ output_asso_values_ref (Positions::LASTCHAR);
+ }
+ printf (";\n");
+ }
+ }
+ printf ("}\n\n");
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Prints out a table of keyword lengths, for use with the
+ comparison code in generated function 'in_word_set'.
+ Only called if option[LENTABLE]. */
+
+void
+Output::output_keylength_table () const
+{
+ const int columns = 14;
+ const char * const indent = option[GLOBAL] ? "" : " ";
+
+ printf ("%sstatic %s%s %s[] =\n"
+ "%s {",
+ indent, const_readonly_array,
+ smallest_integral_type (_max_key_len),
+ option.get_lengthtable_name (),
+ indent);
+
+ /* Generate an array of lengths, similar to output_keyword_table. */
+ int index;
+ int column;
+ KeywordExt_List *temp;
+
+ column = 0;
+ for (temp = _head, index = 0; temp; temp = temp->rest())
+ {
+ KeywordExt *keyword = temp->first();
+
+ /* If generating a switch statement, and there is no user defined type,
+ we generate non-duplicates directly in the code. Only duplicates go
+ into the table. */
+ if (option[SWITCH] && !option[TYPE] && !keyword->_duplicate_link)
+ continue;
+
+ if (index < keyword->_hash_value && !option[SWITCH] && !option[DUP])
+ {
+ /* Some blank entries. */
+ for ( ; index < keyword->_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", keyword->_allchars_length);
+ index++;
+
+ /* Deal with duplicates specially. */
+ if (keyword->_duplicate_link) // implies option[DUP]
+ for (KeywordExt *links = keyword->_duplicate_link; links; links = links->_duplicate_link)
+ {
+ printf (",");
+ if ((column++ % columns) == 0)
+ printf("\n%s ", indent);
+ printf ("%3d", links->_allchars_length);
+ index++;
+ }
+ }
+
+ printf ("\n%s };\n", indent);
+ if (option[GLOBAL])
+ printf ("\n");
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Prints out the string pool, containing the strings of the keyword table.
+ Only called if option[SHAREDLIB]. */
+
+void
+Output::output_string_pool () const
+{
+ const char * const indent = option[TYPE] || option[GLOBAL] ? "" : " ";
+ int index;
+ KeywordExt_List *temp;
+
+ printf ("%sstruct %s_t\n"
+ "%s {\n",
+ indent, option.get_stringpool_name (), indent);
+ for (temp = _head, index = 0; temp; temp = temp->rest())
+ {
+ KeywordExt *keyword = temp->first();
+
+ /* If generating a switch statement, and there is no user defined type,
+ we generate non-duplicates directly in the code. Only duplicates go
+ into the table. */
+ if (option[SWITCH] && !option[TYPE] && !keyword->_duplicate_link)
+ continue;
+
+ if (!option[SWITCH] && !option[DUP])
+ index = keyword->_hash_value;
+
+ printf ("%s char %s_str%d[sizeof(",
+ indent, option.get_stringpool_name (), index);
+ output_string (keyword->_allchars, keyword->_allchars_length);
+ printf (")];\n");
+
+ /* Deal with duplicates specially. */
+ if (keyword->_duplicate_link) // implies option[DUP]
+ for (KeywordExt *links = keyword->_duplicate_link; links; links = links->_duplicate_link)
+ if (!(links->_allchars_length == keyword->_allchars_length
+ && memcmp (links->_allchars, keyword->_allchars,
+ keyword->_allchars_length) == 0))
+ {
+ index++;
+ printf ("%s char %s_str%d[sizeof(",
+ indent, option.get_stringpool_name (), index);
+ output_string (links->_allchars, links->_allchars_length);
+ printf (")];\n");
+ }
+
+ index++;
+ }
+ printf ("%s };\n",
+ indent);
+
+ printf ("%sstatic %sstruct %s_t %s_contents =\n"
+ "%s {\n",
+ indent, const_readonly_array, option.get_stringpool_name (),
+ option.get_stringpool_name (), indent);
+ for (temp = _head, index = 0; temp; temp = temp->rest())
+ {
+ KeywordExt *keyword = temp->first();
+
+ /* If generating a switch statement, and there is no user defined type,
+ we generate non-duplicates directly in the code. Only duplicates go
+ into the table. */
+ if (option[SWITCH] && !option[TYPE] && !keyword->_duplicate_link)
+ continue;
+
+ if (index > 0)
+ printf (",\n");
+
+ if (!option[SWITCH] && !option[DUP])
+ index = keyword->_hash_value;
+
+ printf ("%s ",
+ indent);
+ output_string (keyword->_allchars, keyword->_allchars_length);
+
+ /* Deal with duplicates specially. */
+ if (keyword->_duplicate_link) // implies option[DUP]
+ for (KeywordExt *links = keyword->_duplicate_link; links; links = links->_duplicate_link)
+ if (!(links->_allchars_length == keyword->_allchars_length
+ && memcmp (links->_allchars, keyword->_allchars,
+ keyword->_allchars_length) == 0))
+ {
+ index++;
+ printf (",\n");
+ printf ("%s ",
+ indent);
+ output_string (links->_allchars, links->_allchars_length);
+ }
+
+ index++;
+ }
+ if (index > 0)
+ printf ("\n");
+ printf ("%s };\n",
+ indent);
+ printf ("%s#define %s ((%schar *) &%s_contents)\n",
+ indent, option.get_stringpool_name (), const_always,
+ option.get_stringpool_name ());
+ if (option[GLOBAL])
+ printf ("\n");
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void
+output_keyword_entry (KeywordExt *temp, int stringpool_index, const char *indent)
+{
+ if (option[TYPE])
+ output_line_directive (temp->_lineno);
+ printf ("%s ", indent);
+ if (option[TYPE])
+ printf ("{");
+ if (option[SHAREDLIB])
+ printf ("(int)(long)&((struct %s_t *)0)->%s_str%d",
+ option.get_stringpool_name (), option.get_stringpool_name (),
+ stringpool_index);
+ else
+ output_string (temp->_allchars, temp->_allchars_length);
+ if (option[TYPE])
+ {
+ if (strlen (temp->_rest) > 0)
+ printf (",%s", temp->_rest);
+ printf ("}");
+ }
+ if (option[DEBUG])
+ printf (" /* hash value = %d, index = %d */",
+ temp->_hash_value, temp->_final_index);
+}
+
+static void
+output_keyword_blank_entries (int count, const char *indent)
+{
+ int columns;
+ if (option[TYPE])
+ {
+ columns = 58 / (4 + (option[SHAREDLIB] ? 2 : option[NULLSTRINGS] ? 8 : 2)
+ + strlen (option.get_initializer_suffix()));
+ if (columns == 0)
+ columns = 1;
+ }
+ else
+ {
+ columns = (option[SHAREDLIB] ? 9 : option[NULLSTRINGS] ? 4 : 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 ("{");
+ if (option[SHAREDLIB])
+ printf ("-1");
+ else
+ {
+ if (option[NULLSTRINGS])
+ printf ("(char*)0");
+ else
+ printf ("\"\"");
+ }
+ if (option[TYPE])
+ printf ("%s}", option.get_initializer_suffix());
+ column++;
+ }
+}
+
+/* Prints out the array containing the keywords for the hash function. */
+
+void
+Output::output_keyword_table () const
+{
+ const char *indent = option[GLOBAL] ? "" : " ";
+ int index;
+ KeywordExt_List *temp;
+
+ printf ("%sstatic ",
+ indent);
+ output_const_type (const_readonly_array, _wordlist_eltype);
+ 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->rest())
+ {
+ KeywordExt *keyword = temp->first();
+
+ /* If generating a switch statement, and there is no user defined type,
+ we generate non-duplicates directly in the code. Only duplicates go
+ into the table. */
+ if (option[SWITCH] && !option[TYPE] && !keyword->_duplicate_link)
+ continue;
+
+ if (index > 0)
+ printf (",\n");
+
+ if (index < keyword->_hash_value && !option[SWITCH] && !option[DUP])
+ {
+ /* Some blank entries. */
+ output_keyword_blank_entries (keyword->_hash_value - index, indent);
+ printf (",\n");
+ index = keyword->_hash_value;
+ }
+
+ keyword->_final_index = index;
+
+ output_keyword_entry (keyword, index, indent);
+
+ /* Deal with duplicates specially. */
+ if (keyword->_duplicate_link) // implies option[DUP]
+ for (KeywordExt *links = keyword->_duplicate_link; links; links = links->_duplicate_link)
+ {
+ links->_final_index = ++index;
+ printf (",\n");
+ int stringpool_index =
+ (links->_allchars_length == keyword->_allchars_length
+ && memcmp (links->_allchars, keyword->_allchars,
+ keyword->_allchars_length) == 0
+ ? keyword->_final_index
+ : links->_final_index);
+ output_keyword_entry (links, stringpool_index, 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
+Output::output_lookup_array () const
+{
+ 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. */
+ };
+
+ duplicate_entry *duplicates = new duplicate_entry[_total_duplicates];
+ int *lookup_array = new int[_max_hash_value + 1 + 2*_total_duplicates];
+ 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 (KeywordExt_List *temp = _head; temp; temp = temp->rest())
+ {
+ int hash_value = temp->first()->_hash_value;
+ lookup_array[hash_value] = temp->first()->_final_index;
+ if (option[DEBUG])
+ fprintf (stderr, "keyword = %.*s, index = %d\n",
+ temp->first()->_allchars_length, temp->first()->_allchars, temp->first()->_final_index);
+ if (temp->first()->_duplicate_link)
+ {
+ /* Start a duplicate entry. */
+ dup_ptr->hash_value = hash_value;
+ dup_ptr->index = temp->first()->_final_index;
+ dup_ptr->count = 1;
+
+ for (KeywordExt *ptr = temp->first()->_duplicate_link; ptr; ptr = ptr->_duplicate_link)
+ {
+ dup_ptr->count++;
+ if (option[DEBUG])
+ fprintf (stderr,
+ "static linked keyword = %.*s, index = %d\n",
+ ptr->_allchars_length, ptr->_allchars, ptr->_final_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->_final_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);
+
+ delete[] duplicates;
+ delete[] lookup_array;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Generate all pools needed for the lookup function. */
+
+void
+Output::output_lookup_pools () const
+{
+ if (option[SWITCH])
+ {
+ if (option[TYPE] || (option[DUP] && _total_duplicates > 0))
+ output_string_pool ();
+ }
+ else
+ {
+ output_string_pool ();
+ }
+}
+
+/* Generate all the tables needed for the lookup function. */
+
+void
+Output::output_lookup_tables () const
+{
+ 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 KeywordExt_List *
+output_switch_case (KeywordExt_List *list, int indent, int *jumps_away)
+{
+ if (option[DEBUG])
+ printf ("%*s/* hash value = %4d, keyword = \"%.*s\" */\n",
+ indent, "", list->first()->_hash_value, list->first()->_allchars_length, list->first()->_allchars);
+
+ if (option[DUP] && list->first()->_duplicate_link)
+ {
+ if (option[LENTABLE])
+ printf ("%*slengthptr = &%s[%d];\n",
+ indent, "", option.get_lengthtable_name (), list->first()->_final_index);
+ printf ("%*swordptr = &%s[%d];\n",
+ indent, "", option.get_wordlist_name (), list->first()->_final_index);
+
+ int count = 0;
+ for (KeywordExt *links = list->first(); links; links = links->_duplicate_link)
+ count++;
+
+ 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->first()->_allchars_length,
+ indent, "");
+ indent += 4;
+ }
+ printf ("%*sresword = ",
+ indent, "");
+ if (option[TYPE])
+ printf ("&%s[%d]", option.get_wordlist_name (), list->first()->_final_index);
+ else
+ output_string (list->first()->_allchars, list->first()->_allchars_length);
+ printf (";\n");
+ printf ("%*sgoto compare;\n",
+ indent, "");
+ if (option[LENTABLE])
+ {
+ indent -= 4;
+ printf ("%*s }\n",
+ indent, "");
+ }
+ else
+ *jumps_away = 1;
+ }
+
+ return list->rest();
+}
+
+/* Output a total of size cases, grouped into num_switches switch statements,
+ where 0 < num_switches <= size. */
+
+static void
+output_switches (KeywordExt_List *list, int num_switches, int size, int min_hash_value, int max_hash_value, int indent)
+{
+ 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 = static_cast<int>(static_cast<double>(size) / static_cast<double>(num_switches) * static_cast<double>(part1) + 0.5);
+ int size2 = size - size1;
+
+ KeywordExt_List *temp = list;
+ for (int count = size1; count > 0; count--)
+ temp = temp->rest();
+
+ printf ("%*sif (key < %d)\n"
+ "%*s {\n",
+ indent, "", temp->first()->_hash_value,
+ indent, "");
+
+ output_switches (list, part1, size1, min_hash_value, temp->first()->_hash_value-1, indent+4);
+
+ printf ("%*s }\n"
+ "%*selse\n"
+ "%*s {\n",
+ indent, "", indent, "", indent, "");
+
+ output_switches (temp, part2, size2, temp->first()->_hash_value, max_hash_value, indent+4);
+
+ printf ("%*s }\n",
+ indent, "");
+ }
+ else
+ {
+ /* Output a single switch. */
+ int lowest_case_value = list->first()->_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->first()->_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
+Output::output_lookup_function_body (const Output_Compare& comparison) const
+{
+ 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] && _total_duplicates > 0)
+ {
+ 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, _wordlist_eltype);
+ printf ("*wordptr;\n");
+ printf (" register ");
+ output_const_type (const_readonly_array, _wordlist_eltype);
+ 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);
+
+ printf (" return 0;\n");
+ if (option[DUP] && _total_duplicates > 0)
+ {
+ int indent = 8;
+ printf ("%*smulticompare:\n"
+ "%*s while (wordptr < wordendptr)\n"
+ "%*s {\n",
+ 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_slot_name ());
+ else
+ printf ("*wordptr");
+ if (option[SHAREDLIB])
+ printf (" + %s",
+ option.get_stringpool_name ());
+ 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 return 0;\n",
+ indent, "", indent, "", indent, "");
+ }
+ printf (" compare:\n");
+ if (option[TYPE])
+ {
+ printf (" {\n"
+ " register %schar *s = resword->%s",
+ const_always, option.get_slot_name ());
+ if (option[SHAREDLIB])
+ printf (" + %s",
+ option.get_stringpool_name ());
+ printf (";\n\n"
+ " if (");
+ 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 == %s[index])\n",
+ indent, "", indent, "", option.get_lengthtable_name ());
+ 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_slot_name ());
+ if (option[SHAREDLIB])
+ printf (" + %s",
+ option.get_stringpool_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, "");
+ }
+ if (_total_duplicates > 0)
+ {
+ 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 = &%s[TOTAL_KEYWORDS + lookup[offset]];\n",
+ indent, "", const_always, smallest_integral_type (_max_key_len),
+ option.get_lengthtable_name ());
+ printf ("%*s register ",
+ indent, "");
+ output_const_type (const_readonly_array, _wordlist_eltype);
+ printf ("*wordptr = &%s[TOTAL_KEYWORDS + lookup[offset]];\n",
+ option.get_wordlist_name ());
+ printf ("%*s register ",
+ indent, "");
+ output_const_type (const_readonly_array, _wordlist_eltype);
+ 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_slot_name ());
+ else
+ printf ("*wordptr");
+ if (option[SHAREDLIB])
+ printf (" + %s",
+ option.get_stringpool_name ());
+ 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",
+ indent, "", indent, "", indent, "");
+ }
+ printf ("%*s}\n",
+ indent, "");
+ }
+ else
+ {
+ int indent = 8;
+ if (option[LENTABLE])
+ {
+ printf ("%*sif (len == %s[key])\n",
+ indent, "", option.get_lengthtable_name ());
+ indent += 2;
+ }
+
+ if (option[SHAREDLIB])
+ {
+ if (!option[LENTABLE])
+ {
+ printf ("%*s{\n"
+ "%*s register int o = %s[key]",
+ indent, "",
+ indent, "", option.get_wordlist_name ());
+ if (option[TYPE])
+ printf (".%s", option.get_slot_name ());
+ printf (";\n"
+ "%*s if (o >= 0)\n"
+ "%*s {\n",
+ indent, "",
+ indent, "");
+ indent += 4;
+ printf ("%*s register %schar *s = o",
+ indent, "", const_always);
+ }
+ else
+ {
+ /* No need for the (o >= 0) test, because the
+ (len == lengthtable[key]) test already guarantees that
+ key points to nonempty table entry. */
+ printf ("%*s{\n"
+ "%*s register %schar *s = %s[key]",
+ indent, "",
+ indent, "", const_always,
+ option.get_wordlist_name ());
+ if (option[TYPE])
+ printf (".%s", option.get_slot_name ());
+ }
+ printf (" + %s",
+ option.get_stringpool_name ());
+ }
+ else
+ {
+ printf ("%*s{\n"
+ "%*s register %schar *s = %s[key]",
+ indent, "",
+ indent, "", const_always, option.get_wordlist_name ());
+ if (option[TYPE])
+ printf (".%s", option.get_slot_name ());
+ }
+
+ printf (";\n\n"
+ "%*s if (",
+ indent, "");
+ if (!option[SHAREDLIB] && option[NULLSTRINGS])
+ printf ("s && ");
+ 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");
+ if (option[SHAREDLIB] && !option[LENTABLE])
+ {
+ indent -= 4;
+ printf ("%*s }\n",
+ indent, "");
+ }
+ printf ("%*s}\n",
+ indent, "");
+ }
+ }
+ printf (" }\n"
+ " return 0;\n");
+}
+
+/* Generates C code for the lookup function. */
+
+void
+Output::output_lookup_function () const
+{
+ /* Output the function's head. */
+ if (option[KRC] | option[C] | option[ANSIC])
+ /* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99
+ inline semantics, unless -fgnu89-inline is used. It defines a macro
+ __GNUC_STDC_INLINE__ to indicate this situation. */
+ printf ("#ifdef __GNUC__\n"
+ "__inline\n"
+ "#ifdef __GNUC_STDC_INLINE__\n"
+ "__attribute__ ((__gnu_inline__))\n"
+ "#endif\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[SHAREDLIB] && !(option[GLOBAL] || option[TYPE]))
+ output_lookup_pools ();
+ if (!option[GLOBAL])
+ output_lookup_tables ();
+
+ if (option[LENTABLE])
+ output_lookup_function_body (Output_Compare_Memcmp ());
+ else
+ {
+ 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
+Output::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 *");
+ }
+
+ _wordlist_eltype = (option[SHAREDLIB] && !option[TYPE] ? "int" : _struct_tag);
+
+ 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);
+ option.print_options ();
+ printf ("\n");
+ if (!option[POSITIONS])
+ {
+ printf ("/* Computed positions: -k'");
+ _key_positions.print();
+ printf ("' */\n");
+ }
+ printf ("\n");
+
+ if (_charset_dependent
+ && (_key_positions.get_size() > 0 || option[UPPERLOWER]))
+ {
+ /* The generated tables assume that the execution character set is
+ based on ISO-646, not EBCDIC. */
+ printf ("#if !((' ' == 32) && ('!' == 33) && ('\"' == 34) && ('#' == 35) \\\n"
+ " && ('%%' == 37) && ('&' == 38) && ('\\'' == 39) && ('(' == 40) \\\n"
+ " && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \\\n"
+ " && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \\\n"
+ " && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \\\n"
+ " && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \\\n"
+ " && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \\\n"
+ " && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \\\n"
+ " && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \\\n"
+ " && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \\\n"
+ " && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \\\n"
+ " && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \\\n"
+ " && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \\\n"
+ " && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \\\n"
+ " && ('Z' == 90) && ('[' == 91) && ('\\\\' == 92) && (']' == 93) \\\n"
+ " && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \\\n"
+ " && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \\\n"
+ " && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \\\n"
+ " && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \\\n"
+ " && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \\\n"
+ " && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \\\n"
+ " && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \\\n"
+ " && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))\n"
+ "/* The character set is not based on ISO-646. */\n");
+ printf ("%s \"gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>.\"\n", option[KRC] || option[C] ? "error" : "#error");
+ printf ("#endif\n\n");
+ }
+
+ if (_verbatim_declarations < _verbatim_declarations_end)
+ {
+ output_line_directive (_verbatim_declarations_lineno);
+ fwrite (_verbatim_declarations, 1,
+ _verbatim_declarations_end - _verbatim_declarations, stdout);
+ }
+
+ if (option[TYPE] && !option[NOTYPE]) /* Output type declaration now, reference it later on.... */
+ {
+ output_line_directive (_struct_decl_lineno);
+ printf ("%s\n", _struct_decl);
+ }
+
+ 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[UPPERLOWER])
+ {
+ #if USE_DOWNCASE_TABLE
+ output_upperlower_table ();
+ #endif
+
+ if (option[LENTABLE])
+ output_upperlower_memcmp ();
+ else
+ {
+ if (option[COMP])
+ output_upperlower_strncmp ();
+ else
+ output_upperlower_strcmp ();
+ }
+ }
+
+ 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[SHAREDLIB] && (option[GLOBAL] || option[TYPE]))
+ output_lookup_pools ();
+ if (option[GLOBAL])
+ output_lookup_tables ();
+
+ output_lookup_function ();
+
+ if (_verbatim_code < _verbatim_code_end)
+ {
+ output_line_directive (_verbatim_code_lineno);
+ fwrite (_verbatim_code, 1, _verbatim_code_end - _verbatim_code, stdout);
+ }
+
+ fflush (stdout);
+}
diff --git a/contrib/gperf/src/output.h b/contrib/gperf/src/output.h
new file mode 100644
index 0000000..bb9345b
--- /dev/null
+++ b/contrib/gperf/src/output.h
@@ -0,0 +1,154 @@
+/* This may look like C code, but it is really -*- C++ -*- */
+
+/* Output routines.
+
+ Copyright (C) 1989-1998, 2000, 2002-2003 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
+
+ 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 2, 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 this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef output_h
+#define output_h 1
+
+#include "keyword-list.h"
+#include "positions.h"
+
+/* OSF/1 cxx needs these forward declarations. */
+struct Output_Constants;
+struct Output_Compare;
+
+class Output
+{
+public:
+ /* Constructor. */
+ Output (KeywordExt_List *head,
+ const char *struct_decl,
+ unsigned int struct_decl_lineno,
+ const char *return_type,
+ const char *struct_tag,
+ const char *verbatim_declarations,
+ const char *verbatim_declarations_end,
+ unsigned int verbatim_declarations_lineno,
+ const char *verbatim_code,
+ const char *verbatim_code_end,
+ unsigned int verbatim_code_lineno,
+ bool charset_dependent,
+ int total_keys,
+ int max_key_len, int min_key_len,
+ const Positions& positions,
+ const unsigned int *alpha_inc,
+ int total_duplicates,
+ unsigned int alpha_size,
+ const int *asso_values);
+
+ /* Generates the hash function and the key word recognizer function. */
+ void output ();
+
+private:
+
+ /* Computes the minimum and maximum hash values, and stores them
+ in _min_hash_value and _max_hash_value. */
+ void compute_min_max ();
+
+ /* Returns the number of different hash values. */
+ int num_hash_values () const;
+
+ /* Outputs the maximum and minimum hash values etc. */
+ void output_constants (struct Output_Constants&) const;
+
+ /* Generates a C expression for an asso_values[] reference. */
+ void output_asso_values_ref (int pos) const;
+
+ /* Generates C code for the hash function that returns the
+ proper encoding for each keyword. */
+ void output_hash_function () const;
+
+ /* Prints out a table of keyword lengths, for use with the
+ comparison code in generated function 'in_word_set'. */
+ void output_keylength_table () const;
+
+ /* Prints out the string pool, containing the strings of the keyword table.
+ */
+ void output_string_pool () const;
+
+ /* Prints out the array containing the keywords for the hash function. */
+ void output_keyword_table () const;
+
+ /* Generates the large, sparse table that maps hash values into
+ the smaller, contiguous range of the keyword table. */
+ void output_lookup_array () const;
+
+ /* Generate all pools needed for the lookup function. */
+ void output_lookup_pools () const;
+
+ /* Generate all the tables needed for the lookup function. */
+ void output_lookup_tables () const;
+
+ /* Generates C code to perform the keyword lookup. */
+ void output_lookup_function_body (const struct Output_Compare&) const;
+
+ /* Generates C code for the lookup function. */
+ void output_lookup_function () const;
+
+ /* Linked list of keywords. */
+ KeywordExt_List * _head;
+
+ /* Declaration of struct type for a keyword and its attributes. */
+ const char * const _struct_decl;
+ unsigned int const _struct_decl_lineno;
+ /* Pointer to return type for lookup function. */
+ const char * _return_type;
+ /* Shorthand for user-defined struct tag type. */
+ const char * _struct_tag;
+ /* Element type of keyword array. */
+ const char * _wordlist_eltype;
+ /* The C code from the declarations section. */
+ const char * const _verbatim_declarations;
+ const char * const _verbatim_declarations_end;
+ unsigned int const _verbatim_declarations_lineno;
+ /* The C code from the end of the file. */
+ const char * const _verbatim_code;
+ const char * const _verbatim_code_end;
+ unsigned int const _verbatim_code_lineno;
+ /* Whether the keyword chars would have different values in a different
+ character set. */
+ bool _charset_dependent;
+ /* Total number of keys, counting duplicates. */
+ int const _total_keys;
+ /* Maximum length of the longest keyword. */
+ int const _max_key_len;
+ /* Minimum length of the shortest keyword. */
+ int const _min_key_len;
+ /* Key positions. */
+ Positions const _key_positions;
+ /* Adjustments to add to bytes add specific key positions. */
+ const unsigned int * const _alpha_inc;
+ /* Total number of duplicate hash values. */
+ int const _total_duplicates;
+ /* Minimum hash value for all keywords. */
+ int _min_hash_value;
+ /* Maximum hash value for all keywords. */
+ int _max_hash_value;
+ /* Size of alphabet. */
+ unsigned int const _alpha_size;
+ /* Value associated with each character. */
+ const int * const _asso_values;
+};
+
+#endif
diff --git a/contrib/gperf/src/positions.cc b/contrib/gperf/src/positions.cc
new file mode 100644
index 0000000..d023fdb
--- /dev/null
+++ b/contrib/gperf/src/positions.cc
@@ -0,0 +1,177 @@
+/* A set of byte positions.
+ Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
+
+ 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 2, 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 this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Specification. */
+#include "positions.h"
+
+#include <stdio.h>
+#include <stdlib.h> /* declares exit() */
+#include <string.h>
+
+/* ---------------------------- Class Positions ---------------------------- */
+
+/* Set operations. Assumes the array is in reverse order. */
+
+bool
+Positions::contains (int pos) const
+{
+ unsigned int count = _size;
+ const int *p = _positions + _size - 1;
+
+ for (; count > 0; p--, count--)
+ {
+ if (*p == pos)
+ return true;
+ if (*p > pos)
+ break;
+ }
+ return false;
+}
+
+void
+Positions::add (int pos)
+{
+ set_useall (false);
+
+ unsigned int count = _size;
+
+ if (count == MAX_SIZE)
+ {
+ fprintf (stderr, "Positions::add internal error: overflow\n");
+ exit (1);
+ }
+
+ int *p = _positions + _size - 1;
+
+ for (; count > 0; p--, count--)
+ {
+ if (*p == pos)
+ {
+ fprintf (stderr, "Positions::add internal error: duplicate\n");
+ exit (1);
+ }
+ if (*p > pos)
+ break;
+ p[1] = p[0];
+ }
+ p[1] = pos;
+ _size++;
+}
+
+void
+Positions::remove (int pos)
+{
+ set_useall (false);
+
+ unsigned int count = _size;
+ if (count > 0)
+ {
+ int *p = _positions + _size - 1;
+
+ if (*p == pos)
+ {
+ _size--;
+ return;
+ }
+ if (*p < pos)
+ {
+ int prev = *p;
+
+ for (;;)
+ {
+ p--;
+ count--;
+ if (count == 0)
+ break;
+ if (*p == pos)
+ {
+ *p = prev;
+ _size--;
+ return;
+ }
+ if (*p > pos)
+ break;
+ int curr = *p;
+ *p = prev;
+ prev = curr;
+ }
+ }
+ }
+ fprintf (stderr, "Positions::remove internal error: not found\n");
+ exit (1);
+}
+
+/* Output in external syntax. */
+void
+Positions::print () const
+{
+ if (_useall)
+ printf ("*");
+ else
+ {
+ bool first = true;
+ bool seen_LASTCHAR = false;
+ unsigned int count = _size;
+ const int *p = _positions + _size - 1;
+
+ for (; count > 0; p--)
+ {
+ count--;
+ if (*p == LASTCHAR)
+ seen_LASTCHAR = true;
+ else
+ {
+ if (!first)
+ printf (",");
+ printf ("%d", *p + 1);
+ if (count > 0 && p[-1] == *p + 1)
+ {
+ printf ("-");
+ do
+ {
+ p--;
+ count--;
+ }
+ while (count > 0 && p[-1] == *p + 1);
+ printf ("%d", *p + 1);
+ }
+ first = false;
+ }
+ }
+ if (seen_LASTCHAR)
+ {
+ if (!first)
+ printf (",");
+ printf ("$");
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+#ifndef __OPTIMIZE__
+
+#define INLINE /* not inline */
+#include "positions.icc"
+#undef INLINE
+
+#endif /* not defined __OPTIMIZE__ */
diff --git a/contrib/gperf/src/positions.h b/contrib/gperf/src/positions.h
new file mode 100644
index 0000000..596844f
--- /dev/null
+++ b/contrib/gperf/src/positions.h
@@ -0,0 +1,175 @@
+/* This may look like C code, but it is really -*- C++ -*- */
+
+/* A set of byte positions.
+
+ Copyright (C) 1989-1998, 2000, 2002, 2005 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
+
+ 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 2, 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 this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef positions_h
+#define positions_h 1
+
+/* Classes defined below. */
+class PositionIterator;
+class PositionReverseIterator;
+
+/* This class denotes a set of byte positions, used to access a keyword. */
+
+class Positions
+{
+ friend class PositionIterator;
+ friend class PositionReverseIterator;
+public:
+ /* Denotes the last char of a keyword, depending on the keyword's length. */
+ enum { LASTCHAR = -1 };
+
+ /* Maximum key position specifiable by the user, 1-based.
+ Note that MAX_KEY_POS-1 must fit into the element type of _positions[],
+ below. */
+ enum { MAX_KEY_POS = 255 };
+
+ /* Maximum possible size. Since duplicates are eliminated and the possible
+ 0-based positions are -1 .. MAX_KEY_POS-1, this is: */
+ enum { MAX_SIZE = MAX_KEY_POS + 1 };
+
+ /* Constructors. */
+ Positions ();
+ Positions (int pos1);
+ Positions (int pos1, int pos2);
+
+ /* Copy constructor. */
+ Positions (const Positions& src);
+
+ /* Assignment operator. */
+ Positions& operator= (const Positions& src);
+
+ /* Accessors. */
+ bool is_useall () const;
+ int operator[] (unsigned int index) const;
+ unsigned int get_size () const;
+
+ /* Write access. */
+ void set_useall (bool useall);
+ int * pointer ();
+ void set_size (unsigned int size);
+
+ /* Sorts the array in reverse order.
+ Returns true if there are no duplicates, false otherwise. */
+ bool sort ();
+
+ /* Creates an iterator, returning the positions in descending order. */
+ PositionIterator iterator () const;
+ /* Creates an iterator, returning the positions in descending order,
+ that apply to strings of length <= maxlen. */
+ PositionIterator iterator (int maxlen) const;
+ /* Creates an iterator, returning the positions in ascending order. */
+ PositionReverseIterator reviterator () const;
+ /* Creates an iterator, returning the positions in ascending order,
+ that apply to strings of length <= maxlen. */
+ PositionReverseIterator reviterator (int maxlen) const;
+
+ /* Set operations. Assumes the array is in reverse order. */
+ bool contains (int pos) const;
+ void add (int pos);
+ void remove (int pos);
+
+ /* Output in external syntax. */
+ void print () const;
+
+private:
+ /* The special case denoted by '*'. */
+ bool _useall;
+ /* Number of positions. */
+ unsigned int _size;
+ /* Array of positions. 0 for the first char, 1 for the second char etc.,
+ LASTCHAR for the last char. */
+ int _positions[MAX_SIZE];
+};
+
+/* This class denotes an iterator through a set of byte positions. */
+
+class PositionIterator
+{
+ friend class Positions;
+public:
+ /* Copy constructor. */
+ PositionIterator (const PositionIterator& src);
+
+ /* End of iteration marker. */
+ enum { EOS = -2 };
+
+ /* Retrieves the next position, or EOS past the end. */
+ int next ();
+
+ /* Returns the number of remaining positions, i.e. how often next() will
+ return a value != EOS. */
+ unsigned int remaining () const;
+
+private:
+ /* Initializes an iterator through POSITIONS. */
+ PositionIterator (Positions const& positions);
+ /* Initializes an iterator through POSITIONS, ignoring positions >= maxlen. */
+ PositionIterator (Positions const& positions, int maxlen);
+
+ const Positions& _set;
+ unsigned int _index;
+};
+
+/* This class denotes an iterator in reverse direction through a set of
+ byte positions. */
+
+class PositionReverseIterator
+{
+ friend class Positions;
+public:
+ /* Copy constructor. */
+ PositionReverseIterator (const PositionReverseIterator& src);
+
+ /* End of iteration marker. */
+ enum { EOS = -2 };
+
+ /* Retrieves the next position, or EOS past the end. */
+ int next ();
+
+ /* Returns the number of remaining positions, i.e. how often next() will
+ return a value != EOS. */
+ unsigned int remaining () const;
+
+private:
+ /* Initializes an iterator through POSITIONS. */
+ PositionReverseIterator (Positions const& positions);
+ /* Initializes an iterator through POSITIONS, ignoring positions >= maxlen. */
+ PositionReverseIterator (Positions const& positions, int maxlen);
+
+ const Positions& _set;
+ unsigned int _index;
+ unsigned int _minindex;
+};
+
+#ifdef __OPTIMIZE__
+
+#include <string.h>
+#define INLINE inline
+#include "positions.icc"
+#undef INLINE
+
+#endif
+
+#endif
diff --git a/contrib/gperf/src/positions.icc b/contrib/gperf/src/positions.icc
new file mode 100644
index 0000000..c0be81b
--- /dev/null
+++ b/contrib/gperf/src/positions.icc
@@ -0,0 +1,285 @@
+/* Inline Functions for positions.{h,cc}.
+
+ Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
+
+ 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 2, 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 this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+// This needs:
+//#include <string.h>
+
+/* ---------------------------- Class Positions ---------------------------- */
+
+/* Constructors. */
+
+INLINE
+Positions::Positions ()
+ : _useall (false),
+ _size (0)
+{
+}
+
+INLINE
+Positions::Positions (int pos1)
+ : _useall (false),
+ _size (1)
+{
+ _positions[0] = pos1;
+}
+
+INLINE
+Positions::Positions (int pos1, int pos2)
+ : _useall (false),
+ _size (2)
+{
+ _positions[0] = pos1;
+ _positions[1] = pos2;
+}
+
+/* Copy constructor. */
+
+INLINE
+Positions::Positions (const Positions& src)
+ : _useall (src._useall),
+ _size (src._size)
+{
+ memcpy (_positions, src._positions, _size * sizeof (_positions[0]));
+}
+
+/* Assignment operator. */
+
+INLINE Positions&
+Positions::operator= (const Positions& src)
+{
+ _useall = src._useall;
+ _size = src._size;
+ memcpy (_positions, src._positions, _size * sizeof (_positions[0]));
+ return *this;
+}
+
+/* Accessors. */
+
+INLINE bool
+Positions::is_useall () const
+{
+ return _useall;
+}
+
+INLINE int
+Positions::operator[] (unsigned int index) const
+{
+ return _positions[index];
+}
+
+INLINE unsigned int
+Positions::get_size () const
+{
+ return _size;
+}
+
+/* Write access. */
+
+INLINE void
+Positions::set_useall (bool useall)
+{
+ _useall = useall;
+ if (useall)
+ {
+ /* The positions are 0, 1, ..., MAX_KEY_POS-1, in descending order. */
+ _size = MAX_KEY_POS;
+ int *ptr = _positions;
+ for (int i = MAX_KEY_POS - 1; i >= 0; i--)
+ *ptr++ = i;
+ }
+}
+
+INLINE int *
+Positions::pointer ()
+{
+ return _positions;
+}
+
+INLINE void
+Positions::set_size (unsigned int size)
+{
+ _size = size;
+}
+
+/* Sorts the array in reverse order.
+ Returns true if there are no duplicates, false otherwise. */
+INLINE bool
+Positions::sort ()
+{
+ if (_useall)
+ return true;
+
+ /* Bubble sort. */
+ bool duplicate_free = true;
+ int *base = _positions;
+ unsigned int len = _size;
+
+ for (unsigned int i = 1; i < len; i++)
+ {
+ unsigned int j;
+ int tmp;
+
+ for (j = i, tmp = base[j]; j > 0 && tmp >= base[j - 1]; j--)
+ if ((base[j] = base[j - 1]) == tmp) /* oh no, a duplicate!!! */
+ duplicate_free = false;
+
+ base[j] = tmp;
+ }
+
+ return duplicate_free;
+}
+
+/* Creates an iterator, returning the positions in descending order. */
+INLINE PositionIterator
+Positions::iterator () const
+{
+ return PositionIterator (*this);
+}
+
+/* Creates an iterator, returning the positions in descending order,
+ that apply to strings of length <= maxlen. */
+INLINE PositionIterator
+Positions::iterator (int maxlen) const
+{
+ return PositionIterator (*this, maxlen);
+}
+
+/* Creates an iterator, returning the positions in ascending order. */
+INLINE PositionReverseIterator
+Positions::reviterator () const
+{
+ return PositionReverseIterator (*this);
+}
+
+/* Creates an iterator, returning the positions in ascending order,
+ that apply to strings of length <= maxlen. */
+INLINE PositionReverseIterator
+Positions::reviterator (int maxlen) const
+{
+ return PositionReverseIterator (*this, maxlen);
+}
+
+/* ------------------------- Class PositionIterator ------------------------ */
+
+/* Initializes an iterator through POSITIONS. */
+INLINE
+PositionIterator::PositionIterator (Positions const& positions)
+ : _set (positions),
+ _index (0)
+{
+}
+
+/* Initializes an iterator through POSITIONS, ignoring positions >= maxlen. */
+INLINE
+PositionIterator::PositionIterator (Positions const& positions, int maxlen)
+ : _set (positions)
+{
+ if (positions._useall)
+ _index = (maxlen <= Positions::MAX_KEY_POS ? Positions::MAX_KEY_POS - maxlen : 0);
+ else
+ {
+ unsigned int index;
+ for (index = 0;
+ index < positions._size && positions._positions[index] >= maxlen;
+ index++)
+ ;
+ _index = index;
+ }
+}
+
+/* Retrieves the next position, or EOS past the end. */
+INLINE int
+PositionIterator::next ()
+{
+ return (_index < _set._size ? _set._positions[_index++] : EOS);
+}
+
+/* Returns the number of remaining positions, i.e. how often next() will
+ return a value != EOS. */
+INLINE unsigned int
+PositionIterator::remaining () const
+{
+ return _set._size - _index;
+}
+
+/* Copy constructor. */
+INLINE
+PositionIterator::PositionIterator (const PositionIterator& src)
+ : _set (src._set),
+ _index (src._index)
+{
+}
+
+/* --------------------- Class PositionReverseIterator --------------------- */
+
+/* Initializes an iterator through POSITIONS. */
+INLINE
+PositionReverseIterator::PositionReverseIterator (Positions const& positions)
+ : _set (positions),
+ _index (_set._size),
+ _minindex (0)
+{
+}
+
+/* Initializes an iterator through POSITIONS, ignoring positions >= maxlen. */
+INLINE
+PositionReverseIterator::PositionReverseIterator (Positions const& positions, int maxlen)
+ : _set (positions),
+ _index (_set._size)
+{
+ if (positions._useall)
+ _minindex = (maxlen <= Positions::MAX_KEY_POS ? Positions::MAX_KEY_POS - maxlen : 0);
+ else
+ {
+ unsigned int index;
+ for (index = 0;
+ index < positions._size && positions._positions[index] >= maxlen;
+ index++)
+ ;
+ _minindex = index;
+ }
+}
+
+/* Retrieves the next position, or EOS past the end. */
+INLINE int
+PositionReverseIterator::next ()
+{
+ return (_index > _minindex ? _set._positions[--_index] : EOS);
+}
+
+/* Returns the number of remaining positions, i.e. how often next() will
+ return a value != EOS. */
+INLINE unsigned int
+PositionReverseIterator::remaining () const
+{
+ return _index - _minindex;
+}
+
+/* Copy constructor. */
+INLINE
+PositionReverseIterator::PositionReverseIterator (const PositionReverseIterator& src)
+ : _set (src._set),
+ _index (src._index),
+ _minindex (src._minindex)
+{
+}
diff --git a/contrib/gperf/src/read-line.cc b/contrib/gperf/src/read-line.cc
deleted file mode 100644
index 8cb0971..0000000
--- a/contrib/gperf/src/read-line.cc
+++ /dev/null
@@ -1,97 +0,0 @@
-/* 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
deleted file mode 100644
index b243c84..0000000
--- a/contrib/gperf/src/read-line.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* 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
deleted file mode 100644
index cdb5bf6..0000000
--- a/contrib/gperf/src/read-line.icc
+++ /dev/null
@@ -1,47 +0,0 @@
-/* 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/search.cc b/contrib/gperf/src/search.cc
new file mode 100644
index 0000000..c245970
--- /dev/null
+++ b/contrib/gperf/src/search.cc
@@ -0,0 +1,1684 @@
+/* Search algorithm.
+ Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
+
+ 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 2, 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 this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Specification. */
+#include "search.h"
+
+#include <stdio.h>
+#include <stdlib.h> /* declares exit(), rand(), srand() */
+#include <string.h> /* declares memset(), memcmp() */
+#include <time.h> /* declares time() */
+#include <math.h> /* declares exp() */
+#include <limits.h> /* defines INT_MIN, INT_MAX, UINT_MAX */
+#include "options.h"
+#include "hash-table.h"
+#include "config.h"
+
+/* ============================== Portability ============================== */
+
+/* Assume ISO C++ 'for' scoping rule. */
+#define for if (0) ; else for
+
+/* Dynamically allocated array with dynamic extent:
+
+ Example:
+ DYNAMIC_ARRAY (my_array, int, n);
+ ...
+ FREE_DYNAMIC_ARRAY (my_array);
+
+ Attention: depending on your implementation my_array is either the array
+ itself or a pointer to the array! Always use my_array only as expression!
+ */
+#if HAVE_DYNAMIC_ARRAY
+ #define DYNAMIC_ARRAY(var,eltype,size) eltype var[size]
+ #define FREE_DYNAMIC_ARRAY(var)
+#else
+ #define DYNAMIC_ARRAY(var,eltype,size) eltype *var = new eltype[size]
+ #define FREE_DYNAMIC_ARRAY(var) delete[] var
+#endif
+
+/* ================================ Theory ================================= */
+
+/* The general form of the hash function is
+
+ hash (keyword) = sum (asso_values[keyword[i] + alpha_inc[i]] : i in Pos)
+ + len (keyword)
+
+ where Pos is a set of byte positions,
+ each alpha_inc[i] is a nonnegative integer,
+ each asso_values[c] is a nonnegative integer,
+ len (keyword) is the keyword's length if !option[NOLENGTH], or 0 otherwise.
+
+ Theorem 1: If all keywords are different, there is a set Pos such that
+ all tuples (keyword[i] : i in Pos) are different.
+
+ Theorem 2: If all tuples (keyword[i] : i in Pos) are different, there
+ are nonnegative integers alpha_inc[i] such that all multisets
+ {keyword[i] + alpha_inc[i] : i in Pos} are different.
+
+ Define selchars[keyword] := {keyword[i] + alpha_inc[i] : i in Pos}.
+
+ Theorem 3: If all multisets selchars[keyword] are different, there are
+ nonnegative integers asso_values[c] such that all hash values
+ sum (asso_values[c] : c in selchars[keyword]) are different.
+
+ Based on these three facts, we find the hash function in three steps:
+
+ Step 1 (Finding good byte positions):
+ Find a set Pos, as small as possible, such that all tuples
+ (keyword[i] : i in Pos) are different.
+
+ Step 2 (Finding good alpha increments):
+ Find nonnegative integers alpha_inc[i], as many of them as possible being
+ zero, and the others being as small as possible, such that all multisets
+ {keyword[i] + alpha_inc[i] : i in Pos} are different.
+
+ Step 3 (Finding good asso_values):
+ Find asso_values[c] such that all hash (keyword) are different.
+
+ In other words, each step finds a projection that is injective on the
+ given finite set:
+ proj1 : String --> Map (Pos --> N)
+ proj2 : Map (Pos --> N) --> Map (Pos --> N) / S(Pos)
+ proj3 : Map (Pos --> N) / S(Pos) --> N
+ where
+ N denotes the set of nonnegative integers,
+ Map (A --> B) := Hom_Set (A, B) is the set of maps from A to B, and
+ S(Pos) is the symmetric group over Pos.
+
+ This was the theory for option[NOLENGTH]; if !option[NOLENGTH], slight
+ modifications apply:
+ proj1 : String --> Map (Pos --> N) x N
+ proj2 : Map (Pos --> N) x N --> Map (Pos --> N) / S(Pos) x N
+ proj3 : Map (Pos --> N) / S(Pos) x N --> N
+
+ For a case-insensitive hash function, the general form is
+
+ hash (keyword) =
+ sum (asso_values[alpha_unify[keyword[i] + alpha_inc[i]]] : i in Pos)
+ + len (keyword)
+
+ where alpha_unify[c] is chosen so that an upper/lower case change in
+ keyword[i] doesn't change alpha_unify[keyword[i] + alpha_inc[i]].
+ */
+
+/* ==================== Initialization and Preparation ===================== */
+
+Search::Search (KeywordExt_List *list)
+ : _head (list)
+{
+}
+
+void
+Search::prepare ()
+{
+ /* Compute the total number of keywords. */
+ _total_keys = 0;
+ for (KeywordExt_List *temp = _head; temp; temp = temp->rest())
+ _total_keys++;
+
+ /* Compute the minimum and maximum keyword length. */
+ _max_key_len = INT_MIN;
+ _min_key_len = INT_MAX;
+ for (KeywordExt_List *temp = _head; temp; temp = temp->rest())
+ {
+ KeywordExt *keyword = temp->first();
+
+ if (_max_key_len < keyword->_allchars_length)
+ _max_key_len = keyword->_allchars_length;
+ if (_min_key_len > keyword->_allchars_length)
+ _min_key_len = keyword->_allchars_length;
+ }
+
+ /* Exit program if an empty string is used as keyword, since the comparison
+ expressions don't work correctly for looking up an empty string. */
+ if (_min_key_len == 0)
+ {
+ fprintf (stderr, "Empty input keyword is not allowed.\n"
+ "To recognize an empty input keyword, your code should check for\n"
+ "len == 0 before calling the gperf generated lookup function.\n");
+ exit (1);
+ }
+
+ /* Exit program if the characters in the keywords are not in the required
+ range. */
+ if (option[SEVENBIT])
+ for (KeywordExt_List *temp = _head; temp; temp = temp->rest())
+ {
+ KeywordExt *keyword = temp->first();
+
+ const char *k = keyword->_allchars;
+ for (int i = keyword->_allchars_length; i > 0; k++, i--)
+ if (!(static_cast<unsigned char>(*k) < 128))
+ {
+ fprintf (stderr, "Option --seven-bit has been specified,\n"
+ "but keyword \"%.*s\" contains non-ASCII characters.\n"
+ "Try removing option --seven-bit.\n",
+ keyword->_allchars_length, keyword->_allchars);
+ exit (1);
+ }
+ }
+}
+
+/* ====================== Finding good byte positions ====================== */
+
+/* Computes the upper bound on the indices passed to asso_values[],
+ assuming no alpha_increments. */
+unsigned int
+Search::compute_alpha_size () const
+{
+ return (option[SEVENBIT] ? 128 : 256);
+}
+
+/* Computes the unification rules between different asso_values[c],
+ assuming no alpha_increments. */
+unsigned int *
+Search::compute_alpha_unify () const
+{
+ if (option[UPPERLOWER])
+ {
+ /* Uppercase to lowercase mapping. */
+ unsigned int alpha_size = compute_alpha_size();
+ unsigned int *alpha_unify = new unsigned int[alpha_size];
+ for (unsigned int c = 0; c < alpha_size; c++)
+ alpha_unify[c] = c;
+ for (unsigned int c = 'A'; c <= 'Z'; c++)
+ alpha_unify[c] = c + ('a'-'A');
+ return alpha_unify;
+ }
+ else
+ /* Identity mapping. */
+ return NULL;
+}
+
+/* Initializes each keyword's _selchars array. */
+void
+Search::init_selchars_tuple (const Positions& positions, const unsigned int *alpha_unify) const
+{
+ for (KeywordExt_List *temp = _head; temp; temp = temp->rest())
+ temp->first()->init_selchars_tuple(positions, alpha_unify);
+}
+
+/* Deletes each keyword's _selchars array. */
+void
+Search::delete_selchars () const
+{
+ for (KeywordExt_List *temp = _head; temp; temp = temp->rest())
+ temp->first()->delete_selchars();
+}
+
+/* Count the duplicate keywords that occur with a given set of positions.
+ In other words, it returns the difference
+ # K - # proj1 (K)
+ where K is the multiset of given keywords. */
+unsigned int
+Search::count_duplicates_tuple (const Positions& positions, const unsigned int *alpha_unify) const
+{
+ /* Run through the keyword list and count the duplicates incrementally.
+ The result does not depend on the order of the keyword list, thanks to
+ the formula above. */
+ init_selchars_tuple (positions, alpha_unify);
+
+ unsigned int count = 0;
+ {
+ Hash_Table representatives (_total_keys, option[NOLENGTH]);
+ for (KeywordExt_List *temp = _head; temp; temp = temp->rest())
+ {
+ KeywordExt *keyword = temp->first();
+ if (representatives.insert (keyword))
+ count++;
+ }
+ }
+
+ delete_selchars ();
+
+ return count;
+}
+
+/* Find good key positions. */
+
+void
+Search::find_positions ()
+{
+ /* If the user gave the key positions, we use them. */
+ if (option[POSITIONS])
+ {
+ _key_positions = option.get_key_positions();
+ return;
+ }
+
+ /* Compute preliminary alpha_unify table. */
+ unsigned int *alpha_unify = compute_alpha_unify ();
+
+ /* 1. Find positions that must occur in order to distinguish duplicates. */
+ Positions mandatory;
+
+ if (!option[DUP])
+ {
+ for (KeywordExt_List *l1 = _head; l1 && l1->rest(); l1 = l1->rest())
+ {
+ KeywordExt *keyword1 = l1->first();
+ for (KeywordExt_List *l2 = l1->rest(); l2; l2 = l2->rest())
+ {
+ KeywordExt *keyword2 = l2->first();
+
+ /* If keyword1 and keyword2 have the same length and differ
+ in just one position, and it is not the last character,
+ this position is mandatory. */
+ if (keyword1->_allchars_length == keyword2->_allchars_length)
+ {
+ int n = keyword1->_allchars_length;
+ int i;
+ for (i = 0; i < n - 1; i++)
+ {
+ unsigned char c1 = keyword1->_allchars[i];
+ unsigned char c2 = keyword2->_allchars[i];
+ if (option[UPPERLOWER])
+ {
+ if (c1 >= 'A' && c1 <= 'Z')
+ c1 += 'a' - 'A';
+ if (c2 >= 'A' && c2 <= 'Z')
+ c2 += 'a' - 'A';
+ }
+ if (c1 != c2)
+ break;
+ }
+ if (i < n - 1)
+ {
+ int j;
+ for (j = i + 1; j < n; j++)
+ {
+ unsigned char c1 = keyword1->_allchars[j];
+ unsigned char c2 = keyword2->_allchars[j];
+ if (option[UPPERLOWER])
+ {
+ if (c1 >= 'A' && c1 <= 'Z')
+ c1 += 'a' - 'A';
+ if (c2 >= 'A' && c2 <= 'Z')
+ c2 += 'a' - 'A';
+ }
+ if (c1 != c2)
+ break;
+ }
+ if (j >= n)
+ {
+ /* Position i is mandatory. */
+ if (!mandatory.contains (i))
+ mandatory.add (i);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* 2. Add positions, as long as this decreases the duplicates count. */
+ int imax = (_max_key_len - 1 < Positions::MAX_KEY_POS - 1
+ ? _max_key_len - 1 : Positions::MAX_KEY_POS - 1);
+ Positions current = mandatory;
+ unsigned int current_duplicates_count =
+ count_duplicates_tuple (current, alpha_unify);
+ for (;;)
+ {
+ Positions best;
+ unsigned int best_duplicates_count = UINT_MAX;
+
+ for (int i = imax; i >= -1; i--)
+ if (!current.contains (i))
+ {
+ Positions tryal = current;
+ tryal.add (i);
+ unsigned int try_duplicates_count =
+ count_duplicates_tuple (tryal, alpha_unify);
+
+ /* We prefer 'try' to 'best' if it produces less duplicates,
+ or if it produces the same number of duplicates but with
+ a more efficient hash function. */
+ if (try_duplicates_count < best_duplicates_count
+ || (try_duplicates_count == best_duplicates_count && i >= 0))
+ {
+ best = tryal;
+ best_duplicates_count = try_duplicates_count;
+ }
+ }
+
+ /* Stop adding positions when it gives no improvement. */
+ if (best_duplicates_count >= current_duplicates_count)
+ break;
+
+ current = best;
+ current_duplicates_count = best_duplicates_count;
+ }
+
+ /* 3. Remove positions, as long as this doesn't increase the duplicates
+ count. */
+ for (;;)
+ {
+ Positions best;
+ unsigned int best_duplicates_count = UINT_MAX;
+
+ for (int i = imax; i >= -1; i--)
+ if (current.contains (i) && !mandatory.contains (i))
+ {
+ Positions tryal = current;
+ tryal.remove (i);
+ unsigned int try_duplicates_count =
+ count_duplicates_tuple (tryal, alpha_unify);
+
+ /* We prefer 'try' to 'best' if it produces less duplicates,
+ or if it produces the same number of duplicates but with
+ a more efficient hash function. */
+ if (try_duplicates_count < best_duplicates_count
+ || (try_duplicates_count == best_duplicates_count && i == -1))
+ {
+ best = tryal;
+ best_duplicates_count = try_duplicates_count;
+ }
+ }
+
+ /* Stop removing positions when it gives no improvement. */
+ if (best_duplicates_count > current_duplicates_count)
+ break;
+
+ current = best;
+ current_duplicates_count = best_duplicates_count;
+ }
+
+ /* 4. Replace two positions by one, as long as this doesn't increase the
+ duplicates count. */
+ for (;;)
+ {
+ Positions best;
+ unsigned int best_duplicates_count = UINT_MAX;
+
+ for (int i1 = imax; i1 >= -1; i1--)
+ if (current.contains (i1) && !mandatory.contains (i1))
+ for (int i2 = imax; i2 >= -1; i2--)
+ if (current.contains (i2) && !mandatory.contains (i2) && i2 != i1)
+ for (int i3 = imax; i3 >= 0; i3--)
+ if (!current.contains (i3))
+ {
+ Positions tryal = current;
+ tryal.remove (i1);
+ tryal.remove (i2);
+ tryal.add (i3);
+ unsigned int try_duplicates_count =
+ count_duplicates_tuple (tryal, alpha_unify);
+
+ /* We prefer 'try' to 'best' if it produces less duplicates,
+ or if it produces the same number of duplicates but with
+ a more efficient hash function. */
+ if (try_duplicates_count < best_duplicates_count
+ || (try_duplicates_count == best_duplicates_count
+ && (i1 == -1 || i2 == -1 || i3 >= 0)))
+ {
+ best = tryal;
+ best_duplicates_count = try_duplicates_count;
+ }
+ }
+
+ /* Stop removing positions when it gives no improvement. */
+ if (best_duplicates_count > current_duplicates_count)
+ break;
+
+ current = best;
+ current_duplicates_count = best_duplicates_count;
+ }
+
+ /* That's it. Hope it's good enough. */
+ _key_positions = current;
+
+ if (option[DEBUG])
+ {
+ /* Print the result. */
+ fprintf (stderr, "\nComputed positions: ");
+ PositionReverseIterator iter = _key_positions.reviterator();
+ bool seen_lastchar = false;
+ bool first = true;
+ for (int i; (i = iter.next ()) != PositionReverseIterator::EOS; )
+ {
+ if (!first)
+ fprintf (stderr, ", ");
+ if (i == Positions::LASTCHAR)
+ seen_lastchar = true;
+ else
+ {
+ fprintf (stderr, "%d", i + 1);
+ first = false;
+ }
+ }
+ if (seen_lastchar)
+ {
+ if (!first)
+ fprintf (stderr, ", ");
+ fprintf (stderr, "$");
+ }
+ fprintf (stderr, "\n");
+ }
+
+ /* Free preliminary alpha_unify table. */
+ delete[] alpha_unify;
+}
+
+/* Count the duplicate keywords that occur with the found set of positions.
+ In other words, it returns the difference
+ # K - # proj1 (K)
+ where K is the multiset of given keywords. */
+unsigned int
+Search::count_duplicates_tuple () const
+{
+ unsigned int *alpha_unify = compute_alpha_unify ();
+ unsigned int count = count_duplicates_tuple (_key_positions, alpha_unify);
+ delete[] alpha_unify;
+ return count;
+}
+
+/* ===================== Finding good alpha increments ===================== */
+
+/* Computes the upper bound on the indices passed to asso_values[]. */
+unsigned int
+Search::compute_alpha_size (const unsigned int *alpha_inc) const
+{
+ unsigned int max_alpha_inc = 0;
+ for (int i = 0; i < _max_key_len; i++)
+ if (max_alpha_inc < alpha_inc[i])
+ max_alpha_inc = alpha_inc[i];
+ return (option[SEVENBIT] ? 128 : 256) + max_alpha_inc;
+}
+
+/* Computes the unification rules between different asso_values[c]. */
+unsigned int *
+Search::compute_alpha_unify (const Positions& positions, const unsigned int *alpha_inc) const
+{
+ if (option[UPPERLOWER])
+ {
+ /* Without alpha increments, we would simply unify
+ 'A' -> 'a', ..., 'Z' -> 'z'.
+ But when a keyword contains at position i a character c,
+ we have the constraint
+ asso_values[tolower(c) + alpha_inc[i]] ==
+ asso_values[toupper(c) + alpha_inc[i]].
+ This introduces a unification
+ toupper(c) + alpha_inc[i] -> tolower(c) + alpha_inc[i].
+ Note that this unification can extend outside the range of
+ ASCII letters! But still every unified character pair is at
+ a distance of 'a'-'A' = 32, or (after chained unification)
+ at a multiple of 32. So in the end the alpha_unify vector has
+ the form c -> c + 32 * f(c) where f(c) is a nonnegative
+ integer. */
+ unsigned int alpha_size = compute_alpha_size (alpha_inc);
+
+ unsigned int *alpha_unify = new unsigned int[alpha_size];
+ for (unsigned int c = 0; c < alpha_size; c++)
+ alpha_unify[c] = c;
+
+ for (KeywordExt_List *temp = _head; temp; temp = temp->rest())
+ {
+ KeywordExt *keyword = temp->first();
+
+ /* Iterate through the selected character positions. */
+ PositionIterator iter = positions.iterator(keyword->_allchars_length);
+
+ for (int i; (i = iter.next ()) != PositionIterator::EOS; )
+ {
+ unsigned int c;
+ if (i == Positions::LASTCHAR)
+ c = static_cast<unsigned char>(keyword->_allchars[keyword->_allchars_length - 1]);
+ else if (i < keyword->_allchars_length)
+ c = static_cast<unsigned char>(keyword->_allchars[i]);
+ else
+ abort ();
+ if (c >= 'A' && c <= 'Z')
+ c += 'a' - 'A';
+ if (c >= 'a' && c <= 'z')
+ {
+ if (i != Positions::LASTCHAR)
+ c += alpha_inc[i];
+ /* Unify c with c - ('a'-'A'). */
+ unsigned int d = alpha_unify[c];
+ unsigned int b = c - ('a'-'A');
+ for (int a = b; a >= 0 && alpha_unify[a] == b; a -= ('a'-'A'))
+ alpha_unify[a] = d;
+ }
+ }
+ }
+ return alpha_unify;
+ }
+ else
+ /* Identity mapping. */
+ return NULL;
+}
+
+/* Initializes each keyword's _selchars array. */
+void
+Search::init_selchars_multiset (const Positions& positions, const unsigned int *alpha_unify, const unsigned int *alpha_inc) const
+{
+ for (KeywordExt_List *temp = _head; temp; temp = temp->rest())
+ temp->first()->init_selchars_multiset(positions, alpha_unify, alpha_inc);
+}
+
+/* Count the duplicate keywords that occur with the given set of positions
+ and a given alpha_inc[] array.
+ In other words, it returns the difference
+ # K - # proj2 (proj1 (K))
+ where K is the multiset of given keywords. */
+unsigned int
+Search::count_duplicates_multiset (const unsigned int *alpha_inc) const
+{
+ /* Run through the keyword list and count the duplicates incrementally.
+ The result does not depend on the order of the keyword list, thanks to
+ the formula above. */
+ unsigned int *alpha_unify = compute_alpha_unify (_key_positions, alpha_inc);
+ init_selchars_multiset (_key_positions, alpha_unify, alpha_inc);
+
+ unsigned int count = 0;
+ {
+ Hash_Table representatives (_total_keys, option[NOLENGTH]);
+ for (KeywordExt_List *temp = _head; temp; temp = temp->rest())
+ {
+ KeywordExt *keyword = temp->first();
+ if (representatives.insert (keyword))
+ count++;
+ }
+ }
+
+ delete_selchars ();
+ delete[] alpha_unify;
+
+ return count;
+}
+
+/* Find good _alpha_inc[]. */
+
+void
+Search::find_alpha_inc ()
+{
+ /* The goal is to choose _alpha_inc[] such that it doesn't introduce
+ artificial duplicates.
+ In other words, the goal is # proj2 (proj1 (K)) = # proj1 (K). */
+ unsigned int duplicates_goal = count_duplicates_tuple ();
+
+ /* Start with zero increments. This is sufficient in most cases. */
+ unsigned int *current = new unsigned int [_max_key_len];
+ for (int i = 0; i < _max_key_len; i++)
+ current[i] = 0;
+ unsigned int current_duplicates_count = count_duplicates_multiset (current);
+
+ if (current_duplicates_count > duplicates_goal)
+ {
+ /* Look which _alpha_inc[i] we are free to increment. */
+ unsigned int nindices;
+ {
+ nindices = 0;
+ PositionIterator iter = _key_positions.iterator(_max_key_len);
+ for (;;)
+ {
+ int key_pos = iter.next ();
+ if (key_pos == PositionIterator::EOS)
+ break;
+ if (key_pos != Positions::LASTCHAR)
+ nindices++;
+ }
+ }
+
+ DYNAMIC_ARRAY (indices, unsigned int, nindices);
+ {
+ unsigned int j = 0;
+ PositionIterator iter = _key_positions.iterator(_max_key_len);
+ for (;;)
+ {
+ int key_pos = iter.next ();
+ if (key_pos == PositionIterator::EOS)
+ break;
+ if (key_pos != Positions::LASTCHAR)
+ indices[j++] = key_pos;
+ }
+ if (!(j == nindices))
+ abort ();
+ }
+
+ /* Perform several rounds of searching for a good alpha increment.
+ Each round reduces the number of artificial collisions by adding
+ an increment in a single key position. */
+ DYNAMIC_ARRAY (best, unsigned int, _max_key_len);
+ DYNAMIC_ARRAY (tryal, unsigned int, _max_key_len);
+ do
+ {
+ /* An increment of 1 is not always enough. Try higher increments
+ also. */
+ for (unsigned int inc = 1; ; inc++)
+ {
+ unsigned int best_duplicates_count = UINT_MAX;
+
+ for (unsigned int j = 0; j < nindices; j++)
+ {
+ memcpy (tryal, current, _max_key_len * sizeof (unsigned int));
+ tryal[indices[j]] += inc;
+ unsigned int try_duplicates_count =
+ count_duplicates_multiset (tryal);
+
+ /* We prefer 'try' to 'best' if it produces less
+ duplicates. */
+ if (try_duplicates_count < best_duplicates_count)
+ {
+ memcpy (best, tryal, _max_key_len * sizeof (unsigned int));
+ best_duplicates_count = try_duplicates_count;
+ }
+ }
+
+ /* Stop this round when we got an improvement. */
+ if (best_duplicates_count < current_duplicates_count)
+ {
+ memcpy (current, best, _max_key_len * sizeof (unsigned int));
+ current_duplicates_count = best_duplicates_count;
+ break;
+ }
+ }
+ }
+ while (current_duplicates_count > duplicates_goal);
+ FREE_DYNAMIC_ARRAY (tryal);
+ FREE_DYNAMIC_ARRAY (best);
+
+ if (option[DEBUG])
+ {
+ /* Print the result. */
+ fprintf (stderr, "\nComputed alpha increments: ");
+ bool first = true;
+ for (unsigned int j = nindices; j-- > 0; )
+ if (current[indices[j]] != 0)
+ {
+ if (!first)
+ fprintf (stderr, ", ");
+ fprintf (stderr, "%u:+%u",
+ indices[j] + 1, current[indices[j]]);
+ first = false;
+ }
+ fprintf (stderr, "\n");
+ }
+ FREE_DYNAMIC_ARRAY (indices);
+ }
+
+ _alpha_inc = current;
+ _alpha_size = compute_alpha_size (_alpha_inc);
+ _alpha_unify = compute_alpha_unify (_key_positions, _alpha_inc);
+}
+
+/* ======================= Finding good asso_values ======================== */
+
+/* Initializes the asso_values[] related parameters. */
+
+void
+Search::prepare_asso_values ()
+{
+ KeywordExt_List *temp;
+
+ /* Initialize each keyword's _selchars array. */
+ init_selchars_multiset(_key_positions, _alpha_unify, _alpha_inc);
+
+ /* Compute the maximum _selchars_length over all keywords. */
+ _max_selchars_length = _key_positions.iterator(_max_key_len).remaining();
+
+ /* Check for duplicates, i.e. keywords with the same _selchars array
+ (and - if !option[NOLENGTH] - also the same length).
+ We deal with these by building an equivalence class, so that only
+ 1 keyword is representative of the entire collection. Only this
+ representative remains in the keyword list; the others are accessible
+ through the _duplicate_link chain, starting at the representative.
+ This *greatly* simplifies processing during later stages of the program.
+ Set _total_duplicates and _list_len = _total_keys - _total_duplicates. */
+ {
+ _list_len = _total_keys;
+ _total_duplicates = 0;
+ /* Make hash table for efficiency. */
+ Hash_Table representatives (_list_len, option[NOLENGTH]);
+
+ KeywordExt_List *prev = NULL; /* list node before temp */
+ for (temp = _head; temp; )
+ {
+ KeywordExt *keyword = temp->first();
+ KeywordExt *other_keyword = representatives.insert (keyword);
+ KeywordExt_List *garbage = NULL;
+
+ if (other_keyword)
+ {
+ _total_duplicates++;
+ _list_len--;
+ /* Remove keyword from the main list. */
+ prev->rest() = temp->rest();
+ garbage = temp;
+ /* And insert it on other_keyword's duplicate list. */
+ keyword->_duplicate_link = other_keyword->_duplicate_link;
+ other_keyword->_duplicate_link = keyword;
+
+ /* Complain if user hasn't enabled the duplicate option. */
+ if (!option[DUP] || option[DEBUG])
+ {
+ fprintf (stderr, "Key link: \"%.*s\" = \"%.*s\", with key set \"",
+ keyword->_allchars_length, keyword->_allchars,
+ other_keyword->_allchars_length, other_keyword->_allchars);
+ for (int j = 0; j < keyword->_selchars_length; j++)
+ putc (keyword->_selchars[j], stderr);
+ fprintf (stderr, "\".\n");
+ }
+ }
+ else
+ {
+ keyword->_duplicate_link = NULL;
+ prev = temp;
+ }
+ temp = temp->rest();
+ if (garbage)
+ delete garbage;
+ }
+ if (option[DEBUG])
+ representatives.dump();
+ }
+
+ /* Exit program if duplicates exists and option[DUP] not set, since we
+ don't want to continue in this case. (We don't want to turn on
+ option[DUP] implicitly, because the generated code is usually much
+ slower. */
+ 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,\n",
+ _total_duplicates);
+ if (option[POSITIONS])
+ fprintf (stderr, "try different key positions or use option -D.\n");
+ else
+ fprintf (stderr, "use option -D.\n");
+ exit (1);
+ }
+ }
+
+ /* Compute the occurrences of each character in the alphabet. */
+ _occurrences = new int[_alpha_size];
+ memset (_occurrences, 0, _alpha_size * sizeof (_occurrences[0]));
+ for (temp = _head; temp; temp = temp->rest())
+ {
+ KeywordExt *keyword = temp->first();
+ const unsigned int *ptr = keyword->_selchars;
+ for (int count = keyword->_selchars_length; count > 0; ptr++, count--)
+ _occurrences[*ptr]++;
+ }
+
+ /* Memory allocation. */
+ _asso_values = new int[_alpha_size];
+
+ int non_linked_length = _list_len;
+ unsigned int asso_value_max;
+
+ asso_value_max =
+ static_cast<unsigned int>(non_linked_length * option.get_size_multiple());
+ /* Round up to the next power of two. This makes it easy to ensure
+ an _asso_value[c] is >= 0 and < asso_value_max. Also, the jump value
+ being odd, it guarantees that Search::try_asso_value() will iterate
+ through different values for _asso_value[c]. */
+ if (asso_value_max == 0)
+ asso_value_max = 1;
+ asso_value_max |= asso_value_max >> 1;
+ asso_value_max |= asso_value_max >> 2;
+ asso_value_max |= asso_value_max >> 4;
+ asso_value_max |= asso_value_max >> 8;
+ asso_value_max |= asso_value_max >> 16;
+ asso_value_max++;
+ _asso_value_max = asso_value_max;
+
+ /* Given the bound for _asso_values[c], we have a bound for the possible
+ hash values, as computed in compute_hash(). */
+ _max_hash_value = (option[NOLENGTH] ? 0 : _max_key_len)
+ + (_asso_value_max - 1) * _max_selchars_length;
+ /* Allocate a sparse bit vector for detection of collisions of hash
+ values. */
+ _collision_detector = new Bool_Array (_max_hash_value + 1);
+
+ 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);
+
+ int field_width;
+
+ field_width = 0;
+ {
+ for (KeywordExt_List *temp = _head; temp; temp = temp->rest())
+ {
+ KeywordExt *keyword = temp->first();
+ if (field_width < keyword->_selchars_length)
+ field_width = keyword->_selchars_length;
+ }
+ }
+
+ fprintf (stderr, "\ndumping the keyword list without duplicates\n");
+ fprintf (stderr, "keyword #, %*s, keyword\n", field_width, "keysig");
+ int i = 0;
+ for (KeywordExt_List *temp = _head; temp; temp = temp->rest())
+ {
+ KeywordExt *keyword = temp->first();
+ fprintf (stderr, "%9d, ", ++i);
+ if (field_width > keyword->_selchars_length)
+ fprintf (stderr, "%*s", field_width - keyword->_selchars_length, "");
+ for (int j = 0; j < keyword->_selchars_length; j++)
+ putc (keyword->_selchars[j], stderr);
+ fprintf (stderr, ", %.*s\n",
+ keyword->_allchars_length, keyword->_allchars);
+ }
+ fprintf (stderr, "\nend of keyword list\n\n");
+ }
+
+ if (option[RANDOM] || option.get_jump () == 0)
+ /* We will use rand(), so initialize the random number generator. */
+ srand (static_cast<long>(time (0)));
+
+ _initial_asso_value = (option[RANDOM] ? -1 : option.get_initial_asso_value ());
+ _jump = option.get_jump ();
+}
+
+/* Finds some _asso_values[] that fit. */
+
+/* The idea is to choose the _asso_values[] one by one, in a way that
+ a choice that has been made never needs to be undone later. This
+ means that we split the work into several steps. Each step chooses
+ one or more _asso_values[c]. The result of choosing one or more
+ _asso_values[c] is that the partitioning of the keyword set gets
+ broader.
+ Look at this partitioning: After every step, the _asso_values[] of a
+ certain set C of characters are undetermined. (At the beginning, C
+ is the set of characters c with _occurrences[c] > 0. At the end, C
+ is empty.) To each keyword K, we associate the multiset of _selchars
+ for which the _asso_values[] are undetermined:
+ K --> K->_selchars intersect C.
+ Consider two keywords equivalent if their value under this mapping is
+ the same. This introduces an equivalence relation on the set of
+ keywords. The equivalence classes partition the keyword set. (At the
+ beginning, the partition is the finest possible: each K is an equivalence
+ class by itself, because all K have a different _selchars. At the end,
+ all K have been merged into a single equivalence class.)
+ The partition before a step is always a refinement of the partition
+ after the step.
+ We choose the steps in such a way that the partition really becomes
+ broader at each step. (A step that only chooses an _asso_values[c]
+ without changing the partition is better merged with the previous step,
+ to avoid useless backtracking.) */
+
+struct EquivalenceClass
+{
+ /* The keywords in this equivalence class. */
+ KeywordExt_List * _keywords;
+ KeywordExt_List * _keywords_last;
+ /* The number of keywords in this equivalence class. */
+ unsigned int _cardinality;
+ /* The undetermined selected characters for the keywords in this
+ equivalence class, as a canonically reordered multiset. */
+ unsigned int * _undetermined_chars;
+ unsigned int _undetermined_chars_length;
+
+ EquivalenceClass * _next;
+};
+
+struct Step
+{
+ /* The characters whose values are being determined in this step. */
+ unsigned int _changing_count;
+ unsigned int * _changing;
+ /* Exclusive upper bound for the _asso_values[c] of this step.
+ A power of 2. */
+ unsigned int _asso_value_max;
+ /* The characters whose values will be determined after this step. */
+ bool * _undetermined;
+ /* The keyword set partition after this step. */
+ EquivalenceClass * _partition;
+ /* The expected number of iterations in this step. */
+ double _expected_lower;
+ double _expected_upper;
+
+ Step * _next;
+};
+
+static inline bool
+equals (const unsigned int *ptr1, const unsigned int *ptr2, unsigned int len)
+{
+ while (len > 0)
+ {
+ if (*ptr1 != *ptr2)
+ return false;
+ ptr1++;
+ ptr2++;
+ len--;
+ }
+ return true;
+}
+
+EquivalenceClass *
+Search::compute_partition (bool *undetermined) const
+{
+ EquivalenceClass *partition = NULL;
+ EquivalenceClass *partition_last = NULL;
+ for (KeywordExt_List *temp = _head; temp; temp = temp->rest())
+ {
+ KeywordExt *keyword = temp->first();
+
+ /* Compute the undetermined characters for this keyword. */
+ unsigned int *undetermined_chars =
+ new unsigned int[keyword->_selchars_length];
+ unsigned int undetermined_chars_length = 0;
+
+ for (int i = 0; i < keyword->_selchars_length; i++)
+ if (undetermined[keyword->_selchars[i]])
+ undetermined_chars[undetermined_chars_length++] = keyword->_selchars[i];
+
+ /* Look up the equivalence class to which this keyword belongs. */
+ EquivalenceClass *equclass;
+ for (equclass = partition; equclass; equclass = equclass->_next)
+ if (equclass->_undetermined_chars_length == undetermined_chars_length
+ && equals (equclass->_undetermined_chars, undetermined_chars,
+ undetermined_chars_length))
+ break;
+ if (equclass == NULL)
+ {
+ equclass = new EquivalenceClass();
+ equclass->_keywords = NULL;
+ equclass->_keywords_last = NULL;
+ equclass->_cardinality = 0;
+ equclass->_undetermined_chars = undetermined_chars;
+ equclass->_undetermined_chars_length = undetermined_chars_length;
+ equclass->_next = NULL;
+ if (partition)
+ partition_last->_next = equclass;
+ else
+ partition = equclass;
+ partition_last = equclass;
+ }
+ else
+ delete[] undetermined_chars;
+
+ /* Add the keyword to the equivalence class. */
+ KeywordExt_List *cons = new KeywordExt_List(keyword);
+ if (equclass->_keywords)
+ equclass->_keywords_last->rest() = cons;
+ else
+ equclass->_keywords = cons;
+ equclass->_keywords_last = cons;
+ equclass->_cardinality++;
+ }
+
+ /* Free some of the allocated memory. The caller doesn't need it. */
+ for (EquivalenceClass *cls = partition; cls; cls = cls->_next)
+ delete[] cls->_undetermined_chars;
+
+ return partition;
+}
+
+static void
+delete_partition (EquivalenceClass *partition)
+{
+ while (partition != NULL)
+ {
+ EquivalenceClass *equclass = partition;
+ partition = equclass->_next;
+ delete_list (equclass->_keywords);
+ //delete[] equclass->_undetermined_chars; // already freed above
+ delete equclass;
+ }
+}
+
+/* Compute the possible number of collisions when _asso_values[c] is
+ chosen, leading to the given partition. */
+unsigned int
+Search::count_possible_collisions (EquivalenceClass *partition, unsigned int c) const
+{
+ /* Every equivalence class p is split according to the frequency of
+ occurrence of c, leading to equivalence classes p1, p2, ...
+ This leads to (|p|^2 - |p1|^2 - |p2|^2 - ...)/2 possible collisions.
+ Return the sum of this expression over all equivalence classes. */
+ unsigned int sum = 0;
+ unsigned int m = _max_selchars_length;
+ DYNAMIC_ARRAY (split_cardinalities, unsigned int, m + 1);
+ for (EquivalenceClass *cls = partition; cls; cls = cls->_next)
+ {
+ for (unsigned int i = 0; i <= m; i++)
+ split_cardinalities[i] = 0;
+
+ for (KeywordExt_List *temp = cls->_keywords; temp; temp = temp->rest())
+ {
+ KeywordExt *keyword = temp->first();
+
+ unsigned int count = 0;
+ for (int i = 0; i < keyword->_selchars_length; i++)
+ if (keyword->_selchars[i] == c)
+ count++;
+
+ split_cardinalities[count]++;
+ }
+
+ sum += cls->_cardinality * cls->_cardinality;
+ for (unsigned int i = 0; i <= m; i++)
+ sum -= split_cardinalities[i] * split_cardinalities[i];
+ }
+ FREE_DYNAMIC_ARRAY (split_cardinalities);
+ return sum;
+}
+
+/* Test whether adding c to the undetermined characters changes the given
+ partition. */
+bool
+Search::unchanged_partition (EquivalenceClass *partition, unsigned int c) const
+{
+ for (EquivalenceClass *cls = partition; cls; cls = cls->_next)
+ {
+ unsigned int first_count = UINT_MAX;
+
+ for (KeywordExt_List *temp = cls->_keywords; temp; temp = temp->rest())
+ {
+ KeywordExt *keyword = temp->first();
+
+ unsigned int count = 0;
+ for (int i = 0; i < keyword->_selchars_length; i++)
+ if (keyword->_selchars[i] == c)
+ count++;
+
+ if (temp == cls->_keywords)
+ first_count = count;
+ else if (count != first_count)
+ /* c would split this equivalence class. */
+ return false;
+ }
+ }
+ return true;
+}
+
+void
+Search::find_asso_values ()
+{
+ Step *steps;
+
+ /* Determine the steps, starting with the last one. */
+ {
+ bool *undetermined;
+ bool *determined;
+
+ steps = NULL;
+
+ undetermined = new bool[_alpha_size];
+ for (unsigned int c = 0; c < _alpha_size; c++)
+ undetermined[c] = false;
+
+ determined = new bool[_alpha_size];
+ for (unsigned int c = 0; c < _alpha_size; c++)
+ determined[c] = true;
+
+ for (;;)
+ {
+ /* Compute the partition that needs to be refined. */
+ EquivalenceClass *partition = compute_partition (undetermined);
+
+ /* Determine the main character to be chosen in this step.
+ Choosing such a character c has the effect of splitting every
+ equivalence class (according the the frequency of occurrence of c).
+ We choose the c with the minimum number of possible collisions,
+ so that characters which lead to a large number of collisions get
+ handled early during the search. */
+ unsigned int chosen_c;
+ unsigned int chosen_possible_collisions;
+ {
+ unsigned int best_c = 0;
+ unsigned int best_possible_collisions = UINT_MAX;
+ for (unsigned int c = 0; c < _alpha_size; c++)
+ if (_occurrences[c] > 0 && determined[c])
+ {
+ unsigned int possible_collisions =
+ count_possible_collisions (partition, c);
+ if (possible_collisions < best_possible_collisions)
+ {
+ best_c = c;
+ best_possible_collisions = possible_collisions;
+ }
+ }
+ if (best_possible_collisions == UINT_MAX)
+ {
+ /* All c with _occurrences[c] > 0 are undetermined. We are
+ are the starting situation and don't need any more step. */
+ delete_partition (partition);
+ break;
+ }
+ chosen_c = best_c;
+ chosen_possible_collisions = best_possible_collisions;
+ }
+
+ /* We need one more step. */
+ Step *step = new Step();
+
+ step->_undetermined = new bool[_alpha_size];
+ memcpy (step->_undetermined, undetermined, _alpha_size*sizeof(bool));
+
+ step->_partition = partition;
+
+ /* Now determine how the equivalence classes will be before this
+ step. */
+ undetermined[chosen_c] = true;
+ partition = compute_partition (undetermined);
+
+ /* Now determine which other characters should be determined in this
+ step, because they will not change the equivalence classes at
+ this point. It is the set of all c which, for all equivalence
+ classes, have the same frequency of occurrence in every keyword
+ of the equivalence class. */
+ for (unsigned int c = 0; c < _alpha_size; c++)
+ if (_occurrences[c] > 0 && determined[c]
+ && unchanged_partition (partition, c))
+ {
+ undetermined[c] = true;
+ determined[c] = false;
+ }
+
+ /* main_c must be one of these. */
+ if (determined[chosen_c])
+ abort ();
+
+ /* Now the set of changing characters of this step. */
+ unsigned int changing_count;
+
+ changing_count = 0;
+ for (unsigned int c = 0; c < _alpha_size; c++)
+ if (undetermined[c] && !step->_undetermined[c])
+ changing_count++;
+
+ unsigned int *changing = new unsigned int[changing_count];
+ changing_count = 0;
+ for (unsigned int c = 0; c < _alpha_size; c++)
+ if (undetermined[c] && !step->_undetermined[c])
+ changing[changing_count++] = c;
+
+ step->_changing = changing;
+ step->_changing_count = changing_count;
+
+ step->_asso_value_max = _asso_value_max;
+
+ step->_expected_lower =
+ exp (static_cast<double>(chosen_possible_collisions)
+ / static_cast<double>(_max_hash_value));
+ step->_expected_upper =
+ exp (static_cast<double>(chosen_possible_collisions)
+ / static_cast<double>(_asso_value_max));
+
+ delete_partition (partition);
+
+ step->_next = steps;
+ steps = step;
+ }
+
+ delete[] determined;
+ delete[] undetermined;
+ }
+
+ if (option[DEBUG])
+ {
+ unsigned int stepno = 0;
+ for (Step *step = steps; step; step = step->_next)
+ {
+ stepno++;
+ fprintf (stderr, "Step %u chooses _asso_values[", stepno);
+ for (unsigned int i = 0; i < step->_changing_count; i++)
+ {
+ if (i > 0)
+ fprintf (stderr, ",");
+ fprintf (stderr, "'%c'", step->_changing[i]);
+ }
+ fprintf (stderr, "], expected number of iterations between %g and %g.\n",
+ step->_expected_lower, step->_expected_upper);
+ fprintf (stderr, "Keyword equivalence classes:\n");
+ for (EquivalenceClass *cls = step->_partition; cls; cls = cls->_next)
+ {
+ fprintf (stderr, "\n");
+ for (KeywordExt_List *temp = cls->_keywords; temp; temp = temp->rest())
+ {
+ KeywordExt *keyword = temp->first();
+ fprintf (stderr, " %.*s\n",
+ keyword->_allchars_length, keyword->_allchars);
+ }
+ }
+ fprintf (stderr, "\n");
+ }
+ }
+
+ /* Initialize _asso_values[]. (The value given here matters only
+ for those c which occur in all keywords with equal multiplicity.) */
+ for (unsigned int c = 0; c < _alpha_size; c++)
+ _asso_values[c] = 0;
+
+ unsigned int stepno = 0;
+ for (Step *step = steps; step; step = step->_next)
+ {
+ stepno++;
+
+ /* Initialize the asso_values[]. */
+ unsigned int k = step->_changing_count;
+ for (unsigned int i = 0; i < k; i++)
+ {
+ unsigned int c = step->_changing[i];
+ _asso_values[c] =
+ (_initial_asso_value < 0 ? rand () : _initial_asso_value)
+ & (step->_asso_value_max - 1);
+ }
+
+ unsigned int iterations = 0;
+ DYNAMIC_ARRAY (iter, unsigned int, k);
+ for (unsigned int i = 0; i < k; i++)
+ iter[i] = 0;
+ unsigned int ii = (_jump != 0 ? k - 1 : 0);
+
+ for (;;)
+ {
+ /* Test whether these asso_values[] lead to collisions among
+ the equivalence classes that should be collision-free. */
+ bool has_collision = false;
+ for (EquivalenceClass *cls = step->_partition; cls; cls = cls->_next)
+ {
+ /* Iteration Number array is a win, O(1) initialization time! */
+ _collision_detector->clear ();
+
+ for (KeywordExt_List *ptr = cls->_keywords; ptr; ptr = ptr->rest())
+ {
+ KeywordExt *keyword = ptr->first();
+
+ /* Compute the new hash code for the keyword, leaving apart
+ the yet undetermined asso_values[]. */
+ int hashcode;
+ {
+ int sum = option[NOLENGTH] ? 0 : keyword->_allchars_length;
+ const unsigned int *p = keyword->_selchars;
+ int i = keyword->_selchars_length;
+ for (; i > 0; p++, i--)
+ if (!step->_undetermined[*p])
+ sum += _asso_values[*p];
+ hashcode = sum;
+ }
+
+ /* See whether it collides with another keyword's hash code,
+ from the same equivalence class. */
+ if (_collision_detector->set_bit (hashcode))
+ {
+ has_collision = true;
+ break;
+ }
+ }
+
+ /* Don't need to continue looking at the other equivalence
+ classes if we already have found a collision. */
+ if (has_collision)
+ break;
+ }
+
+ iterations++;
+ if (!has_collision)
+ break;
+
+ /* Try other asso_values[]. */
+ if (_jump != 0)
+ {
+ /* The way we try various values for
+ asso_values[step->_changing[0],...step->_changing[k-1]]
+ is like this:
+ for (bound = 0,1,...)
+ for (ii = 0,...,k-1)
+ iter[ii] := bound
+ iter[0..ii-1] := values <= bound
+ iter[ii+1..k-1] := values < bound
+ and
+ asso_values[step->_changing[i]] =
+ _initial_asso_value + iter[i] * _jump.
+ This makes it more likely to find small asso_values[].
+ */
+ unsigned int bound = iter[ii];
+ unsigned int i = 0;
+ while (i < ii)
+ {
+ unsigned int c = step->_changing[i];
+ iter[i]++;
+ _asso_values[c] =
+ (_asso_values[c] + _jump) & (step->_asso_value_max - 1);
+ if (iter[i] <= bound)
+ goto found_next;
+ _asso_values[c] =
+ (_asso_values[c] - iter[i] * _jump)
+ & (step->_asso_value_max - 1);
+ iter[i] = 0;
+ i++;
+ }
+ i = ii + 1;
+ while (i < k)
+ {
+ unsigned int c = step->_changing[i];
+ iter[i]++;
+ _asso_values[c] =
+ (_asso_values[c] + _jump) & (step->_asso_value_max - 1);
+ if (iter[i] < bound)
+ goto found_next;
+ _asso_values[c] =
+ (_asso_values[c] - iter[i] * _jump)
+ & (step->_asso_value_max - 1);
+ iter[i] = 0;
+ i++;
+ }
+ /* Switch from one ii to the next. */
+ {
+ unsigned int c = step->_changing[ii];
+ _asso_values[c] =
+ (_asso_values[c] - bound * _jump)
+ & (step->_asso_value_max - 1);
+ iter[ii] = 0;
+ }
+ /* Here all iter[i] == 0. */
+ ii++;
+ if (ii == k)
+ {
+ ii = 0;
+ bound++;
+ if (bound == step->_asso_value_max)
+ {
+ /* Out of search space! We can either backtrack, or
+ increase the available search space of this step.
+ It seems simpler to choose the latter solution. */
+ step->_asso_value_max = 2 * step->_asso_value_max;
+ if (step->_asso_value_max > _asso_value_max)
+ {
+ _asso_value_max = step->_asso_value_max;
+ /* Reinitialize _max_hash_value. */
+ _max_hash_value =
+ (option[NOLENGTH] ? 0 : _max_key_len)
+ + (_asso_value_max - 1) * _max_selchars_length;
+ /* Reinitialize _collision_detector. */
+ delete _collision_detector;
+ _collision_detector =
+ new Bool_Array (_max_hash_value + 1);
+ }
+ }
+ }
+ {
+ unsigned int c = step->_changing[ii];
+ iter[ii] = bound;
+ _asso_values[c] =
+ (_asso_values[c] + bound * _jump)
+ & (step->_asso_value_max - 1);
+ }
+ found_next: ;
+ }
+ else
+ {
+ /* Random. */
+ unsigned int c = step->_changing[ii];
+ _asso_values[c] =
+ (_asso_values[c] + rand ()) & (step->_asso_value_max - 1);
+ /* Next time, change the next c. */
+ ii++;
+ if (ii == k)
+ ii = 0;
+ }
+ }
+ FREE_DYNAMIC_ARRAY (iter);
+
+ if (option[DEBUG])
+ {
+ fprintf (stderr, "Step %u chose _asso_values[", stepno);
+ for (unsigned int i = 0; i < step->_changing_count; i++)
+ {
+ if (i > 0)
+ fprintf (stderr, ",");
+ fprintf (stderr, "'%c'", step->_changing[i]);
+ }
+ fprintf (stderr, "] in %u iterations.\n", iterations);
+ }
+ }
+
+ /* Free allocated memory. */
+ while (steps != NULL)
+ {
+ Step *step = steps;
+ steps = step->_next;
+ delete[] step->_changing;
+ delete[] step->_undetermined;
+ delete_partition (step->_partition);
+ delete step;
+ }
+}
+
+/* Computes a keyword's hash value, relative to the current _asso_values[],
+ and stores it in keyword->_hash_value. */
+
+inline int
+Search::compute_hash (KeywordExt *keyword) const
+{
+ int sum = option[NOLENGTH] ? 0 : keyword->_allchars_length;
+
+ const unsigned int *p = keyword->_selchars;
+ int i = keyword->_selchars_length;
+ for (; i > 0; p++, i--)
+ sum += _asso_values[*p];
+
+ return keyword->_hash_value = sum;
+}
+
+/* Finds good _asso_values[]. */
+
+void
+Search::find_good_asso_values ()
+{
+ prepare_asso_values ();
+
+ /* Search for good _asso_values[]. */
+ int asso_iteration;
+ if ((asso_iteration = option.get_asso_iterations ()) == 0)
+ /* Try only the given _initial_asso_value and _jump. */
+ find_asso_values ();
+ else
+ {
+ /* Try different pairs of _initial_asso_value and _jump, in the
+ following order:
+ (0, 1)
+ (1, 1)
+ (2, 1) (0, 3)
+ (3, 1) (1, 3)
+ (4, 1) (2, 3) (0, 5)
+ (5, 1) (3, 3) (1, 5)
+ ..... */
+ KeywordExt_List *saved_head = _head;
+ int best_initial_asso_value = 0;
+ int best_jump = 1;
+ int *best_asso_values = new int[_alpha_size];
+ int best_collisions = INT_MAX;
+ int best_max_hash_value = INT_MAX;
+
+ _initial_asso_value = 0; _jump = 1;
+ for (;;)
+ {
+ /* Restore the keyword list in its original order. */
+ _head = copy_list (saved_head);
+ /* Find good _asso_values[]. */
+ find_asso_values ();
+ /* Test whether it is the best solution so far. */
+ int collisions = 0;
+ int max_hash_value = INT_MIN;
+ _collision_detector->clear ();
+ for (KeywordExt_List *ptr = _head; ptr; ptr = ptr->rest())
+ {
+ KeywordExt *keyword = ptr->first();
+ int hashcode = compute_hash (keyword);
+ if (max_hash_value < hashcode)
+ max_hash_value = hashcode;
+ if (_collision_detector->set_bit (hashcode))
+ collisions++;
+ }
+ if (collisions < best_collisions
+ || (collisions == best_collisions
+ && max_hash_value < best_max_hash_value))
+ {
+ memcpy (best_asso_values, _asso_values,
+ _alpha_size * sizeof (_asso_values[0]));
+ best_collisions = collisions;
+ best_max_hash_value = max_hash_value;
+ }
+ /* Delete the copied keyword list. */
+ delete_list (_head);
+
+ if (--asso_iteration == 0)
+ break;
+ /* Prepare for next iteration. */
+ if (_initial_asso_value >= 2)
+ _initial_asso_value -= 2, _jump += 2;
+ else
+ _initial_asso_value += _jump, _jump = 1;
+ }
+ _head = saved_head;
+ /* Install the best found asso_values. */
+ _initial_asso_value = best_initial_asso_value;
+ _jump = best_jump;
+ memcpy (_asso_values, best_asso_values,
+ _alpha_size * sizeof (_asso_values[0]));
+ delete[] best_asso_values;
+ /* The keywords' _hash_value fields are recomputed below. */
+ }
+}
+
+/* ========================================================================= */
+
+/* Comparison function for sorting by increasing _hash_value. */
+static bool
+less_by_hash_value (KeywordExt *keyword1, KeywordExt *keyword2)
+{
+ return keyword1->_hash_value < keyword2->_hash_value;
+}
+
+/* Sorts the keyword list by hash value. */
+
+void
+Search::sort ()
+{
+ _head = mergesort_list (_head, less_by_hash_value);
+}
+
+void
+Search::optimize ()
+{
+ /* Preparations. */
+ prepare ();
+
+ /* Step 1: Finding good byte positions. */
+ find_positions ();
+
+ /* Step 2: Finding good alpha increments. */
+ find_alpha_inc ();
+
+ /* Step 3: Finding good asso_values. */
+ find_good_asso_values ();
+
+ /* Make one final check, just to make sure nothing weird happened.... */
+ _collision_detector->clear ();
+ for (KeywordExt_List *curr_ptr = _head; curr_ptr; curr_ptr = curr_ptr->rest())
+ {
+ KeywordExt *curr = curr_ptr->first();
+ unsigned int hashcode = compute_hash (curr);
+ if (_collision_detector->set_bit (hashcode))
+ {
+ /* This shouldn't happen. proj1, proj2, proj3 must have been
+ computed to be injective on the given keyword set. */
+ fprintf (stderr,
+ "\nInternal error, unexpected duplicate hash code\n");
+ if (option[POSITIONS])
+ fprintf (stderr, "try options -m or -r, or use new key positions.\n\n");
+ else
+ fprintf (stderr, "try options -m or -r.\n\n");
+ exit (1);
+ }
+ }
+
+ /* Sorts the keyword list by hash value. */
+ sort ();
+
+ /* Set unused asso_values[c] to max_hash_value + 1. This is not absolutely
+ necessary, but speeds up the lookup function in many cases of lookup
+ failure: no string comparison is needed once the hash value of a string
+ is larger than the hash value of any keyword. */
+ int max_hash_value;
+ {
+ KeywordExt_List *temp;
+ for (temp = _head; temp->rest(); temp = temp->rest())
+ ;
+ max_hash_value = temp->first()->_hash_value;
+ }
+ for (unsigned int c = 0; c < _alpha_size; c++)
+ if (_occurrences[c] == 0)
+ _asso_values[c] = max_hash_value + 1;
+
+ /* Propagate unified asso_values. */
+ if (_alpha_unify)
+ for (unsigned int c = 0; c < _alpha_size; c++)
+ if (_alpha_unify[c] != c)
+ _asso_values[c] = _asso_values[_alpha_unify[c]];
+}
+
+/* Prints out some diagnostics upon completion. */
+
+Search::~Search ()
+{
+ delete _collision_detector;
+ if (option[DEBUG])
+ {
+ fprintf (stderr, "\ndumping occurrence and associated values tables\n");
+
+ for (unsigned 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");
+
+ 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);
+
+ int field_width = _max_selchars_length;
+ fprintf (stderr, "\nList contents are:\n(hash value, key length, index, %*s, keyword):\n",
+ field_width, "selchars");
+ for (KeywordExt_List *ptr = _head; ptr; ptr = ptr->rest())
+ {
+ fprintf (stderr, "%11d,%11d,%6d, ",
+ ptr->first()->_hash_value, ptr->first()->_allchars_length, ptr->first()->_final_index);
+ if (field_width > ptr->first()->_selchars_length)
+ fprintf (stderr, "%*s", field_width - ptr->first()->_selchars_length, "");
+ for (int j = 0; j < ptr->first()->_selchars_length; j++)
+ putc (ptr->first()->_selchars[j], stderr);
+ fprintf (stderr, ", %.*s\n",
+ ptr->first()->_allchars_length, ptr->first()->_allchars);
+ }
+
+ fprintf (stderr, "End dumping list.\n\n");
+ }
+ delete[] _asso_values;
+ delete[] _occurrences;
+ delete[] _alpha_unify;
+ delete[] _alpha_inc;
+}
diff --git a/contrib/gperf/src/search.h b/contrib/gperf/src/search.h
new file mode 100644
index 0000000..6b562c9
--- /dev/null
+++ b/contrib/gperf/src/search.h
@@ -0,0 +1,165 @@
+/* This may look like C code, but it is really -*- C++ -*- */
+
+/* Search algorithm.
+
+ Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
+
+ 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 2, 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 this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef search_h
+#define search_h 1
+
+#include "keyword-list.h"
+#include "positions.h"
+#include "bool-array.h"
+
+struct EquivalenceClass;
+
+class Search
+{
+public:
+ Search (KeywordExt_List *list);
+ ~Search ();
+ void optimize ();
+private:
+ void prepare ();
+
+ /* Computes the upper bound on the indices passed to asso_values[],
+ assuming no alpha_increments. */
+ unsigned int compute_alpha_size () const;
+
+ /* Computes the unification rules between different asso_values[c],
+ assuming no alpha_increments. */
+ unsigned int * compute_alpha_unify () const;
+
+ /* Initializes each keyword's _selchars array. */
+ void init_selchars_tuple (const Positions& positions, const unsigned int *alpha_unify) const;
+ /* Deletes each keyword's _selchars array. */
+ void delete_selchars () const;
+
+ /* Count the duplicate keywords that occur with a given set of positions. */
+ unsigned int count_duplicates_tuple (const Positions& positions, const unsigned int *alpha_unify) const;
+
+ /* Find good key positions. */
+ void find_positions ();
+
+ /* Count the duplicate keywords that occur with the found set of positions. */
+ unsigned int count_duplicates_tuple () const;
+
+ /* Computes the upper bound on the indices passed to asso_values[]. */
+ unsigned int compute_alpha_size (const unsigned int *alpha_inc) const;
+
+ /* Computes the unification rules between different asso_values[c]. */
+ unsigned int * compute_alpha_unify (const Positions& positions, const unsigned int *alpha_inc) const;
+
+ /* Initializes each keyword's _selchars array. */
+ void init_selchars_multiset (const Positions& positions, const unsigned int *alpha_unify, const unsigned int *alpha_inc) const;
+
+ /* Count the duplicate keywords that occur with the given set of positions
+ and a given alpha_inc[] array. */
+ unsigned int count_duplicates_multiset (const unsigned int *alpha_inc) const;
+
+ /* Find good _alpha_inc[]. */
+ void find_alpha_inc ();
+
+ /* Initializes the asso_values[] related parameters. */
+ void prepare_asso_values ();
+
+ EquivalenceClass * compute_partition (bool *undetermined) const;
+
+ unsigned int count_possible_collisions (EquivalenceClass *partition, unsigned int c) const;
+
+ bool unchanged_partition (EquivalenceClass *partition, unsigned int c) const;
+
+ /* Finds some _asso_values[] that fit. */
+ void find_asso_values ();
+
+ /* Computes a keyword's hash value, relative to the current _asso_values[],
+ and stores it in keyword->_hash_value. */
+ int compute_hash (KeywordExt *keyword) const;
+
+ /* Finds good _asso_values[]. */
+ void find_good_asso_values ();
+
+ /* Sorts the keyword list by hash value. */
+ void sort ();
+
+public:
+
+ /* Linked list of keywords. */
+ KeywordExt_List * _head;
+
+ /* Total number of keywords, counting duplicates. */
+ int _total_keys;
+
+ /* Maximum length of the longest keyword. */
+ int _max_key_len;
+
+ /* Minimum length of the shortest keyword. */
+ int _min_key_len;
+
+ /* User-specified or computed key positions. */
+ Positions _key_positions;
+
+ /* Adjustments to add to bytes add specific key positions. */
+ unsigned int * _alpha_inc;
+
+ /* Size of alphabet. */
+ unsigned int _alpha_size;
+
+ /* Alphabet character unification, either the identity or a mapping from
+ upper case characters to lower case characters (and maybe more). */
+ unsigned int * _alpha_unify;
+
+ /* Maximum _selchars_length over all keywords. */
+ unsigned int _max_selchars_length;
+
+ /* Total number of duplicates that have been moved to _duplicate_link lists
+ (not counting their representatives which stay on the main list). */
+ int _total_duplicates;
+
+ /* Counts occurrences of each key set character.
+ _occurrences[c] is the number of times that c occurs among the _selchars
+ of a keyword. */
+ int * _occurrences;
+ /* Value associated with each character. */
+ int * _asso_values;
+
+private:
+
+ /* Length of _head list. Number of keywords, not counting duplicates. */
+ int _list_len;
+
+ /* Exclusive upper bound for every _asso_values[c]. A power of 2. */
+ unsigned int _asso_value_max;
+
+ /* Initial value for asso_values table. -1 means random. */
+ int _initial_asso_value;
+ /* Jump length when trying alternative values. 0 means random. */
+ int _jump;
+
+ /* Maximal possible hash value. */
+ int _max_hash_value;
+
+ /* Sparse bit vector for collision detection. */
+ Bool_Array * _collision_detector;
+};
+
+#endif
diff --git a/contrib/gperf/src/trace.cc b/contrib/gperf/src/trace.cc
deleted file mode 100644
index e571aba..0000000
--- a/contrib/gperf/src/trace.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-/* 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
deleted file mode 100644
index f16fcc5..0000000
--- a/contrib/gperf/src/trace.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* 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
deleted file mode 100644
index 1da014d..0000000
--- a/contrib/gperf/src/vectors.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-/* 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
deleted file mode 100644
index 28a1053..0000000
--- a/contrib/gperf/src/vectors.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* 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
index 8f07c69..f86ef4d 100644
--- a/contrib/gperf/src/version.cc
+++ b/contrib/gperf/src/version.cc
@@ -1,22 +1,28 @@
/* Current program version number.
- Copyright (C) 1989-1998, 2000 Free Software Foundation, Inc.
- written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+ Copyright (C) 1989-1998, 2000, 2002-2003, 2005, 2007 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
-This file is part of GNU GPERF.
+ 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 free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
-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.
+ 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. */
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-const char *version_string = "2.7.2";
+/* Specification. */
+#include "version.h"
+
+/* Current release version. */
+const char *version_string = "3.0.3";
diff --git a/contrib/gperf/src/version.h b/contrib/gperf/src/version.h
index 4ffba2e..feafbe9 100644
--- a/contrib/gperf/src/version.h
+++ b/contrib/gperf/src/version.h
@@ -1,23 +1,25 @@
/* Current program version number.
- Copyright (C) 1989-1998 Free Software Foundation, Inc.
- written by Douglas C. Schmidt (schmidt@ics.uci.edu)
+ Copyright (C) 1989-1998, 2002 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
-This file is part of GNU GPERF.
+ 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 free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
-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.
+ 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. */
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* Current release version. */
extern const char *version_string;
OpenPOWER on IntegriCloud