diff options
-rw-r--r-- | ChangeLog | 43 | ||||
-rw-r--r-- | NEWS | 10 | ||||
-rw-r--r-- | doc/gperf.texi | 67 | ||||
-rw-r--r-- | src/input.cc | 15 | ||||
-rw-r--r-- | src/options.cc | 45 | ||||
-rw-r--r-- | src/options.h | 29 | ||||
-rw-r--r-- | src/options.icc | 9 | ||||
-rw-r--r-- | src/output.cc | 296 | ||||
-rw-r--r-- | src/output.h | 11 | ||||
-rw-r--r-- | tests/Makefile.in | 175 | ||||
-rw-r--r-- | tests/jstest4.gperf | 147 | ||||
-rw-r--r-- | tests/test-6.exp | 5 |
12 files changed, 709 insertions, 143 deletions
@@ -1,5 +1,48 @@ 2003-01-01 Bruno Haible <bruno@clisp.org> + * src/options.h (NULLSTRINGS): New enum value. + (Options::get_stringpool_name, Options::set_stringpool_name): New + method declarations. + (Options::_stringpool_name): New field. + * src/options.icc (Options::get_stringpool_name): New method. + * src/options.cc (DEFAULT_STRINGPOOL_NAME): New variable. + (Options::long_usage): Document -Q and --null-strings. + (Options::Options): Initialize _stringpool_name. + (Options::~Options): Output _stringpool_name, NULLSTRINGS values too. + (Options::set_stringpool_name): New method. + (long_options): Add options --string-pool-name, --null-strings. + (Options::parse_options): Implement options -P, -Q and --null-strings. + * src/input.cc (Input::read_input): Recognize declarations %pic, + %define string-pool-name, %null-strings. + * src/output.h (Output::output_string_pool, + Output::output_lookup_pools): New method declarations. + (Output::_wordlist_eltype): New field. + * src/output.cc (Output::output_keylength_table): Trivial + simplification. + (Output::output_string_pool): New method. + (output_keyword_entry): Add stringpool_index argument. For SHAREDLIB, + use struct offsets. + (output_keyword_blank_entries): For SHAREDLIB, use -1 instead of "". + (Output::output_keyword_table): Use _wordlist_eltype instead of + _struct_tag. Compute stringpool_index for output_keyword_entry. + (Output::output_lookup_pools): New method. + (Output::output_lookup_function_body): Use _wordlist_eltype instead of + _struct_tag. For SHAREDLIB, use "+ stringpool" to convert offsets to + strings. Use "o >= 0" to test for nonempty table entry. + (Output::output_lookup_function): Call output_lookup_pools. + (Output::output): Initialize _wordlist_eltype. Call + output_lookup_pools. + * tests/jstest4.gperf: New file. + * tests/test-6.exp: Update. + * tests/Makefile.in (check-lang-syntax): Drop test of -p. Add tests of + -P and -Q. + * doc/gperf.texi (User-supplied Struct): Mention that first field has + to be of type 'int' if -P is given. + (Gperf Declarations): Document %pic, %define string-pool-name, + %null-strings. + (Output Details): Update description of option -P. Document options -Q + and --null-strings. + * tests/Makefile.in (check-link-c, check-ada, check-pascal, check-test): Omit option -p. * tests/c-parse.exp: Regenerated. @@ -23,6 +23,9 @@ New in 2.97: %enum %includes %global-table + %pic + %define string-pool-name NAME + %null-strings %define word-array-name NAME %switch=COUNT %omit-struct-type @@ -41,8 +44,11 @@ New in 2.97: the table's size will grow as needed. Earlier versions of gperf bailed out with an "Internal error, duplicate hash code value". * The options -f/--fast and -o/--occurrence-sort have no effect any more. -* Added option -P/--pic that optimizes the generated code for use in shared - libraries. +* Added options -P/--pic and --null-strings that optimize the generated code + for use in shared libraries. -P/--pic does a perfect optimization but may + require some small code changes (see the documentation for details), whereas + --null-strings does only a half-hearted optimization but works without + needing any change to surrounding code. * Added option --ignore-case that produces a case independent lookup function. * Bug fixes. diff --git a/doc/gperf.texi b/doc/gperf.texi index 56676ce..0ebfd5d 100644 --- a/doc/gperf.texi +++ b/doc/gperf.texi @@ -7,7 +7,7 @@ @c some day we should @include version.texi instead of defining @c these values at hand. -@set UPDATED 8 December 2002 +@set UPDATED 1 January 2003 @set EDITION 2.7.2 @set VERSION 2.7.2 @c --------------------- @@ -28,7 +28,7 @@ This file documents the features of the GNU Perfect Hash Function Generator @value{VERSION}. -Copyright @copyright{} 1989-2002 Free Software Foundation, Inc. +Copyright @copyright{} 1989-2003 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are @@ -65,7 +65,7 @@ Software Foundation instead of in the original English. @page @vskip 0pt plus 1filll -Copyright @copyright{} 1989-2002 Free Software Foundation, Inc. +Copyright @copyright{} 1989-2003 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of @@ -365,10 +365,12 @@ act like command-line options, as well as for providing a user-supplied If the @samp{-t} option (or, equivalently, the @samp{%struct-type} declaration) @emph{is} enabled, you @emph{must} provide a C @code{struct} as the last component in the declaration section from the input file. The first -field in this struct must be a @code{char *} or @code{const char *} -identifier called @samp{name}, although it is possible to modify this -field's name with the @samp{-K} option (or, equivalently, the -@samp{%define slot-name}) described below. +field in this struct must be of type @code{char *} or @code{const char *} +if the @samp{-P} option is not given, or of type @code{int} if the option +@samp{-P} (or, equivalently, the @samp{%pic} declaration) is enabled. +This first field must be called @samp{name}, although it is possible to modify +its name with the @samp{-K} option (or, equivalently, the +@samp{%define slot-name} declaration) described below. Here is a simple example, using months of the year and their attributes as input: @@ -544,6 +546,34 @@ Generate the static table of keywords as a static global variable, rather than hiding it inside of the lookup function (which is the default behavior). +@item %pic +@cindex @samp{%pic} +Optimize the generated table for inclusion in shared libraries. This +reduces the startup time of programs using a shared library containing +the generated code. If the @samp{%struct-type} declaration (or, +equivalently, the option @samp{-t}) is also given, the first field of the +user-defined struct must be of type @samp{int}, not @samp{char *}, because +it will contain offsets into the string pool instead of actual strings. +To convert such an offset to a string, you can use the expression +@samp{stringpool + @var{o}}, where @var{o} is the offset. The string pool +name can be changed through the @samp{%define string-pool-name} declaration. + +@item %define string-pool-name @var{name} +@cindex @samp{%define string-pool-name} +Allows you to specify the name of the generated string pool created by +the declaration @samp{%pic} (or, equivalently, the option @samp{-P}). +The default name is @samp{stringpool}. This declaration permits the use of +two hash tables in the same file, with @samp{%pic} and even when the +@samp{%global-table} declaration (or, equivalently, the option @samp{-G}) +is given. + +@item %null-strings +@cindex @samp{%null-strings} +Use NULL strings instead of empty strings for empty keyword table entries. +This reduces the startup time of programs using a shared library containing +the generated code (but not as much as the declaration @samp{%pic}), at the +expense of one more test-and-branch instruction at run time. + @item %define word-array-name @var{name} @cindex @samp{%define word-array-name} Allows you to specify the name for the generated array containing the @@ -952,8 +982,27 @@ default behavior). @itemx --pic Optimize the generated table for inclusion in shared libraries. This reduces the startup time of programs using a shared library containing -the generated code, at the expense of one more test-and-branch instruction -at run time. +the generated code. If the option @samp{-t} (or, equivalently, the +@samp{%struct-type} declaration) is also given, the first field of the +user-defined struct must be of type @samp{int}, not @samp{char *}, because +it will contain offsets into the string pool instead of actual strings. +To convert such an offset to a string, you can use the expression +@samp{stringpool + @var{o}}, where @var{o} is the offset. The string pool +name can be changed through the option @samp{--string-pool-name}. + +@item -Q @var{string-pool-name} +@itemx --string-pool-name=@var{string-pool-name} +Allows you to specify the name of the generated string pool created by +option @samp{-P}. The default name is @samp{stringpool}. This option +permits the use of two hash tables in the same file, with @samp{-P} and +even when the option @samp{-G} (or, equivalently, the @samp{%global-table} +declaration) is given. + +@item --null-strings +Use NULL strings instead of empty strings for empty keyword table entries. +This reduces the startup time of programs using a shared library containing +the generated code (but not as much as option @samp{-P}), at the expense +of one more test-and-branch instruction at run time. @item -W @var{hash-table-array-name} @itemx --word-array-name=@var{hash-table-array-name} diff --git a/src/input.cc b/src/input.cc index 933911e..4a968ae 100644 --- a/src/input.cc +++ b/src/input.cc @@ -1,5 +1,5 @@ /* Input routines. - Copyright (C) 1989-1998, 2002 Free Software Foundation, Inc. + 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>. @@ -529,6 +529,19 @@ Input::read_input () 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); diff --git a/src/options.cc b/src/options.cc index 8880858..02258a0 100644 --- a/src/options.cc +++ b/src/options.cc @@ -1,5 +1,5 @@ /* Handles parsing the Options provided to the user. - Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc. + 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>. @@ -58,6 +58,9 @@ static const char *const DEFAULT_HASH_NAME = "hash"; /* Default name for generated hash table array. */ static const char *const DEFAULT_WORDLIST_NAME = "wordlist"; +/* 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 = ","; @@ -166,6 +169,13 @@ Options::long_usage (FILE * stream) " 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"); @@ -448,6 +458,7 @@ Options::Options () _class_name (DEFAULT_CLASS_NAME), _hash_name (DEFAULT_HASH_NAME), _wordlist_name (DEFAULT_WORDLIST_NAME), + _stringpool_name (DEFAULT_STRINGPOOL_NAME), _delimiters (DEFAULT_DELIMITERS), _key_positions () { @@ -473,6 +484,7 @@ Options::~Options () "\nENUM is........: %s" "\nINCLUDE is.....: %s" "\nGLOBAL is......: %s" + "\nNULLSTRINGS is.: %s" "\nSHAREDLIB is...: %s" "\nSWITCH is......: %s" "\nNOTYPE is......: %s" @@ -483,6 +495,7 @@ Options::~Options () "\nlookup function name = %s" "\nhash function name = %s" "\nword list name = %s" + "\nstring pool name = %s" "\nslot name = %s" "\ninitializer suffix = %s" "\nasso_values iterations = %d" @@ -504,6 +517,7 @@ Options::~Options () _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", @@ -511,9 +525,10 @@ Options::~Options () _option_word & NOLENGTH ? "enabled" : "disabled", _option_word & RANDOM ? "enabled" : "disabled", _option_word & DEBUG ? "enabled" : "disabled", - _function_name, _hash_name, _wordlist_name, _slot_name, - _initializer_suffix, _asso_iterations, _jump, _size_multiple, - _initial_asso_value, _delimiters, _total_switches); + _function_name, _hash_name, _wordlist_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 @@ -610,6 +625,14 @@ Options::set_wordlist_name (const char *name) _wordlist_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) @@ -656,6 +679,8 @@ static const struct option long_options[] = { "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' }, @@ -675,7 +700,7 @@ Options::parse_options (int argc, char *argv[]) while ((option_char = getopt_long (_argument_count, _argument_vector, - "acCdDe:Ef:F:gGhH:i:Ij:k:K:lL:m:nN:oOpPrs:S:tTvW:Z:7", + "acCdDe:Ef:F:gGhH:i:Ij:k:K:lL:m:nN:oOpPQ:rs:S:tTvW:Z:7", long_options, NULL)) != -1) { @@ -872,6 +897,11 @@ Options::parse_options (int argc, char *argv[]) _option_word |= SHAREDLIB; break; } + case 'Q': /* Sets the name for the string pool. */ + { + _stringpool_name = /*getopt*/optarg; + break; + } case 'r': /* Utilize randomness to initialize the associated values table. */ { _option_word |= RANDOM; @@ -978,6 +1008,11 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ _option_word |= UPPERLOWER; break; } + case CHAR_MAX + 3: /* Use NULL instead of "". */ + { + _option_word |= NULLSTRINGS; + break; + } default: short_usage (stderr); exit (1); diff --git a/src/options.h b/src/options.h index 0bde55c..d153436 100644 --- a/src/options.h +++ b/src/options.h @@ -2,7 +2,7 @@ /* Handles parsing the Options provided to the user. - Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc. + 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>. @@ -81,34 +81,37 @@ enum Option_Type /* 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 << 13, + SHAREDLIB = 1 << 14, /* Generate switch output to save space. */ - SWITCH = 1 << 14, + SWITCH = 1 << 15, /* Don't include user-defined type definition in output -- it's already defined elsewhere. */ - NOTYPE = 1 << 15, + NOTYPE = 1 << 16, /* --- Algorithm employed by gperf --- */ /* Use the given key positions. */ - POSITIONS = 1 << 16, + POSITIONS = 1 << 17, /* Handle duplicate hash values for keywords. */ - DUP = 1 << 17, + DUP = 1 << 18, /* Don't include keyword length in hash computations. */ - NOLENGTH = 1 << 18, + NOLENGTH = 1 << 19, /* Randomly initialize the associated values table. */ - RANDOM = 1 << 19, + RANDOM = 1 << 20, /* --- Informative output --- */ /* Enable debugging (prints diagnostics to stderr). */ - DEBUG = 1 << 20 + DEBUG = 1 << 21 }; /* Class manager for gperf program Options. */ @@ -189,6 +192,11 @@ public: /* Sets the hash table array name, if not already set. */ void set_wordlist_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. */ @@ -255,6 +263,9 @@ private: /* Name used for hash table array. */ const char * _wordlist_name; + /* Name used for the string pool. */ + const char * _stringpool_name; + /* Separates keywords from other attributes. */ const char * _delimiters; diff --git a/src/options.icc b/src/options.icc index f519133..1d21cc5 100644 --- a/src/options.icc +++ b/src/options.icc @@ -1,6 +1,6 @@ /* Inline Functions for options.{h,cc}. - Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc. + 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>. @@ -128,6 +128,13 @@ Options::get_wordlist_name () const return _wordlist_name; } +/* Returns the string pool name. */ +INLINE const char * +Options::get_stringpool_name () const +{ + return _stringpool_name; +} + /* Returns the string used to delimit keywords from other attributes. */ INLINE const char * Options::get_delimiters () const diff --git a/src/output.cc b/src/output.cc index 40bfb44..484d583 100644 --- a/src/output.cc +++ b/src/output.cc @@ -832,16 +832,18 @@ Output::output_keylength_table () const 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] && !temp->first()->_duplicate_link) + if (option[SWITCH] && !option[TYPE] && !keyword->_duplicate_link) continue; - if (index < temp->first()->_hash_value && !option[SWITCH] && !option[DUP]) + if (index < keyword->_hash_value && !option[SWITCH] && !option[DUP]) { /* Some blank entries. */ - for ( ; index < temp->first()->_hash_value; index++) + for ( ; index < keyword->_hash_value; index++) { if (index > 0) printf (","); @@ -855,12 +857,12 @@ Output::output_keylength_table () const printf (","); if ((column++ % columns) == 0) printf("\n%s ", indent); - printf ("%3d", temp->first()->_allchars_length); + printf ("%3d", keyword->_allchars_length); index++; /* Deal with duplicates specially. */ - if (temp->first()->_duplicate_link) // implies option[DUP] - for (KeywordExt *links = temp->first()->_duplicate_link; links; links = links->_duplicate_link) + if (keyword->_duplicate_link) // implies option[DUP] + for (KeywordExt *links = keyword->_duplicate_link; links; links = links->_duplicate_link) { printf (","); if ((column++ % columns) == 0) @@ -877,8 +879,111 @@ Output::output_keylength_table () const /* ------------------------------------------------------------------------- */ +/* 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, const char *indent) +output_keyword_entry (KeywordExt *temp, int stringpool_index, const char *indent) { if (option[TYPE] && option.get_input_file_name ()) printf ("#line %u \"%s\"\n", @@ -886,7 +991,12 @@ output_keyword_entry (KeywordExt *temp, const char *indent) printf ("%s ", indent); if (option[TYPE]) printf ("{"); - output_string (temp->_allchars, temp->_allchars_length); + 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) @@ -904,14 +1014,14 @@ output_keyword_blank_entries (int count, const char *indent) int columns; if (option[TYPE]) { - columns = 58 / (4 + (option[SHAREDLIB] ? 8 : 2) + columns = 58 / (4 + (option[SHAREDLIB] ? 2 : option[NULLSTRINGS] ? 8 : 2) + strlen (option.get_initializer_suffix())); if (columns == 0) columns = 1; } else { - columns = (option[SHAREDLIB] ? 4 : 9); + columns = (option[SHAREDLIB] ? 9 : option[NULLSTRINGS] ? 4 : 9); } int column = 0; for (int i = 0; i < count; i++) @@ -930,9 +1040,14 @@ output_keyword_blank_entries (int count, const char *indent) if (option[TYPE]) printf ("{"); if (option[SHAREDLIB]) - printf ("(char*)0"); + printf ("-1"); else - printf ("\"\""); + { + if (option[NULLSTRINGS]) + printf ("(char*)0"); + else + printf ("\"\""); + } if (option[TYPE]) printf ("%s}", option.get_initializer_suffix()); column++; @@ -945,12 +1060,12 @@ void Output::output_keyword_table () const { const char *indent = option[GLOBAL] ? "" : " "; - int index; + int index; KeywordExt_List *temp; printf ("%sstatic ", indent); - output_const_type (const_readonly_array, _struct_tag); + output_const_type (const_readonly_array, _wordlist_eltype); printf ("%s[] =\n" "%s {\n", option.get_wordlist_name (), @@ -960,31 +1075,42 @@ Output::output_keyword_table () const for (temp = _head, index = 0; temp; temp = temp->rest()) { - if (option[SWITCH] && !option[TYPE] && !temp->first()->_duplicate_link) + 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 < temp->first()->_hash_value && !option[SWITCH] && !option[DUP]) + if (index < keyword->_hash_value && !option[SWITCH] && !option[DUP]) { /* Some blank entries. */ - output_keyword_blank_entries (temp->first()->_hash_value - index, indent); + output_keyword_blank_entries (keyword->_hash_value - index, indent); printf (",\n"); - index = temp->first()->_hash_value; + index = keyword->_hash_value; } - temp->first()->_final_index = index; + keyword->_final_index = index; - output_keyword_entry (temp->first(), indent); + output_keyword_entry (keyword, index, indent); /* Deal with duplicates specially. */ - if (temp->first()->_duplicate_link) // implies option[DUP] - for (KeywordExt *links = temp->first()->_duplicate_link; links; links = links->_duplicate_link) + if (keyword->_duplicate_link) // implies option[DUP] + for (KeywordExt *links = keyword->_duplicate_link; links; links = links->_duplicate_link) { links->_final_index = ++index; printf (",\n"); - output_keyword_entry (links, indent); + 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++; @@ -1147,6 +1273,22 @@ Output::output_lookup_array () const /* ------------------------------------------------------------------------- */ +/* 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 @@ -1340,10 +1482,10 @@ Output::output_lookup_function_body (const Output_Compare& comparison) const printf (" register %s%s *lengthptr;\n", const_always, smallest_integral_type (_max_key_len)); printf (" register "); - output_const_type (const_readonly_array, _struct_tag); + output_const_type (const_readonly_array, _wordlist_eltype); printf ("*wordptr;\n"); printf (" register "); - output_const_type (const_readonly_array, _struct_tag); + output_const_type (const_readonly_array, _wordlist_eltype); printf ("*wordendptr;\n"); } if (option[TYPE]) @@ -1358,14 +1500,14 @@ Output::output_lookup_function_body (const Output_Compare& comparison) const 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 ("%*s return 0;\n" - "%*smulticompare:\n" + printf ("%*smulticompare:\n" "%*s while (wordptr < wordendptr)\n" "%*s {\n", - indent, "", indent, "", indent, "", indent, ""); + indent, "", indent, "", indent, ""); if (option[LENTABLE]) { printf ("%*s if (len == *lengthptr)\n" @@ -1379,6 +1521,9 @@ Output::output_lookup_function_body (const Output_Compare& comparison) const 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, ""); @@ -1397,17 +1542,21 @@ Output::output_lookup_function_body (const Output_Compare& comparison) const printf ("%*s lengthptr++;\n", indent, ""); printf ("%*s wordptr++;\n" - "%*s }\n", - indent, "", indent, ""); + "%*s }\n" + "%*s return 0;\n", + indent, "", indent, "", indent, ""); } - printf (" return 0;\n" - " compare:\n"); + printf (" compare:\n"); if (option[TYPE]) { printf (" {\n" - " register %schar *s = resword->%s;\n\n" - " if (", + " 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" @@ -1446,6 +1595,9 @@ Output::output_lookup_function_body (const Output_Compare& comparison) const 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, ""); @@ -1476,12 +1628,12 @@ Output::output_lookup_function_body (const Output_Compare& comparison) const indent, "", const_always, smallest_integral_type (_max_key_len)); printf ("%*s register ", indent, ""); - output_const_type (const_readonly_array, _struct_tag); + 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, _struct_tag); + output_const_type (const_readonly_array, _wordlist_eltype); printf ("*wordendptr = wordptr + -lookup[offset + 1];\n\n"); printf ("%*s while (wordptr < wordendptr)\n" "%*s {\n", @@ -1499,6 +1651,9 @@ Output::output_lookup_function_body (const Output_Compare& comparison) const 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, ""); @@ -1534,18 +1689,55 @@ Output::output_lookup_function_body (const Output_Compare& comparison) const 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_slot_name ()); + 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]) + if (!option[SHAREDLIB] && option[NULLSTRINGS]) printf ("s && "); comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s")); printf (")\n" @@ -1555,8 +1747,14 @@ Output::output_lookup_function_body (const Output_Compare& comparison) const printf ("&%s[key]", option.get_wordlist_name ()); else printf ("s"); - printf (";\n" - "%*s}\n", + printf (";\n"); + if (option[SHAREDLIB] && !option[LENTABLE]) + { + indent -= 4; + printf ("%*s }\n", + indent, ""); + } + printf ("%*s}\n", indent, ""); } } @@ -1601,6 +1799,8 @@ Output::output_lookup_function () const output_constants (style); } + if (option[SHAREDLIB] && !(option[GLOBAL] || option[TYPE])) + output_lookup_pools (); if (!option[GLOBAL]) output_lookup_tables (); @@ -1646,6 +1846,8 @@ Output::output () _struct_tag = (const_always[0] ? "const char *" : "char *"); } + _wordlist_eltype = (option[SHAREDLIB] && !option[TYPE] ? "int" : _struct_tag); + printf ("/* "); if (option[KRC]) printf ("KR-C"); @@ -1726,6 +1928,8 @@ Output::output () output_hash_function (); + if (option[SHAREDLIB] && (option[GLOBAL] || option[TYPE])) + output_lookup_pools (); if (option[GLOBAL]) output_lookup_tables (); diff --git a/src/output.h b/src/output.h index 7631110..3650f9e 100644 --- a/src/output.h +++ b/src/output.h @@ -2,7 +2,7 @@ /* Output routines. - Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc. + 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>. @@ -82,6 +82,10 @@ private: 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; @@ -89,6 +93,9 @@ private: 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; @@ -108,6 +115,8 @@ private: 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; diff --git a/tests/Makefile.in b/tests/Makefile.in index 5e9eacc..2cd4f65 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -200,21 +200,31 @@ check-lang-syntax : force $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -S 10 -D -l $(VALIDATE) KR-C,C,ANSI-C,C++ -k2 $(srcdir)/jstest1.gperf -S 10 -D -l $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -S 1000 - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -p - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -p -C - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -p -l - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -p -D - $(VALIDATE) KR-C,C,ANSI-C,C++ -k2 $(srcdir)/jstest1.gperf -p -D - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -p -D -l - $(VALIDATE) KR-C,C,ANSI-C,C++ -k2 $(srcdir)/jstest1.gperf -p -D -l - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -p -S 10 - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -p -S 10 -C - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -p -S 10 -l - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -p -S 10 -D - $(VALIDATE) KR-C,C,ANSI-C,C++ -k2 $(srcdir)/jstest1.gperf -p -S 10 -D - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -p -S 10 -D -l - $(VALIDATE) KR-C,C,ANSI-C,C++ -k2 $(srcdir)/jstest1.gperf -p -S 10 -D -l - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -p -S 1000 + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -c + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -C + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -E + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -G + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -G -C + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -G -E + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -D + $(VALIDATE) KR-C,C,ANSI-C,C++ -k2 $(srcdir)/jstest1.gperf -P -D + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -D -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k2 $(srcdir)/jstest1.gperf -P -D -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -S 10 + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -S 10 -c + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -S 10 -C + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -S 10 -E + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -S 10 -G + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -S 10 -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -S 10 -D + $(VALIDATE) KR-C,C,ANSI-C,C++ -k2 $(srcdir)/jstest1.gperf -P -S 10 -D + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -S 10 -D -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k2 $(srcdir)/jstest1.gperf -P -S 10 -D -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -S 1000 + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -Q auxstrings + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -P -Q auxstrings -S 10 $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -K key_name $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -H hash_function_name $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest1.gperf -W word_list_name @@ -222,66 +232,93 @@ check-lang-syntax : force $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 tmp-jstest1.gperf -N lookup_function_name sed -e 's,Perfect_Hash,class_name,g' < $(srcdir)/jstest1.gperf > tmp-jstest1.gperf && \ $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 tmp-jstest1.gperf -Z class_name - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -c - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -C - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -E - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -G - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -G -C - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -G -E - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -l - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -D - $(VALIDATE) KR-C,C,ANSI-C,C++ -k2 $(srcdir)/jstest2.gperf -t -p -D - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -D -l - $(VALIDATE) KR-C,C,ANSI-C,C++ -k2 $(srcdir)/jstest2.gperf -t -p -D -l - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -S 10 - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -S 10 -c - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -S 10 -C - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -S 10 -E - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -S 10 -G - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -S 10 -l - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -S 10 -D - $(VALIDATE) KR-C,C,ANSI-C,C++ -k2 $(srcdir)/jstest2.gperf -t -p -S 10 -D - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -S 10 -D -l - $(VALIDATE) KR-C,C,ANSI-C,C++ -k2 $(srcdir)/jstest2.gperf -t -p -S 10 -D -l - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -S 1000 + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -c + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -C + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -E + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -G + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -G -C + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -G -E + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -D + $(VALIDATE) KR-C,C,ANSI-C,C++ -k2 $(srcdir)/jstest2.gperf -t -D + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -D -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k2 $(srcdir)/jstest2.gperf -t -D -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -S 10 + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -S 10 -c + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -S 10 -C + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -S 10 -E + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -S 10 -G + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -S 10 -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -S 10 -D + $(VALIDATE) KR-C,C,ANSI-C,C++ -k2 $(srcdir)/jstest2.gperf -t -S 10 -D + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -S 10 -D -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k2 $(srcdir)/jstest2.gperf -t -S 10 -D -l + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -S 1000 sed -e 's,name,key_name,g' < $(srcdir)/jstest2.gperf > tmp-jstest2.gperf && \ - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 tmp-jstest2.gperf -t -p -K key_name - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -p -H hash_function_name + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 tmp-jstest2.gperf -t -K key_name + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 $(srcdir)/jstest2.gperf -t -H hash_function_name sed -e 's,in_word_set,lookup_function_name,g' < $(srcdir)/jstest2.gperf > tmp-jstest2.gperf && \ - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 tmp-jstest2.gperf -t -p -N lookup_function_name + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 tmp-jstest2.gperf -t -N lookup_function_name sed -e 's,Perfect_Hash,class_name,g' < $(srcdir)/jstest2.gperf > tmp-jstest2.gperf && \ - $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 tmp-jstest2.gperf -t -p -Z class_name - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -c - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -C - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -E - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -G - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -G -C - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -G -E - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -l - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -D - $(VALIDATE) C,ANSI-C,C++ -k2 $(srcdir)/jstest3.gperf -t -p -D - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -D -l - $(VALIDATE) C,ANSI-C,C++ -k2 $(srcdir)/jstest3.gperf -t -p -D -l - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -S 10 - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -S 10 -c - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -S 10 -C - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -S 10 -E - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -S 10 -G - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -S 10 -l - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -S 10 -D - $(VALIDATE) C,ANSI-C,C++ -k2 $(srcdir)/jstest3.gperf -t -p -S 10 -D - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -S 10 -D -l - $(VALIDATE) C,ANSI-C,C++ -k2 $(srcdir)/jstest3.gperf -t -p -S 10 -D -l - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -S 1000 + $(VALIDATE) KR-C,C,ANSI-C,C++ -k1,2 tmp-jstest2.gperf -t -Z class_name + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -c + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -C + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -E + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -G + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -G -C + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -G -E + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -l + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -D + $(VALIDATE) C,ANSI-C,C++ -k2 $(srcdir)/jstest3.gperf -t -D + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -D -l + $(VALIDATE) C,ANSI-C,C++ -k2 $(srcdir)/jstest3.gperf -t -D -l + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -S 10 + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -S 10 -c + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -S 10 -C + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -S 10 -E + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -S 10 -G + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -S 10 -l + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -S 10 -D + $(VALIDATE) C,ANSI-C,C++ -k2 $(srcdir)/jstest3.gperf -t -S 10 -D + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -S 10 -D -l + $(VALIDATE) C,ANSI-C,C++ -k2 $(srcdir)/jstest3.gperf -t -S 10 -D -l + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -S 1000 sed -e 's,name,key_name,g' < $(srcdir)/jstest3.gperf > tmp-jstest3.gperf && \ - $(VALIDATE) C,ANSI-C,C++ -k1,2 tmp-jstest3.gperf -t -p -K key_name - $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -p -H hash_function_name + $(VALIDATE) C,ANSI-C,C++ -k1,2 tmp-jstest3.gperf -t -K key_name + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest3.gperf -t -H hash_function_name sed -e 's,in_word_set,lookup_function_name,g' < $(srcdir)/jstest3.gperf > tmp-jstest3.gperf && \ - $(VALIDATE) C,ANSI-C,C++ -k1,2 tmp-jstest3.gperf -t -p -N lookup_function_name + $(VALIDATE) C,ANSI-C,C++ -k1,2 tmp-jstest3.gperf -t -N lookup_function_name sed -e 's,Perfect_Hash,class_name,g' < $(srcdir)/jstest3.gperf > tmp-jstest3.gperf && \ - $(VALIDATE) C,ANSI-C,C++ -k1,2 tmp-jstest3.gperf -t -p -Z class_name + $(VALIDATE) C,ANSI-C,C++ -k1,2 tmp-jstest3.gperf -t -Z class_name + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P -c + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P -C + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P -E + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P -G + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P -G -C + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P -G -E + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P -l + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P -D + $(VALIDATE) C,ANSI-C,C++ -k2 $(srcdir)/jstest4.gperf -t -P -D + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P -D -l + $(VALIDATE) C,ANSI-C,C++ -k2 $(srcdir)/jstest4.gperf -t -P -D -l + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P -S 10 + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P -S 10 -c + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P -S 10 -C + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P -S 10 -E + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P -S 10 -G + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P -S 10 -l + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P -S 10 -D + $(VALIDATE) C,ANSI-C,C++ -k2 $(srcdir)/jstest4.gperf -t -P -S 10 -D + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P -S 10 -D -l + $(VALIDATE) C,ANSI-C,C++ -k2 $(srcdir)/jstest4.gperf -t -P -S 10 -D -l + $(VALIDATE) C,ANSI-C,C++ -k1,2 $(srcdir)/jstest4.gperf -t -P -S 1000 + sed -e 's,stringpool,auxstrings,g' < $(srcdir)/jstest4.gperf > tmp-jstest4.gperf && \ + $(VALIDATE) C,ANSI-C,C++ -k1,2 tmp-jstest4.gperf -t -P -Q auxstrings + sed -e 's,stringpool,auxstrings,g' < $(srcdir)/jstest4.gperf > tmp-jstest4.gperf && \ + $(VALIDATE) C,ANSI-C,C++ -k1,2 tmp-jstest4.gperf -t -P -Q auxstrings -S 10 mostlyclean : clean diff --git a/tests/jstest4.gperf b/tests/jstest4.gperf new file mode 100644 index 0000000..b02617c --- /dev/null +++ b/tests/jstest4.gperf @@ -0,0 +1,147 @@ +struct js_keyword { + int name; + int token; +} +%% +abstract, 1 +boolean, 2 +break, 3 +byte, 4 +case, 5 +catch, 6 +char, 7 +class, 8 +const, 9 +continue, 10 +default, 11 +do, 12 +double, 13 +else, 14 +extends, 15 +false, 16 +final, 17 +finally, 18 +float, 19 +for, 20 +function, 21 +goto, 22 +if, 23 +implements, 24 +import, 25 +in, 26 +instanceof, 27 +int, 28 +interface, 29 +long, 30 +native, 31 +new, 32 +null, 33 +package, 34 +private, 35 +protected, 36 +public, 37 +return, 38 +short, 39 +static, 40 +super, 41 +switch, 42 +synchronized, 43 +this, 44 +throw, 45 +throws, 46 +transient, 47 +true, 48 +try, 49 +var, 50 +void, 51 +while, 52 +with, 53 +%% +#include <stdlib.h> +#include <string.h> +#if defined(__STDC__) || defined(__cplusplus) +#define CONST const +#else +#define CONST +#endif +static CONST char* testdata[] = { + "bogus", + "abstract", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "const", + "continue", + "default", + "do", + "double", + "else", + "extends", + "false", + "final", + "finally", + "float", + "for", + "function", + "goto", + "if", + "implements", + "import", + "in", + "instanceof", + "int", + "interface", + "long", + "native", + "new", + "null", + "package", + "private", + "protected", + "public", + "return", + "short", + "static", + "super", + "switch", + "synchronized", + "this", + "throw", + "throws", + "transient", + "true", + "try", + "var", + "void", + "while", + "with" +}; +int main () +{ + int i; + for (i = 0; i < sizeof(testdata)/sizeof(testdata[0]); i++) + { +#ifdef CPLUSPLUS_TEST + CONST struct js_keyword * resword = Perfect_Hash::in_word_set(testdata[i],strlen(testdata[i])); +#else + CONST struct js_keyword * resword = in_word_set(testdata[i],strlen(testdata[i])); +#endif + if (i > 0) + { + if (!resword) + exit (1); + if (strcmp(testdata[i],stringpool+resword->name)) + exit (1); + } + else + { + if (resword) + exit (1); + } + } + return 0; +} diff --git a/tests/test-6.exp b/tests/test-6.exp index cabbe9c..d0e3f21 100644 --- a/tests/test-6.exp +++ b/tests/test-6.exp @@ -63,6 +63,11 @@ Details in the output code: -P, --pic Optimize the generated table for inclusion in shared libraries. This reduces the startup time of programs using a shared library containing the generated code. + -Q, --string-pool-name=NAME + Specify name of string pool generated by option --pic. + Default name is 'stringpool'. + --null-strings Use NULL strings instead of empty strings for empty + keyword table entries. -W, --word-array-name=NAME Specify name of word list array. Default name is 'wordlist'. |