diff options
author | Baptiste Daroussin <bapt@FreeBSD.org> | 2011-12-02 22:46:53 +0000 |
---|---|---|
committer | Baptiste Daroussin <bapt@FreeBSD.org> | 2011-12-02 22:46:53 +0000 |
commit | 29b4be759a1cb9071f684712a745e4b92bd366d0 (patch) | |
tree | 420c69d9e3125fa5ccbd4216e27d200b25f01bed /src/options.cc | |
parent | f823497bd9d420a2cf83fa56f5090d4227ba73f5 (diff) |
Notes
Diffstat (limited to 'src/options.cc')
-rw-r--r-- | src/options.cc | 1118 |
1 files changed, 732 insertions, 386 deletions
diff --git a/src/options.cc b/src/options.cc index d15e21cee8ce..a86432ea65ed 100644 --- a/src/options.cc +++ b/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,70 +213,70 @@ 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); @@ -242,6 +286,20 @@ Options::print_options (void) 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 */ |