158551Skris/* Handles parsing the Options provided to the user. 2228060Sbapt Copyright (C) 1989-1998, 2000, 2002-2004, 2006-2007 Free Software Foundation, Inc. 3228060Sbapt Written by Douglas C. Schmidt <schmidt@ics.uci.edu> 4228060Sbapt and Bruno Haible <bruno@clisp.org>. 558551Skris 6228060Sbapt This file is part of GNU GPERF. 758551Skris 8228060Sbapt GNU GPERF is free software; you can redistribute it and/or modify 9228060Sbapt it under the terms of the GNU General Public License as published by 10228060Sbapt the Free Software Foundation; either version 2, or (at your option) 11228060Sbapt any later version. 1258551Skris 13228060Sbapt GNU GPERF is distributed in the hope that it will be useful, 14228060Sbapt but WITHOUT ANY WARRANTY; without even the implied warranty of 15228060Sbapt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16228060Sbapt GNU General Public License for more details. 1758551Skris 18228060Sbapt You should have received a copy of the GNU General Public License 19228060Sbapt along with this program; see the file COPYING. 20228060Sbapt If not, write to the Free Software Foundation, Inc., 21228060Sbapt 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 2258551Skris 23228060Sbapt/* Specification. */ 24228060Sbapt#include "options.h" 25228060Sbapt 2658551Skris#include <stdio.h> 2758551Skris#include <stdlib.h> /* declares atoi(), abs(), exit() */ 2858551Skris#include <string.h> /* declares strcmp() */ 29228060Sbapt#include <ctype.h> /* declares isdigit() */ 30228060Sbapt#include <limits.h> /* defines CHAR_MAX */ 3158551Skris#include "getopt.h" 3258551Skris#include "version.h" 3358551Skris 34228060Sbapt/* Global option coordinator for the entire program. */ 3558551SkrisOptions option; 3658551Skris 37228060Sbapt/* Records the program name. */ 3858551Skrisconst char *program_name; 3958551Skris 40228060Sbapt/* Size to jump on a collision. */ 4158551Skrisstatic const int DEFAULT_JUMP_VALUE = 5; 4258551Skris 43228060Sbapt/* Default name for generated lookup function. */ 44228060Sbaptstatic const char *const DEFAULT_FUNCTION_NAME = "in_word_set"; 4558551Skris 46228060Sbapt/* Default name for the key component. */ 47228060Sbaptstatic const char *const DEFAULT_SLOT_NAME = "name"; 4858551Skris 49228060Sbapt/* Default struct initializer suffix. */ 5067064Sobrienstatic const char *const DEFAULT_INITIALIZER_SUFFIX = ""; 5167064Sobrien 52228060Sbapt/* Default name for the generated class. */ 5358551Skrisstatic const char *const DEFAULT_CLASS_NAME = "Perfect_Hash"; 5458551Skris 55228060Sbapt/* Default name for generated hash function. */ 5658551Skrisstatic const char *const DEFAULT_HASH_NAME = "hash"; 5758551Skris 58228060Sbapt/* Default name for generated hash table array. */ 5958551Skrisstatic const char *const DEFAULT_WORDLIST_NAME = "wordlist"; 6058551Skris 61228060Sbapt/* Default name for generated length table array. */ 62228060Sbaptstatic const char *const DEFAULT_LENGTHTABLE_NAME = "lengthtable"; 6358551Skris 64228060Sbapt/* Default name for string pool. */ 65228060Sbaptstatic const char *const DEFAULT_STRINGPOOL_NAME = "stringpool"; 6658551Skris 67228060Sbapt/* Default delimiters that separate keywords from their attributes. */ 68228060Sbaptstatic const char *const DEFAULT_DELIMITERS = ","; 6958551Skris 70228060Sbapt/* Prints program usage to given stream. */ 71228060Sbapt 7258551Skrisvoid 73228060SbaptOptions::short_usage (FILE * stream) 7458551Skris{ 75228060Sbapt fprintf (stream, 76228060Sbapt "Try '%s --help' for more information.\n", program_name); 7758551Skris} 7858551Skris 7958551Skrisvoid 80228060SbaptOptions::long_usage (FILE * stream) 8158551Skris{ 82228060Sbapt fprintf (stream, 83228060Sbapt "GNU 'gperf' generates perfect hash functions.\n"); 84228060Sbapt fprintf (stream, "\n"); 85228060Sbapt fprintf (stream, 86228060Sbapt "Usage: %s [OPTION]... [INPUT-FILE]\n", 87228060Sbapt program_name); 88228060Sbapt fprintf (stream, "\n"); 89228060Sbapt fprintf (stream, 9058551Skris "If a long option shows an argument as mandatory, then it is mandatory\n" 91228060Sbapt "for the equivalent short option also.\n"); 92228060Sbapt fprintf (stream, "\n"); 93228060Sbapt fprintf (stream, 94228060Sbapt "Output file location:\n"); 95228060Sbapt fprintf (stream, 96228060Sbapt " --output-file=FILE Write output to specified file.\n"); 97228060Sbapt fprintf (stream, 98228060Sbapt "The results are written to standard output if no output file is specified\n" 99228060Sbapt "or if it is -.\n"); 100228060Sbapt fprintf (stream, "\n"); 101228060Sbapt fprintf (stream, 102228060Sbapt "Input file interpretation:\n"); 103228060Sbapt fprintf (stream, 10458551Skris " -e, --delimiters=DELIMITER-LIST\n" 10558551Skris " Allow user to provide a string containing delimiters\n" 10658551Skris " used to separate keywords from their attributes.\n" 107228060Sbapt " Default is \",\".\n"); 108228060Sbapt fprintf (stream, 10958551Skris " -t, --struct-type Allows the user to include a structured type\n" 11058551Skris " declaration for generated code. Any text before %%%%\n" 11158551Skris " is considered part of the type declaration. Key\n" 11258551Skris " words and additional fields may follow this, one\n" 113228060Sbapt " group of fields per line.\n"); 114228060Sbapt fprintf (stream, 115228060Sbapt " --ignore-case Consider upper and lower case ASCII characters as\n" 116228060Sbapt " equivalent. Note that locale dependent case mappings\n" 117228060Sbapt " are ignored.\n"); 118228060Sbapt fprintf (stream, "\n"); 119228060Sbapt fprintf (stream, 120228060Sbapt "Language for the output code:\n"); 121228060Sbapt fprintf (stream, 12258551Skris " -L, --language=LANGUAGE-NAME\n" 12358551Skris " Generates code in the specified language. Languages\n" 12458551Skris " handled are currently C++, ANSI-C, C, and KR-C. The\n" 125228060Sbapt " default is C.\n"); 126228060Sbapt fprintf (stream, "\n"); 127228060Sbapt fprintf (stream, 128228060Sbapt "Details in the output code:\n"); 129228060Sbapt fprintf (stream, 13058551Skris " -K, --slot-name=NAME Select name of the keyword component in the keyword\n" 131228060Sbapt " structure.\n"); 132228060Sbapt fprintf (stream, 13367064Sobrien " -F, --initializer-suffix=INITIALIZERS\n" 13467064Sobrien " Initializers for additional components in the keyword\n" 135228060Sbapt " structure.\n"); 136228060Sbapt fprintf (stream, 137228060Sbapt " -H, --hash-function-name=NAME\n" 13858551Skris " Specify name of generated hash function. Default is\n" 139228060Sbapt " 'hash'.\n"); 140228060Sbapt fprintf (stream, 141228060Sbapt " -N, --lookup-function-name=NAME\n" 14258551Skris " Specify name of generated lookup function. Default\n" 143228060Sbapt " name is 'in_word_set'.\n"); 144228060Sbapt fprintf (stream, 14558551Skris " -Z, --class-name=NAME Specify name of generated C++ class. Default name is\n" 146228060Sbapt " 'Perfect_Hash'.\n"); 147228060Sbapt fprintf (stream, 148228060Sbapt " -7, --seven-bit Assume 7-bit characters.\n"); 149228060Sbapt fprintf (stream, 150228060Sbapt " -l, --compare-lengths Compare key lengths before trying a string\n" 151228060Sbapt " comparison. This is necessary if the keywords\n" 152228060Sbapt " contain NUL bytes. It also helps cut down on the\n" 153228060Sbapt " number of string comparisons made during the lookup.\n"); 154228060Sbapt fprintf (stream, 15558551Skris " -c, --compare-strncmp Generate comparison code using strncmp rather than\n" 156228060Sbapt " strcmp.\n"); 157228060Sbapt fprintf (stream, 15858551Skris " -C, --readonly-tables Make the contents of generated lookup tables\n" 159228060Sbapt " constant, i.e., readonly.\n"); 160228060Sbapt fprintf (stream, 16158551Skris " -E, --enum Define constant values using an enum local to the\n" 162228060Sbapt " lookup function rather than with defines.\n"); 163228060Sbapt fprintf (stream, 16458551Skris " -I, --includes Include the necessary system include file <string.h>\n" 165228060Sbapt " at the beginning of the code.\n"); 166228060Sbapt fprintf (stream, 167228060Sbapt " -G, --global-table Generate the static table of keywords as a static\n" 16858551Skris " global variable, rather than hiding it inside of the\n" 169228060Sbapt " lookup function (which is the default behavior).\n"); 170228060Sbapt fprintf (stream, 171228060Sbapt " -P, --pic Optimize the generated table for inclusion in shared\n" 172228060Sbapt " libraries. This reduces the startup time of programs\n" 173228060Sbapt " using a shared library containing the generated code.\n"); 174228060Sbapt fprintf (stream, 175228060Sbapt " -Q, --string-pool-name=NAME\n" 176228060Sbapt " Specify name of string pool generated by option --pic.\n" 177228060Sbapt " Default name is 'stringpool'.\n"); 178228060Sbapt fprintf (stream, 179228060Sbapt " --null-strings Use NULL strings instead of empty strings for empty\n" 180228060Sbapt " keyword table entries.\n"); 181228060Sbapt fprintf (stream, 18258551Skris " -W, --word-array-name=NAME\n" 18358551Skris " Specify name of word list array. Default name is\n" 184228060Sbapt " 'wordlist'.\n"); 185228060Sbapt fprintf (stream, 186228060Sbapt " --length-table-name=NAME\n" 187228060Sbapt " Specify name of length table array. Default name is\n" 188228060Sbapt " 'lengthtable'.\n"); 189228060Sbapt fprintf (stream, 19058551Skris " -S, --switch=COUNT Causes the generated C code to use a switch\n" 19158551Skris " statement scheme, rather than an array lookup table.\n" 19258551Skris " This can lead to a reduction in both time and space\n" 19358551Skris " requirements for some keyfiles. The COUNT argument\n" 19458551Skris " determines how many switch statements are generated.\n" 19558551Skris " A value of 1 generates 1 switch containing all the\n" 19658551Skris " elements, a value of 2 generates 2 tables with 1/2\n" 19758551Skris " the elements in each table, etc. If COUNT is very\n" 19858551Skris " large, say 1000000, the generated C code does a\n" 199228060Sbapt " binary search.\n"); 200228060Sbapt fprintf (stream, 20158551Skris " -T, --omit-struct-type\n" 20258551Skris " Prevents the transfer of the type declaration to the\n" 20358551Skris " output file. Use this option if the type is already\n" 204228060Sbapt " defined elsewhere.\n"); 205228060Sbapt fprintf (stream, "\n"); 206228060Sbapt fprintf (stream, 207228060Sbapt "Algorithm employed by gperf:\n"); 208228060Sbapt fprintf (stream, 20958551Skris " -k, --key-positions=KEYS\n" 21058551Skris " Select the key positions used in the hash function.\n" 21158551Skris " The allowable choices range between 1-%d, inclusive.\n" 21258551Skris " The positions are separated by commas, ranges may be\n" 21358551Skris " used, and key positions may occur in any order.\n" 21458551Skris " Also, the meta-character '*' causes the generated\n" 21558551Skris " hash function to consider ALL key positions, and $\n" 216228060Sbapt " indicates the \"final character\" of a key, e.g.,\n" 217228060Sbapt " $,1,2,4,6-10.\n", 218228060Sbapt Positions::MAX_KEY_POS); 219228060Sbapt fprintf (stream, 22058551Skris " -D, --duplicates Handle keywords that hash to duplicate values. This\n" 221228060Sbapt " is useful for certain highly redundant keyword sets.\n"); 222228060Sbapt fprintf (stream, 223228060Sbapt " -m, --multiple-iterations=ITERATIONS\n" 224228060Sbapt " Perform multiple choices of the -i and -j values,\n" 225228060Sbapt " and choose the best results. This increases the\n" 226228060Sbapt " running time by a factor of ITERATIONS but does a\n" 227228060Sbapt " good job minimizing the generated table size.\n"); 228228060Sbapt fprintf (stream, 22958551Skris " -i, --initial-asso=N Provide an initial value for the associate values\n" 23058551Skris " array. Default is 0. Setting this value larger helps\n" 231228060Sbapt " inflate the size of the final table.\n"); 232228060Sbapt fprintf (stream, 233228060Sbapt " -j, --jump=JUMP-VALUE Affects the \"jump value\", i.e., how far to advance\n" 23458551Skris " the associated character value upon collisions. Must\n" 235228060Sbapt " be an odd number, default is %d.\n", 236228060Sbapt DEFAULT_JUMP_VALUE); 237228060Sbapt fprintf (stream, 23858551Skris " -n, --no-strlen Do not include the length of the keyword when\n" 239228060Sbapt " computing the hash function.\n"); 240228060Sbapt fprintf (stream, 24158551Skris " -r, --random Utilizes randomness to initialize the associated\n" 242228060Sbapt " values table.\n"); 243228060Sbapt fprintf (stream, 24458551Skris " -s, --size-multiple=N Affects the size of the generated hash table. The\n" 245228060Sbapt " numeric argument N indicates \"how many times larger\n" 246228060Sbapt " or smaller\" the associated value range should be,\n" 24758551Skris " in relationship to the number of keys, e.g. a value\n" 248228060Sbapt " of 3 means \"allow the maximum associated value to\n" 24958551Skris " be about 3 times larger than the number of input\n" 250228060Sbapt " keys\". Conversely, a value of 1/3 means \"make the\n" 25158551Skris " maximum associated value about 3 times smaller than\n" 252228060Sbapt " the number of input keys\". A larger table should\n" 25358551Skris " decrease the time required for an unsuccessful\n" 25458551Skris " search, at the expense of extra table space. Default\n" 255228060Sbapt " value is 1.\n"); 256228060Sbapt fprintf (stream, "\n"); 257228060Sbapt fprintf (stream, 25858551Skris "Informative output:\n" 25958551Skris " -h, --help Print this message.\n" 26058551Skris " -v, --version Print the gperf version number.\n" 26158551Skris " -d, --debug Enables the debugging option (produces verbose\n" 262228060Sbapt " output to the standard error).\n"); 263228060Sbapt fprintf (stream, "\n"); 264228060Sbapt fprintf (stream, 265228060Sbapt "Report bugs to <bug-gnu-gperf@gnu.org>.\n"); 26658551Skris} 26758551Skris 268228060Sbapt/* Prints the given options. */ 26958551Skris 27058551Skrisvoid 271228060SbaptOptions::print_options () const 27258551Skris{ 27358551Skris printf ("/* Command-line: "); 27458551Skris 275228060Sbapt for (int i = 0; i < _argument_count; i++) 27667064Sobrien { 277228060Sbapt const char *arg = _argument_vector[i]; 27858551Skris 279228060Sbapt /* Escape arg if it contains shell metacharacters. */ 28067064Sobrien if (*arg == '-') 28167064Sobrien { 28267064Sobrien putchar (*arg); 28367064Sobrien arg++; 284228060Sbapt if (*arg >= 'A' && *arg <= 'Z' || *arg >= 'a' && *arg <= 'z') 28567064Sobrien { 28667064Sobrien putchar (*arg); 28767064Sobrien arg++; 28867064Sobrien } 289228060Sbapt else if (*arg == '-') 290228060Sbapt { 291228060Sbapt do 292228060Sbapt { 293228060Sbapt putchar (*arg); 294228060Sbapt arg++; 295228060Sbapt } 296228060Sbapt while (*arg >= 'A' && *arg <= 'Z' || *arg >= 'a' && *arg <= 'z' || *arg == '-'); 297228060Sbapt if (*arg == '=') 298228060Sbapt { 299228060Sbapt putchar (*arg); 300228060Sbapt arg++; 301228060Sbapt } 302228060Sbapt } 30367064Sobrien } 30467064Sobrien if (strpbrk (arg, "\t\n !\"#$&'()*;<>?[\\]`{|}~") != NULL) 30567064Sobrien { 30667064Sobrien if (strchr (arg, '\'') != NULL) 30767064Sobrien { 30867064Sobrien putchar ('"'); 30967064Sobrien for (; *arg; arg++) 31067064Sobrien { 311228060Sbapt if (*arg == '\"' || *arg == '\\' || *arg == '$' || *arg == '`') 31267064Sobrien putchar ('\\'); 31367064Sobrien putchar (*arg); 31467064Sobrien } 31567064Sobrien putchar ('"'); 31667064Sobrien } 31767064Sobrien else 31867064Sobrien { 31967064Sobrien putchar ('\''); 32067064Sobrien for (; *arg; arg++) 32167064Sobrien { 32267064Sobrien if (*arg == '\\') 32367064Sobrien putchar ('\\'); 32467064Sobrien putchar (*arg); 32567064Sobrien } 32667064Sobrien putchar ('\''); 32767064Sobrien } 32867064Sobrien } 32967064Sobrien else 33067064Sobrien printf ("%s", arg); 33167064Sobrien 33267064Sobrien printf (" "); 33367064Sobrien } 33467064Sobrien 33558551Skris printf (" */"); 33658551Skris} 33758551Skris 338228060Sbapt/* ------------------------------------------------------------------------- */ 33958551Skris 340228060Sbapt/* Parses a string denoting key positions. */ 341228060Sbapt 342228060Sbaptclass PositionStringParser 34358551Skris{ 344228060Sbaptpublic: 345228060Sbapt /* Initializes a key position string parser for string STR. */ 346228060Sbapt PositionStringParser (const char *str, 347228060Sbapt int low_bound, int high_bound, 348228060Sbapt int end_word_marker, int error_value, int end_marker); 349228060Sbapt /* Returns the next key position from the given string. */ 350228060Sbapt int nextPosition (); 351228060Sbaptprivate: 352228060Sbapt /* A pointer to the string provided by the user. */ 353228060Sbapt const char * _str; 354228060Sbapt /* Smallest possible value, inclusive. */ 355228060Sbapt int const _low_bound; 356228060Sbapt /* Greatest possible value, inclusive. */ 357228060Sbapt int const _high_bound; 358228060Sbapt /* A value marking the abstract "end of word" ( usually '$'). */ 359228060Sbapt int const _end_word_marker; 360228060Sbapt /* Error value returned when input is syntactically erroneous. */ 361228060Sbapt int const _error_value; 362228060Sbapt /* Value returned after last key is processed. */ 363228060Sbapt int const _end_marker; 364228060Sbapt /* Intermediate state for producing a range of positions. */ 365228060Sbapt bool _in_range; /* True while producing a range of positions. */ 366228060Sbapt int _range_upper_bound; /* Upper bound (inclusive) of the range. */ 367228060Sbapt int _range_curr_value; /* Last value returned. */ 368228060Sbapt}; 36958551Skris 370228060Sbapt/* Initializes a key position strng parser for string STR. */ 371228060SbaptPositionStringParser::PositionStringParser (const char *str, 372228060Sbapt int low_bound, int high_bound, 373228060Sbapt int end_word_marker, int error_value, int end_marker) 374228060Sbapt : _str (str), 375228060Sbapt _low_bound (low_bound), 376228060Sbapt _high_bound (high_bound), 377228060Sbapt _end_word_marker (end_word_marker), 378228060Sbapt _error_value (error_value), 379228060Sbapt _end_marker (end_marker), 380228060Sbapt _in_range (false) 381228060Sbapt{ 382228060Sbapt} 383228060Sbapt 384228060Sbapt/* Returns the next key position from the given string. */ 385228060Sbaptint 386228060SbaptPositionStringParser::nextPosition () 387228060Sbapt{ 388228060Sbapt if (_in_range) 38958551Skris { 390228060Sbapt /* We are inside a range. Return the next value from the range. */ 391228060Sbapt if (++_range_curr_value >= _range_upper_bound) 392228060Sbapt _in_range = false; 393228060Sbapt return _range_curr_value; 394228060Sbapt } 395228060Sbapt else 396228060Sbapt { 397228060Sbapt /* Continue parsing the given string. */ 398228060Sbapt while (*_str) 399228060Sbapt switch (*_str) 400228060Sbapt { 401228060Sbapt case ',': 402228060Sbapt /* Skip the comma. */ 403228060Sbapt _str++; 404228060Sbapt break; 405228060Sbapt case '$': 406228060Sbapt /* Valid key position. */ 407228060Sbapt _str++; 408228060Sbapt return _end_word_marker; 409228060Sbapt case '0': case '1': case '2': case '3': case '4': 410228060Sbapt case '5': case '6': case '7': case '8': case '9': 411228060Sbapt /* Valid key position. */ 412228060Sbapt { 413228060Sbapt int curr_value; 414228060Sbapt for (curr_value = 0; isdigit (static_cast<unsigned char>(*_str)); _str++) 415228060Sbapt curr_value = curr_value * 10 + (*_str - '0'); 41658551Skris 417228060Sbapt if (*_str == '-') 418228060Sbapt { 419228060Sbapt _str++; 420228060Sbapt /* Starting a range of key positions. */ 421228060Sbapt _in_range = true; 42258551Skris 423228060Sbapt for (_range_upper_bound = 0; 424228060Sbapt isdigit (static_cast<unsigned char>(*_str)); 425228060Sbapt _str++) 426228060Sbapt _range_upper_bound = _range_upper_bound * 10 + (*_str - '0'); 427228060Sbapt 428228060Sbapt /* Verify range's upper bound. */ 429228060Sbapt if (!(_range_upper_bound > curr_value && _range_upper_bound <= _high_bound)) 430228060Sbapt return _error_value; 431228060Sbapt _range_curr_value = curr_value; 432228060Sbapt } 433228060Sbapt 434228060Sbapt /* Verify range's lower bound. */ 435228060Sbapt if (!(curr_value >= _low_bound && curr_value <= _high_bound)) 436228060Sbapt return _error_value; 437228060Sbapt return curr_value; 438228060Sbapt } 439228060Sbapt default: 440228060Sbapt /* Invalid syntax. */ 441228060Sbapt return _error_value; 442228060Sbapt } 443228060Sbapt 444228060Sbapt return _end_marker; 44558551Skris } 44658551Skris} 44758551Skris 448228060Sbapt/* ------------------------------------------------------------------------- */ 44958551Skris 450228060Sbapt/* Sets the default Options. */ 451228060Sbapt 452228060SbaptOptions::Options () 453228060Sbapt : _option_word (C), 454228060Sbapt _input_file_name (NULL), 455228060Sbapt _output_file_name (NULL), 456228060Sbapt _language (NULL), 457228060Sbapt _jump (DEFAULT_JUMP_VALUE), 458228060Sbapt _initial_asso_value (0), 459228060Sbapt _asso_iterations (0), 460228060Sbapt _total_switches (1), 461228060Sbapt _size_multiple (1), 462228060Sbapt _function_name (DEFAULT_FUNCTION_NAME), 463228060Sbapt _slot_name (DEFAULT_SLOT_NAME), 464228060Sbapt _initializer_suffix (DEFAULT_INITIALIZER_SUFFIX), 465228060Sbapt _class_name (DEFAULT_CLASS_NAME), 466228060Sbapt _hash_name (DEFAULT_HASH_NAME), 467228060Sbapt _wordlist_name (DEFAULT_WORDLIST_NAME), 468228060Sbapt _lengthtable_name (DEFAULT_LENGTHTABLE_NAME), 469228060Sbapt _stringpool_name (DEFAULT_STRINGPOOL_NAME), 470228060Sbapt _delimiters (DEFAULT_DELIMITERS), 471228060Sbapt _key_positions () 47258551Skris{ 47358551Skris} 47458551Skris 475228060Sbapt/* Dumps option status when debugging is enabled. */ 47658551Skris 477228060SbaptOptions::~Options () 47858551Skris{ 479228060Sbapt if (_option_word & DEBUG) 48058551Skris { 48158551Skris fprintf (stderr, "\ndumping Options:" 48258551Skris "\nTYPE is........: %s" 483228060Sbapt "\nUPPERLOWER is..: %s" 48458551Skris "\nKRC is.........: %s" 48558551Skris "\nC is...........: %s" 48658551Skris "\nANSIC is.......: %s" 48758551Skris "\nCPLUSPLUS is...: %s" 488228060Sbapt "\nSEVENBIT is....: %s" 489228060Sbapt "\nLENTABLE is....: %s" 490228060Sbapt "\nCOMP is........: %s" 491228060Sbapt "\nCONST is.......: %s" 49258551Skris "\nENUM is........: %s" 49358551Skris "\nINCLUDE is.....: %s" 494228060Sbapt "\nGLOBAL is......: %s" 495228060Sbapt "\nNULLSTRINGS is.: %s" 496228060Sbapt "\nSHAREDLIB is...: %s" 497228060Sbapt "\nSWITCH is......: %s" 498228060Sbapt "\nNOTYPE is......: %s" 499228060Sbapt "\nDUP is.........: %s" 500228060Sbapt "\nNOLENGTH is....: %s" 501228060Sbapt "\nRANDOM is......: %s" 502228060Sbapt "\nDEBUG is.......: %s" 50358551Skris "\nlookup function name = %s" 50458551Skris "\nhash function name = %s" 50558551Skris "\nword list name = %s" 506228060Sbapt "\nlength table name = %s" 507228060Sbapt "\nstring pool name = %s" 508228060Sbapt "\nslot name = %s" 50967064Sobrien "\ninitializer suffix = %s" 510228060Sbapt "\nasso_values iterations = %d" 51158551Skris "\njump value = %d" 512228060Sbapt "\nhash table size multiplier = %g" 51358551Skris "\ninitial associated value = %d" 51458551Skris "\ndelimiters = %s" 51558551Skris "\nnumber of switch statements = %d\n", 516228060Sbapt _option_word & TYPE ? "enabled" : "disabled", 517228060Sbapt _option_word & UPPERLOWER ? "enabled" : "disabled", 518228060Sbapt _option_word & KRC ? "enabled" : "disabled", 519228060Sbapt _option_word & C ? "enabled" : "disabled", 520228060Sbapt _option_word & ANSIC ? "enabled" : "disabled", 521228060Sbapt _option_word & CPLUSPLUS ? "enabled" : "disabled", 522228060Sbapt _option_word & SEVENBIT ? "enabled" : "disabled", 523228060Sbapt _option_word & LENTABLE ? "enabled" : "disabled", 524228060Sbapt _option_word & COMP ? "enabled" : "disabled", 525228060Sbapt _option_word & CONST ? "enabled" : "disabled", 526228060Sbapt _option_word & ENUM ? "enabled" : "disabled", 527228060Sbapt _option_word & INCLUDE ? "enabled" : "disabled", 528228060Sbapt _option_word & GLOBAL ? "enabled" : "disabled", 529228060Sbapt _option_word & NULLSTRINGS ? "enabled" : "disabled", 530228060Sbapt _option_word & SHAREDLIB ? "enabled" : "disabled", 531228060Sbapt _option_word & SWITCH ? "enabled" : "disabled", 532228060Sbapt _option_word & NOTYPE ? "enabled" : "disabled", 533228060Sbapt _option_word & DUP ? "enabled" : "disabled", 534228060Sbapt _option_word & NOLENGTH ? "enabled" : "disabled", 535228060Sbapt _option_word & RANDOM ? "enabled" : "disabled", 536228060Sbapt _option_word & DEBUG ? "enabled" : "disabled", 537228060Sbapt _function_name, _hash_name, _wordlist_name, _lengthtable_name, 538228060Sbapt _stringpool_name, _slot_name, _initializer_suffix, 539228060Sbapt _asso_iterations, _jump, _size_multiple, _initial_asso_value, 540228060Sbapt _delimiters, _total_switches); 541228060Sbapt if (_key_positions.is_useall()) 54258551Skris fprintf (stderr, "all characters are used in the hash function\n"); 543228060Sbapt else 544228060Sbapt { 545228060Sbapt fprintf (stderr, "maximum keysig size = %d\nkey positions are: \n", 546228060Sbapt _key_positions.get_size()); 54758551Skris 548228060Sbapt PositionIterator iter = _key_positions.iterator(); 549228060Sbapt for (int pos; (pos = iter.next()) != PositionIterator::EOS; ) 550228060Sbapt if (pos == Positions::LASTCHAR) 551228060Sbapt fprintf (stderr, "$\n"); 552228060Sbapt else 553228060Sbapt fprintf (stderr, "%d\n", pos + 1); 554228060Sbapt } 55558551Skris 55658551Skris fprintf (stderr, "finished dumping Options\n"); 55758551Skris } 55858551Skris} 55958551Skris 56058551Skris 561228060Sbapt/* Sets the output language, if not already set. */ 562228060Sbaptvoid 563228060SbaptOptions::set_language (const char *language) 564228060Sbapt{ 565228060Sbapt if (_language == NULL) 566228060Sbapt { 567228060Sbapt _language = language; 568228060Sbapt _option_word &= ~(KRC | C | ANSIC | CPLUSPLUS); 569228060Sbapt if (!strcmp (language, "KR-C")) 570228060Sbapt _option_word |= KRC; 571228060Sbapt else if (!strcmp (language, "C")) 572228060Sbapt _option_word |= C; 573228060Sbapt else if (!strcmp (language, "ANSI-C")) 574228060Sbapt _option_word |= ANSIC; 575228060Sbapt else if (!strcmp (language, "C++")) 576228060Sbapt _option_word |= CPLUSPLUS; 577228060Sbapt else 578228060Sbapt { 579228060Sbapt fprintf (stderr, "unsupported language option %s, defaulting to C\n", 580228060Sbapt language); 581228060Sbapt _option_word |= C; 582228060Sbapt } 583228060Sbapt } 584228060Sbapt} 58558551Skris 586228060Sbapt/* Sets the total number of switch statements, if not already set. */ 587228060Sbaptvoid 588228060SbaptOptions::set_total_switches (int total_switches) 589228060Sbapt{ 590228060Sbapt if (!(_option_word & SWITCH)) 591228060Sbapt { 592228060Sbapt _option_word |= SWITCH; 593228060Sbapt _total_switches = total_switches; 594228060Sbapt } 595228060Sbapt} 596228060Sbapt 597228060Sbapt/* Sets the generated function name, if not already set. */ 598228060Sbaptvoid 599228060SbaptOptions::set_function_name (const char *name) 600228060Sbapt{ 601228060Sbapt if (_function_name == DEFAULT_FUNCTION_NAME) 602228060Sbapt _function_name = name; 603228060Sbapt} 604228060Sbapt 605228060Sbapt/* Sets the keyword key name, if not already set. */ 606228060Sbaptvoid 607228060SbaptOptions::set_slot_name (const char *name) 608228060Sbapt{ 609228060Sbapt if (_slot_name == DEFAULT_SLOT_NAME) 610228060Sbapt _slot_name = name; 611228060Sbapt} 612228060Sbapt 613228060Sbapt/* Sets the struct initializer suffix, if not already set. */ 614228060Sbaptvoid 615228060SbaptOptions::set_initializer_suffix (const char *initializers) 616228060Sbapt{ 617228060Sbapt if (_initializer_suffix == DEFAULT_INITIALIZER_SUFFIX) 618228060Sbapt _initializer_suffix = initializers; 619228060Sbapt} 620228060Sbapt 621228060Sbapt/* Sets the generated class name, if not already set. */ 622228060Sbaptvoid 623228060SbaptOptions::set_class_name (const char *name) 624228060Sbapt{ 625228060Sbapt if (_class_name == DEFAULT_CLASS_NAME) 626228060Sbapt _class_name = name; 627228060Sbapt} 628228060Sbapt 629228060Sbapt/* Sets the hash function name, if not already set. */ 630228060Sbaptvoid 631228060SbaptOptions::set_hash_name (const char *name) 632228060Sbapt{ 633228060Sbapt if (_hash_name == DEFAULT_HASH_NAME) 634228060Sbapt _hash_name = name; 635228060Sbapt} 636228060Sbapt 637228060Sbapt/* Sets the hash table array name, if not already set. */ 638228060Sbaptvoid 639228060SbaptOptions::set_wordlist_name (const char *name) 640228060Sbapt{ 641228060Sbapt if (_wordlist_name == DEFAULT_WORDLIST_NAME) 642228060Sbapt _wordlist_name = name; 643228060Sbapt} 644228060Sbapt 645228060Sbapt/* Sets the length table array name, if not already set. */ 646228060Sbaptvoid 647228060SbaptOptions::set_lengthtable_name (const char *name) 648228060Sbapt{ 649228060Sbapt if (_lengthtable_name == DEFAULT_LENGTHTABLE_NAME) 650228060Sbapt _lengthtable_name = name; 651228060Sbapt} 652228060Sbapt 653228060Sbapt/* Sets the string pool name, if not already set. */ 654228060Sbaptvoid 655228060SbaptOptions::set_stringpool_name (const char *name) 656228060Sbapt{ 657228060Sbapt if (_stringpool_name == DEFAULT_STRINGPOOL_NAME) 658228060Sbapt _stringpool_name = name; 659228060Sbapt} 660228060Sbapt 661228060Sbapt/* Sets the delimiters string, if not already set. */ 662228060Sbaptvoid 663228060SbaptOptions::set_delimiters (const char *delimiters) 664228060Sbapt{ 665228060Sbapt if (_delimiters == DEFAULT_DELIMITERS) 666228060Sbapt _delimiters = delimiters; 667228060Sbapt} 668228060Sbapt 669228060Sbapt 670228060Sbapt/* Parses the command line Options and sets appropriate flags in option_word. */ 671228060Sbapt 67258551Skrisstatic const struct option long_options[] = 67358551Skris{ 674228060Sbapt { "output-file", required_argument, NULL, CHAR_MAX + 1 }, 675228060Sbapt { "ignore-case", no_argument, NULL, CHAR_MAX + 2 }, 676228060Sbapt { "delimiters", required_argument, NULL, 'e' }, 677228060Sbapt { "struct-type", no_argument, NULL, 't' }, 678228060Sbapt { "language", required_argument, NULL, 'L' }, 679228060Sbapt { "slot-name", required_argument, NULL, 'K' }, 680228060Sbapt { "initializer-suffix", required_argument, NULL, 'F' }, 681228060Sbapt { "hash-fn-name", required_argument, NULL, 'H' }, /* backward compatibility */ 682228060Sbapt { "hash-function-name", required_argument, NULL, 'H' }, 683228060Sbapt { "lookup-fn-name", required_argument, NULL, 'N' }, /* backward compatibility */ 684228060Sbapt { "lookup-function-name", required_argument, NULL, 'N' }, 685228060Sbapt { "class-name", required_argument, NULL, 'Z' }, 686228060Sbapt { "seven-bit", no_argument, NULL, '7' }, 687228060Sbapt { "compare-strncmp", no_argument, NULL, 'c' }, 688228060Sbapt { "readonly-tables", no_argument, NULL, 'C' }, 689228060Sbapt { "enum", no_argument, NULL, 'E' }, 690228060Sbapt { "includes", no_argument, NULL, 'I' }, 691228060Sbapt { "global-table", no_argument, NULL, 'G' }, 692228060Sbapt { "word-array-name", required_argument, NULL, 'W' }, 693228060Sbapt { "length-table-name", required_argument, NULL, CHAR_MAX + 4 }, 694228060Sbapt { "switch", required_argument, NULL, 'S' }, 695228060Sbapt { "omit-struct-type", no_argument, NULL, 'T' }, 696228060Sbapt { "key-positions", required_argument, NULL, 'k' }, 697228060Sbapt { "compare-strlen", no_argument, NULL, 'l' }, /* backward compatibility */ 698228060Sbapt { "compare-lengths", no_argument, NULL, 'l' }, 699228060Sbapt { "duplicates", no_argument, NULL, 'D' }, 700228060Sbapt { "fast", required_argument, NULL, 'f' }, 701228060Sbapt { "initial-asso", required_argument, NULL, 'i' }, 702228060Sbapt { "jump", required_argument, NULL, 'j' }, 703228060Sbapt { "multiple-iterations", required_argument, NULL, 'm' }, 704228060Sbapt { "no-strlen", no_argument, NULL, 'n' }, 705228060Sbapt { "occurrence-sort", no_argument, NULL, 'o' }, 706228060Sbapt { "optimized-collision-resolution", no_argument, NULL, 'O' }, 707228060Sbapt { "pic", no_argument, NULL, 'P' }, 708228060Sbapt { "string-pool-name", required_argument, NULL, 'Q' }, 709228060Sbapt { "null-strings", no_argument, NULL, CHAR_MAX + 3 }, 710228060Sbapt { "random", no_argument, NULL, 'r' }, 711228060Sbapt { "size-multiple", required_argument, NULL, 's' }, 712228060Sbapt { "help", no_argument, NULL, 'h' }, 713228060Sbapt { "version", no_argument, NULL, 'v' }, 714228060Sbapt { "debug", no_argument, NULL, 'd' }, 715228060Sbapt { NULL, no_argument, NULL, 0 } 71658551Skris}; 71758551Skris 71858551Skrisvoid 719228060SbaptOptions::parse_options (int argc, char *argv[]) 72058551Skris{ 721228060Sbapt int option_char; 72258551Skris 72358551Skris program_name = argv[0]; 724228060Sbapt _argument_count = argc; 725228060Sbapt _argument_vector = argv; 72658551Skris 72758551Skris while ((option_char = 728228060Sbapt getopt_long (_argument_count, _argument_vector, 729228060Sbapt "acCdDe:Ef:F:gGhH:i:Ij:k:K:lL:m:nN:oOpPQ:rs:S:tTvW:Z:7", 730228060Sbapt long_options, NULL)) 73158551Skris != -1) 73258551Skris { 73358551Skris switch (option_char) 73458551Skris { 735228060Sbapt case 'a': /* Generated code uses the ANSI prototype format. */ 736228060Sbapt break; /* This is now the default. */ 737228060Sbapt case 'c': /* Generate strncmp rather than strcmp. */ 73858551Skris { 739228060Sbapt _option_word |= COMP; 74058551Skris break; 74158551Skris } 742228060Sbapt case 'C': /* Make the generated tables readonly (const). */ 74358551Skris { 744228060Sbapt _option_word |= CONST; 74558551Skris break; 74658551Skris } 747228060Sbapt case 'd': /* Enable debugging option. */ 74858551Skris { 749228060Sbapt _option_word |= DEBUG; 75058551Skris fprintf (stderr, "Starting program %s, version %s, with debugging on.\n", 75158551Skris program_name, version_string); 75258551Skris break; 75358551Skris } 754228060Sbapt case 'D': /* Enable duplicate option. */ 75558551Skris { 756228060Sbapt _option_word |= DUP; 75758551Skris break; 75858551Skris } 759228060Sbapt case 'e': /* Specify keyword/attribute separator */ 76058551Skris { 761228060Sbapt _delimiters = /*getopt*/optarg; 76258551Skris break; 76358551Skris } 76458551Skris case 'E': 76558551Skris { 766228060Sbapt _option_word |= ENUM; 76758551Skris break; 76858551Skris } 769228060Sbapt case 'f': /* Generate the hash table "fast". */ 770228060Sbapt break; /* Not needed any more. */ 77167064Sobrien case 'F': 77267064Sobrien { 773228060Sbapt _initializer_suffix = /*getopt*/optarg; 77467064Sobrien break; 77567064Sobrien } 776228060Sbapt case 'g': /* Use the 'inline' keyword for generated sub-routines, ifdef __GNUC__. */ 777228060Sbapt break; /* This is now the default. */ 778228060Sbapt case 'G': /* Make the keyword table a global variable. */ 77958551Skris { 780228060Sbapt _option_word |= GLOBAL; 78158551Skris break; 78258551Skris } 783228060Sbapt case 'h': /* Displays a list of helpful Options to the user. */ 78458551Skris { 78558551Skris long_usage (stdout); 78658551Skris exit (0); 78758551Skris } 788228060Sbapt case 'H': /* Sets the name for the hash function. */ 78958551Skris { 790228060Sbapt _hash_name = /*getopt*/optarg; 79158551Skris break; 79258551Skris } 793228060Sbapt case 'i': /* Sets the initial value for the associated values array. */ 79458551Skris { 795228060Sbapt if ((_initial_asso_value = atoi (/*getopt*/optarg)) < 0) 796228060Sbapt fprintf (stderr, "Initial value %d should be non-zero, ignoring and continuing.\n", _initial_asso_value); 79758551Skris if (option[RANDOM]) 79858551Skris fprintf (stderr, "warning, -r option superceeds -i, ignoring -i option and continuing\n"); 79958551Skris break; 80058551Skris } 801228060Sbapt case 'I': /* Enable #include statements. */ 80258551Skris { 803228060Sbapt _option_word |= INCLUDE; 80458551Skris break; 80558551Skris } 806228060Sbapt case 'j': /* Sets the jump value, must be odd for later algorithms. */ 80758551Skris { 808228060Sbapt if ((_jump = atoi (/*getopt*/optarg)) < 0) 80958551Skris { 810228060Sbapt fprintf (stderr, "Jump value %d must be a positive number.\n", _jump); 81158551Skris short_usage (stderr); 81258551Skris exit (1); 81358551Skris } 814228060Sbapt else if (_jump && ((_jump % 2) == 0)) 815228060Sbapt fprintf (stderr, "Jump value %d should be odd, adding 1 and continuing...\n", _jump++); 81658551Skris break; 81758551Skris } 818228060Sbapt case 'k': /* Sets key positions used for hash function. */ 81958551Skris { 820228060Sbapt _option_word |= POSITIONS; 821228060Sbapt const int BAD_VALUE = -3; 822228060Sbapt const int EOS = PositionIterator::EOS; 82358551Skris int value; 824228060Sbapt PositionStringParser sparser (/*getopt*/optarg, 1, Positions::MAX_KEY_POS, Positions::LASTCHAR, BAD_VALUE, EOS); 82558551Skris 82658551Skris if (/*getopt*/optarg [0] == '*') /* Use all the characters for hashing!!!! */ 827228060Sbapt _key_positions.set_useall(true); 82858551Skris else 82958551Skris { 830228060Sbapt _key_positions.set_useall(false); 831228060Sbapt int *key_positions = _key_positions.pointer(); 832228060Sbapt int *key_pos; 83358551Skris 834228060Sbapt for (key_pos = key_positions; (value = sparser.nextPosition()) != EOS; key_pos++) 835228060Sbapt { 836228060Sbapt if (value == BAD_VALUE) 837228060Sbapt { 838228060Sbapt fprintf (stderr, "Invalid position value or range, use 1,2,3-%d,'$' or '*'.\n", 839228060Sbapt Positions::MAX_KEY_POS); 840228060Sbapt short_usage (stderr); 841228060Sbapt exit (1); 842228060Sbapt } 843228060Sbapt if (key_pos - key_positions == Positions::MAX_SIZE) 844228060Sbapt { 845228060Sbapt /* More than Positions::MAX_SIZE key positions. 846228060Sbapt Since all key positions are in the range 847228060Sbapt 0..Positions::MAX_KEY_POS-1 or == Positions::LASTCHAR, 848228060Sbapt there must be duplicates. */ 849228060Sbapt fprintf (stderr, "Duplicate key positions selected\n"); 850228060Sbapt short_usage (stderr); 851228060Sbapt exit (1); 852228060Sbapt } 853228060Sbapt if (value != Positions::LASTCHAR) 854228060Sbapt /* We use 0-based indices in the class Positions. */ 855228060Sbapt value = value - 1; 856228060Sbapt *key_pos = value; 857228060Sbapt } 85858551Skris 859228060Sbapt unsigned int total_keysig_size = key_pos - key_positions; 860228060Sbapt if (total_keysig_size == 0) 86158551Skris { 862228060Sbapt fprintf (stderr, "No key positions selected.\n"); 86358551Skris short_usage (stderr); 86458551Skris exit (1); 86558551Skris } 866228060Sbapt _key_positions.set_size (total_keysig_size); 867228060Sbapt 868228060Sbapt /* Sorts the key positions *IN REVERSE ORDER!!* 869228060Sbapt This makes further routines more efficient. Especially 870228060Sbapt when generating code. */ 871228060Sbapt if (! _key_positions.sort()) 87258551Skris { 873228060Sbapt fprintf (stderr, "Duplicate key positions selected\n"); 87458551Skris short_usage (stderr); 87558551Skris exit (1); 87658551Skris } 87758551Skris } 87858551Skris break; 87958551Skris } 880228060Sbapt case 'K': /* Make this the keyname for the keyword component field. */ 88158551Skris { 882228060Sbapt _slot_name = /*getopt*/optarg; 88358551Skris break; 88458551Skris } 885228060Sbapt case 'l': /* Create length table to avoid extra string compares. */ 88658551Skris { 887228060Sbapt _option_word |= LENTABLE; 88858551Skris break; 88958551Skris } 890228060Sbapt case 'L': /* Deal with different generated languages. */ 89158551Skris { 892228060Sbapt _language = NULL; 893228060Sbapt set_language (/*getopt*/optarg); 894228060Sbapt break; 895228060Sbapt } 896228060Sbapt case 'm': /* Multiple iterations for finding good asso_values. */ 897228060Sbapt { 898228060Sbapt if ((_asso_iterations = atoi (/*getopt*/optarg)) < 0) 89958551Skris { 900228060Sbapt fprintf (stderr, "asso_iterations value must not be negative, assuming 0\n"); 901228060Sbapt _asso_iterations = 0; 90258551Skris } 90358551Skris break; 90458551Skris } 905228060Sbapt case 'n': /* Don't include the length when computing hash function. */ 90658551Skris { 907228060Sbapt _option_word |= NOLENGTH; 90858551Skris break; 90958551Skris } 910228060Sbapt case 'N': /* Make generated lookup function name be optarg. */ 91158551Skris { 912228060Sbapt _function_name = /*getopt*/optarg; 91358551Skris break; 91458551Skris } 915228060Sbapt case 'o': /* Order input by frequency of key set occurrence. */ 916228060Sbapt break; /* Not needed any more. */ 917228060Sbapt case 'O': /* Optimized choice during collision resolution. */ 918228060Sbapt break; /* Not needed any more. */ 919228060Sbapt case 'p': /* Generated lookup function a pointer instead of int. */ 920228060Sbapt break; /* This is now the default. */ 921228060Sbapt case 'P': /* Optimize for position-independent code. */ 92258551Skris { 923228060Sbapt _option_word |= SHAREDLIB; 92458551Skris break; 92558551Skris } 926228060Sbapt case 'Q': /* Sets the name for the string pool. */ 92758551Skris { 928228060Sbapt _stringpool_name = /*getopt*/optarg; 92958551Skris break; 93058551Skris } 931228060Sbapt case 'r': /* Utilize randomness to initialize the associated values table. */ 93258551Skris { 933228060Sbapt _option_word |= RANDOM; 934228060Sbapt if (_initial_asso_value != 0) 935228060Sbapt fprintf (stderr, "warning, -r option supersedes -i, disabling -i option and continuing\n"); 93658551Skris break; 93758551Skris } 938228060Sbapt case 's': /* Range of associated values, determines size of final table. */ 93958551Skris { 940228060Sbapt float numerator; 941228060Sbapt float denominator = 1; 942228060Sbapt bool invalid = false; 943228060Sbapt char *endptr; 944228060Sbapt 945228060Sbapt numerator = strtod (/*getopt*/optarg, &endptr); 946228060Sbapt if (endptr == /*getopt*/optarg) 947228060Sbapt invalid = true; 948228060Sbapt else if (*endptr != '\0') 94958551Skris { 950228060Sbapt if (*endptr == '/') 951228060Sbapt { 952228060Sbapt char *denomptr = endptr + 1; 953228060Sbapt denominator = strtod (denomptr, &endptr); 954228060Sbapt if (endptr == denomptr || *endptr != '\0') 955228060Sbapt invalid = true; 956228060Sbapt } 957228060Sbapt else 958228060Sbapt invalid = true; 959228060Sbapt } 960228060Sbapt if (invalid) 961228060Sbapt { 962228060Sbapt fprintf (stderr, "Invalid value for option -s.\n"); 963228060Sbapt short_usage (stderr); 964228060Sbapt exit (1); 965228060Sbapt } 966228060Sbapt _size_multiple = numerator / denominator; 967228060Sbapt /* Backward compatibility: -3 means 1/3. */ 968228060Sbapt if (_size_multiple < 0) 969228060Sbapt _size_multiple = 1 / (-_size_multiple); 970228060Sbapt /* Catch stupid users. */ 971228060Sbapt if (_size_multiple == 0) 972228060Sbapt _size_multiple = 1; 973228060Sbapt /* Warnings. */ 974228060Sbapt if (_size_multiple > 50) 975228060Sbapt fprintf (stderr, "Size multiple %g is excessive, did you really mean this?! (try '%s --help' for help)\n", _size_multiple, program_name); 976228060Sbapt else if (_size_multiple < 0.01f) 977228060Sbapt fprintf (stderr, "Size multiple %g is extremely small, did you really mean this?! (try '%s --help' for help)\n", _size_multiple, program_name); 978228060Sbapt break; 979228060Sbapt } 980228060Sbapt case 'S': /* Generate switch statement output, rather than lookup table. */ 981228060Sbapt { 982228060Sbapt _option_word |= SWITCH; 983228060Sbapt _total_switches = atoi (/*getopt*/optarg); 984228060Sbapt if (_total_switches <= 0) 985228060Sbapt { 98658551Skris fprintf (stderr, "number of switches %s must be a positive number\n", /*getopt*/optarg); 98758551Skris short_usage (stderr); 98858551Skris exit (1); 98958551Skris } 99058551Skris break; 99158551Skris } 992228060Sbapt case 't': /* Enable the TYPE mode, allowing arbitrary user structures. */ 99358551Skris { 994228060Sbapt _option_word |= TYPE; 99558551Skris break; 99658551Skris } 997228060Sbapt case 'T': /* Don't print structure definition. */ 99858551Skris { 999228060Sbapt _option_word |= NOTYPE; 100058551Skris break; 100158551Skris } 1002228060Sbapt case 'v': /* Print out the version and quit. */ 100358551Skris fprintf (stdout, "GNU gperf %s\n", version_string); 1004228060Sbapt fprintf (stdout, "Copyright (C) %s Free Software Foundation, Inc.\n\ 1005228060SbaptThis is free software; see the source for copying conditions. There is NO\n\ 1006228060Sbaptwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ 1007228060Sbapt", 1008228060Sbapt "1989-1998, 2000-2004, 2006-2007"); 1009228060Sbapt fprintf (stdout, "Written by %s and %s.\n", 1010228060Sbapt "Douglas C. Schmidt", "Bruno Haible"); 101158551Skris exit (0); 1012228060Sbapt case 'W': /* Sets the name for the hash table array. */ 101358551Skris { 1014228060Sbapt _wordlist_name = /*getopt*/optarg; 101558551Skris break; 101658551Skris } 1017228060Sbapt case 'Z': /* Set the class name. */ 101858551Skris { 1019228060Sbapt _class_name = /*getopt*/optarg; 102058551Skris break; 102158551Skris } 1022228060Sbapt case '7': /* Assume 7-bit characters. */ 102358551Skris { 1024228060Sbapt _option_word |= SEVENBIT; 102558551Skris break; 102658551Skris } 1027228060Sbapt case CHAR_MAX + 1: /* Set the output file name. */ 1028228060Sbapt { 1029228060Sbapt _output_file_name = /*getopt*/optarg; 1030228060Sbapt break; 1031228060Sbapt } 1032228060Sbapt case CHAR_MAX + 2: /* Case insignificant. */ 1033228060Sbapt { 1034228060Sbapt _option_word |= UPPERLOWER; 1035228060Sbapt break; 1036228060Sbapt } 1037228060Sbapt case CHAR_MAX + 3: /* Use NULL instead of "". */ 1038228060Sbapt { 1039228060Sbapt _option_word |= NULLSTRINGS; 1040228060Sbapt break; 1041228060Sbapt } 1042228060Sbapt case CHAR_MAX + 4: /* Sets the name for the length table array. */ 1043228060Sbapt { 1044228060Sbapt _lengthtable_name = /*getopt*/optarg; 1045228060Sbapt break; 1046228060Sbapt } 104758551Skris default: 104858551Skris short_usage (stderr); 104958551Skris exit (1); 105058551Skris } 105158551Skris 105258551Skris } 105358551Skris 1054228060Sbapt if (/*getopt*/optind < argc) 1055228060Sbapt _input_file_name = argv[/*getopt*/optind++]; 105658551Skris 1057228060Sbapt if (/*getopt*/optind < argc) 105858551Skris { 105958551Skris fprintf (stderr, "Extra trailing arguments to %s.\n", program_name); 106058551Skris short_usage (stderr); 106158551Skris exit (1); 106258551Skris } 106358551Skris} 106458551Skris 1065228060Sbapt/* ------------------------------------------------------------------------- */ 1066228060Sbapt 106758551Skris#ifndef __OPTIMIZE__ 106858551Skris 106958551Skris#define INLINE /* not inline */ 107058551Skris#include "options.icc" 107158551Skris#undef INLINE 107258551Skris 107358551Skris#endif /* not defined __OPTIMIZE__ */ 1074