1/* Handles parsing the Options provided to the user. 2 Copyright (C) 1989-1998, 2000, 2002-2004, 2006-2007 Free Software Foundation, Inc. 3 Written by Douglas C. Schmidt <schmidt@ics.uci.edu> 4 and Bruno Haible <bruno@clisp.org>. 5 6 This file is part of GNU GPERF. 7 8 GNU GPERF is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2, or (at your option) 11 any later version. 12 13 GNU GPERF is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; see the file COPYING. 20 If not, write to the Free Software Foundation, Inc., 21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 22 23/* Specification. */ 24#include "options.h" 25 26#include <stdio.h> 27#include <stdlib.h> /* declares atoi(), abs(), exit() */ 28#include <string.h> /* declares strcmp() */ 29#include <ctype.h> /* declares isdigit() */ 30#include <limits.h> /* defines CHAR_MAX */ 31#include "getopt.h" 32#include "version.h" 33 34/* Global option coordinator for the entire program. */ 35Options option; 36 37/* Records the program name. */ 38const char *program_name; 39 40/* Size to jump on a collision. */ 41static const int DEFAULT_JUMP_VALUE = 5; 42 43/* Default name for generated lookup function. */ 44static const char *const DEFAULT_FUNCTION_NAME = "in_word_set"; 45 46/* Default name for the key component. */ 47static const char *const DEFAULT_SLOT_NAME = "name"; 48 49/* Default struct initializer suffix. */ 50static const char *const DEFAULT_INITIALIZER_SUFFIX = ""; 51 52/* Default name for the generated class. */ 53static const char *const DEFAULT_CLASS_NAME = "Perfect_Hash"; 54 55/* Default name for generated hash function. */ 56static const char *const DEFAULT_HASH_NAME = "hash"; 57 58/* Default name for generated hash table array. */ 59static const char *const DEFAULT_WORDLIST_NAME = "wordlist"; 60 61/* Default name for generated length table array. */ 62static const char *const DEFAULT_LENGTHTABLE_NAME = "lengthtable"; 63 64/* Default name for string pool. */ 65static const char *const DEFAULT_STRINGPOOL_NAME = "stringpool"; 66 67/* Default delimiters that separate keywords from their attributes. */ 68static const char *const DEFAULT_DELIMITERS = ","; 69 70/* Prints program usage to given stream. */ 71 72void 73Options::short_usage (FILE * stream) 74{ 75 fprintf (stream, 76 "Try '%s --help' for more information.\n", program_name); 77} 78 79void 80Options::long_usage (FILE * stream) 81{ 82 fprintf (stream, 83 "GNU 'gperf' generates perfect hash functions.\n"); 84 fprintf (stream, "\n"); 85 fprintf (stream, 86 "Usage: %s [OPTION]... [INPUT-FILE]\n", 87 program_name); 88 fprintf (stream, "\n"); 89 fprintf (stream, 90 "If a long option shows an argument as mandatory, then it is mandatory\n" 91 "for the equivalent short option also.\n"); 92 fprintf (stream, "\n"); 93 fprintf (stream, 94 "Output file location:\n"); 95 fprintf (stream, 96 " --output-file=FILE Write output to specified file.\n"); 97 fprintf (stream, 98 "The results are written to standard output if no output file is specified\n" 99 "or if it is -.\n"); 100 fprintf (stream, "\n"); 101 fprintf (stream, 102 "Input file interpretation:\n"); 103 fprintf (stream, 104 " -e, --delimiters=DELIMITER-LIST\n" 105 " Allow user to provide a string containing delimiters\n" 106 " used to separate keywords from their attributes.\n" 107 " Default is \",\".\n"); 108 fprintf (stream, 109 " -t, --struct-type Allows the user to include a structured type\n" 110 " declaration for generated code. Any text before %%%%\n" 111 " is considered part of the type declaration. Key\n" 112 " words and additional fields may follow this, one\n" 113 " group of fields per line.\n"); 114 fprintf (stream, 115 " --ignore-case Consider upper and lower case ASCII characters as\n" 116 " equivalent. Note that locale dependent case mappings\n" 117 " are ignored.\n"); 118 fprintf (stream, "\n"); 119 fprintf (stream, 120 "Language for the output code:\n"); 121 fprintf (stream, 122 " -L, --language=LANGUAGE-NAME\n" 123 " Generates code in the specified language. Languages\n" 124 " handled are currently C++, ANSI-C, C, and KR-C. The\n" 125 " default is C.\n"); 126 fprintf (stream, "\n"); 127 fprintf (stream, 128 "Details in the output code:\n"); 129 fprintf (stream, 130 " -K, --slot-name=NAME Select name of the keyword component in the keyword\n" 131 " structure.\n"); 132 fprintf (stream, 133 " -F, --initializer-suffix=INITIALIZERS\n" 134 " Initializers for additional components in the keyword\n" 135 " structure.\n"); 136 fprintf (stream, 137 " -H, --hash-function-name=NAME\n" 138 " Specify name of generated hash function. Default is\n" 139 " 'hash'.\n"); 140 fprintf (stream, 141 " -N, --lookup-function-name=NAME\n" 142 " Specify name of generated lookup function. Default\n" 143 " name is 'in_word_set'.\n"); 144 fprintf (stream, 145 " -Z, --class-name=NAME Specify name of generated C++ class. Default name is\n" 146 " 'Perfect_Hash'.\n"); 147 fprintf (stream, 148 " -7, --seven-bit Assume 7-bit characters.\n"); 149 fprintf (stream, 150 " -l, --compare-lengths Compare key lengths before trying a string\n" 151 " comparison. This is necessary if the keywords\n" 152 " contain NUL bytes. It also helps cut down on the\n" 153 " number of string comparisons made during the lookup.\n"); 154 fprintf (stream, 155 " -c, --compare-strncmp Generate comparison code using strncmp rather than\n" 156 " strcmp.\n"); 157 fprintf (stream, 158 " -C, --readonly-tables Make the contents of generated lookup tables\n" 159 " constant, i.e., readonly.\n"); 160 fprintf (stream, 161 " -E, --enum Define constant values using an enum local to the\n" 162 " lookup function rather than with defines.\n"); 163 fprintf (stream, 164 " -I, --includes Include the necessary system include file <string.h>\n" 165 " at the beginning of the code.\n"); 166 fprintf (stream, 167 " -G, --global-table Generate the static table of keywords as a static\n" 168 " global variable, rather than hiding it inside of the\n" 169 " lookup function (which is the default behavior).\n"); 170 fprintf (stream, 171 " -P, --pic Optimize the generated table for inclusion in shared\n" 172 " libraries. This reduces the startup time of programs\n" 173 " using a shared library containing the generated code.\n"); 174 fprintf (stream, 175 " -Q, --string-pool-name=NAME\n" 176 " Specify name of string pool generated by option --pic.\n" 177 " Default name is 'stringpool'.\n"); 178 fprintf (stream, 179 " --null-strings Use NULL strings instead of empty strings for empty\n" 180 " keyword table entries.\n"); 181 fprintf (stream, 182 " -W, --word-array-name=NAME\n" 183 " Specify name of word list array. Default name is\n" 184 " 'wordlist'.\n"); 185 fprintf (stream, 186 " --length-table-name=NAME\n" 187 " Specify name of length table array. Default name is\n" 188 " 'lengthtable'.\n"); 189 fprintf (stream, 190 " -S, --switch=COUNT Causes the generated C code to use a switch\n" 191 " statement scheme, rather than an array lookup table.\n" 192 " This can lead to a reduction in both time and space\n" 193 " requirements for some keyfiles. The COUNT argument\n" 194 " determines how many switch statements are generated.\n" 195 " A value of 1 generates 1 switch containing all the\n" 196 " elements, a value of 2 generates 2 tables with 1/2\n" 197 " the elements in each table, etc. If COUNT is very\n" 198 " large, say 1000000, the generated C code does a\n" 199 " binary search.\n"); 200 fprintf (stream, 201 " -T, --omit-struct-type\n" 202 " Prevents the transfer of the type declaration to the\n" 203 " output file. Use this option if the type is already\n" 204 " defined elsewhere.\n"); 205 fprintf (stream, "\n"); 206 fprintf (stream, 207 "Algorithm employed by gperf:\n"); 208 fprintf (stream, 209 " -k, --key-positions=KEYS\n" 210 " Select the key positions used in the hash function.\n" 211 " The allowable choices range between 1-%d, inclusive.\n" 212 " The positions are separated by commas, ranges may be\n" 213 " used, and key positions may occur in any order.\n" 214 " Also, the meta-character '*' causes the generated\n" 215 " hash function to consider ALL key positions, and $\n" 216 " indicates the \"final character\" of a key, e.g.,\n" 217 " $,1,2,4,6-10.\n", 218 Positions::MAX_KEY_POS); 219 fprintf (stream, 220 " -D, --duplicates Handle keywords that hash to duplicate values. This\n" 221 " is useful for certain highly redundant keyword sets.\n"); 222 fprintf (stream, 223 " -m, --multiple-iterations=ITERATIONS\n" 224 " Perform multiple choices of the -i and -j values,\n" 225 " and choose the best results. This increases the\n" 226 " running time by a factor of ITERATIONS but does a\n" 227 " good job minimizing the generated table size.\n"); 228 fprintf (stream, 229 " -i, --initial-asso=N Provide an initial value for the associate values\n" 230 " array. Default is 0. Setting this value larger helps\n" 231 " inflate the size of the final table.\n"); 232 fprintf (stream, 233 " -j, --jump=JUMP-VALUE Affects the \"jump value\", i.e., how far to advance\n" 234 " the associated character value upon collisions. Must\n" 235 " be an odd number, default is %d.\n", 236 DEFAULT_JUMP_VALUE); 237 fprintf (stream, 238 " -n, --no-strlen Do not include the length of the keyword when\n" 239 " computing the hash function.\n"); 240 fprintf (stream, 241 " -r, --random Utilizes randomness to initialize the associated\n" 242 " values table.\n"); 243 fprintf (stream, 244 " -s, --size-multiple=N Affects the size of the generated hash table. The\n" 245 " numeric argument N indicates \"how many times larger\n" 246 " or smaller\" the associated value range should be,\n" 247 " in relationship to the number of keys, e.g. a value\n" 248 " of 3 means \"allow the maximum associated value to\n" 249 " be about 3 times larger than the number of input\n" 250 " keys\". Conversely, a value of 1/3 means \"make the\n" 251 " maximum associated value about 3 times smaller than\n" 252 " the number of input keys\". A larger table should\n" 253 " decrease the time required for an unsuccessful\n" 254 " search, at the expense of extra table space. Default\n" 255 " value is 1.\n"); 256 fprintf (stream, "\n"); 257 fprintf (stream, 258 "Informative output:\n" 259 " -h, --help Print this message.\n" 260 " -v, --version Print the gperf version number.\n" 261 " -d, --debug Enables the debugging option (produces verbose\n" 262 " output to the standard error).\n"); 263 fprintf (stream, "\n"); 264 fprintf (stream, 265 "Report bugs to <bug-gnu-gperf@gnu.org>.\n"); 266} 267 268/* Prints the given options. */ 269 270void 271Options::print_options () const 272{ 273 printf ("/* Command-line: "); 274 275 for (int i = 0; i < _argument_count; i++) 276 { 277 const char *arg = _argument_vector[i]; 278 279 /* Escape arg if it contains shell metacharacters. */ 280 if (*arg == '-') 281 { 282 putchar (*arg); 283 arg++; 284 if ( (*arg >= 'A' && *arg <= 'Z') || (*arg >= 'a' && *arg <= 'z') ) 285 { 286 putchar (*arg); 287 arg++; 288 } 289 else if (*arg == '-') 290 { 291 do 292 { 293 putchar (*arg); 294 arg++; 295 } 296 while ( (*arg >= 'A' && *arg <= 'Z') || 297 (*arg >= 'a' && *arg <= 'z') || 298 *arg == '-'); 299 if (*arg == '=') 300 { 301 putchar (*arg); 302 arg++; 303 } 304 } 305 } 306 if (strpbrk (arg, "\t\n !\"#$&'()*;<>?[\\]`{|}~") != NULL) 307 { 308 if (strchr (arg, '\'') != NULL) 309 { 310 putchar ('"'); 311 for (; *arg; arg++) 312 { 313 if (*arg == '\"' || *arg == '\\' || *arg == '$' || *arg == '`') 314 putchar ('\\'); 315 putchar (*arg); 316 } 317 putchar ('"'); 318 } 319 else 320 { 321 putchar ('\''); 322 for (; *arg; arg++) 323 { 324 if (*arg == '\\') 325 putchar ('\\'); 326 putchar (*arg); 327 } 328 putchar ('\''); 329 } 330 } 331 else 332 printf ("%s", arg); 333 334 printf (" "); 335 } 336 337 printf (" */"); 338} 339 340/* ------------------------------------------------------------------------- */ 341 342/* Parses a string denoting key positions. */ 343 344class PositionStringParser 345{ 346public: 347 /* Initializes a key position string parser for string STR. */ 348 PositionStringParser (const char *str, 349 int low_bound, int high_bound, 350 int end_word_marker, int error_value, int end_marker); 351 /* Returns the next key position from the given string. */ 352 int nextPosition (); 353private: 354 /* A pointer to the string provided by the user. */ 355 const char * _str; 356 /* Smallest possible value, inclusive. */ 357 int const _low_bound; 358 /* Greatest possible value, inclusive. */ 359 int const _high_bound; 360 /* A value marking the abstract "end of word" ( usually '$'). */ 361 int const _end_word_marker; 362 /* Error value returned when input is syntactically erroneous. */ 363 int const _error_value; 364 /* Value returned after last key is processed. */ 365 int const _end_marker; 366 /* Intermediate state for producing a range of positions. */ 367 bool _in_range; /* True while producing a range of positions. */ 368 int _range_upper_bound; /* Upper bound (inclusive) of the range. */ 369 int _range_curr_value; /* Last value returned. */ 370}; 371 372/* Initializes a key position strng parser for string STR. */ 373PositionStringParser::PositionStringParser (const char *str, 374 int low_bound, int high_bound, 375 int end_word_marker, int error_value, int end_marker) 376 : _str (str), 377 _low_bound (low_bound), 378 _high_bound (high_bound), 379 _end_word_marker (end_word_marker), 380 _error_value (error_value), 381 _end_marker (end_marker), 382 _in_range (false) 383{ 384} 385 386/* Returns the next key position from the given string. */ 387int 388PositionStringParser::nextPosition () 389{ 390 if (_in_range) 391 { 392 /* We are inside a range. Return the next value from the range. */ 393 if (++_range_curr_value >= _range_upper_bound) 394 _in_range = false; 395 return _range_curr_value; 396 } 397 else 398 { 399 /* Continue parsing the given string. */ 400 while (*_str) 401 switch (*_str) 402 { 403 case ',': 404 /* Skip the comma. */ 405 _str++; 406 break; 407 case '$': 408 /* Valid key position. */ 409 _str++; 410 return _end_word_marker; 411 case '0': case '1': case '2': case '3': case '4': 412 case '5': case '6': case '7': case '8': case '9': 413 /* Valid key position. */ 414 { 415 int curr_value; 416 for (curr_value = 0; isdigit (static_cast<unsigned char>(*_str)); _str++) 417 curr_value = curr_value * 10 + (*_str - '0'); 418 419 if (*_str == '-') 420 { 421 _str++; 422 /* Starting a range of key positions. */ 423 _in_range = true; 424 425 for (_range_upper_bound = 0; 426 isdigit (static_cast<unsigned char>(*_str)); 427 _str++) 428 _range_upper_bound = _range_upper_bound * 10 + (*_str - '0'); 429 430 /* Verify range's upper bound. */ 431 if (!(_range_upper_bound > curr_value && _range_upper_bound <= _high_bound)) 432 return _error_value; 433 _range_curr_value = curr_value; 434 } 435 436 /* Verify range's lower bound. */ 437 if (!(curr_value >= _low_bound && curr_value <= _high_bound)) 438 return _error_value; 439 return curr_value; 440 } 441 default: 442 /* Invalid syntax. */ 443 return _error_value; 444 } 445 446 return _end_marker; 447 } 448} 449 450/* ------------------------------------------------------------------------- */ 451 452/* Sets the default Options. */ 453 454Options::Options () 455 : _option_word (C), 456 _input_file_name (NULL), 457 _output_file_name (NULL), 458 _language (NULL), 459 _jump (DEFAULT_JUMP_VALUE), 460 _initial_asso_value (0), 461 _asso_iterations (0), 462 _total_switches (1), 463 _size_multiple (1), 464 _function_name (DEFAULT_FUNCTION_NAME), 465 _slot_name (DEFAULT_SLOT_NAME), 466 _initializer_suffix (DEFAULT_INITIALIZER_SUFFIX), 467 _class_name (DEFAULT_CLASS_NAME), 468 _hash_name (DEFAULT_HASH_NAME), 469 _wordlist_name (DEFAULT_WORDLIST_NAME), 470 _lengthtable_name (DEFAULT_LENGTHTABLE_NAME), 471 _stringpool_name (DEFAULT_STRINGPOOL_NAME), 472 _delimiters (DEFAULT_DELIMITERS), 473 _key_positions () 474{ 475} 476 477/* Dumps option status when debugging is enabled. */ 478 479Options::~Options () 480{ 481 if (_option_word & DEBUG) 482 { 483 fprintf (stderr, "\ndumping Options:" 484 "\nTYPE is........: %s" 485 "\nUPPERLOWER is..: %s" 486 "\nKRC is.........: %s" 487 "\nC is...........: %s" 488 "\nANSIC is.......: %s" 489 "\nCPLUSPLUS is...: %s" 490 "\nSEVENBIT is....: %s" 491 "\nLENTABLE is....: %s" 492 "\nCOMP is........: %s" 493 "\nCONST is.......: %s" 494 "\nENUM is........: %s" 495 "\nINCLUDE is.....: %s" 496 "\nGLOBAL is......: %s" 497 "\nNULLSTRINGS is.: %s" 498 "\nSHAREDLIB is...: %s" 499 "\nSWITCH is......: %s" 500 "\nNOTYPE is......: %s" 501 "\nDUP is.........: %s" 502 "\nNOLENGTH is....: %s" 503 "\nRANDOM is......: %s" 504 "\nDEBUG is.......: %s" 505 "\nlookup function name = %s" 506 "\nhash function name = %s" 507 "\nword list name = %s" 508 "\nlength table name = %s" 509 "\nstring pool name = %s" 510 "\nslot name = %s" 511 "\ninitializer suffix = %s" 512 "\nasso_values iterations = %d" 513 "\njump value = %d" 514 "\nhash table size multiplier = %g" 515 "\ninitial associated value = %d" 516 "\ndelimiters = %s" 517 "\nnumber of switch statements = %d\n", 518 _option_word & TYPE ? "enabled" : "disabled", 519 _option_word & UPPERLOWER ? "enabled" : "disabled", 520 _option_word & KRC ? "enabled" : "disabled", 521 _option_word & C ? "enabled" : "disabled", 522 _option_word & ANSIC ? "enabled" : "disabled", 523 _option_word & CPLUSPLUS ? "enabled" : "disabled", 524 _option_word & SEVENBIT ? "enabled" : "disabled", 525 _option_word & LENTABLE ? "enabled" : "disabled", 526 _option_word & COMP ? "enabled" : "disabled", 527 _option_word & CONST ? "enabled" : "disabled", 528 _option_word & ENUM ? "enabled" : "disabled", 529 _option_word & INCLUDE ? "enabled" : "disabled", 530 _option_word & GLOBAL ? "enabled" : "disabled", 531 _option_word & NULLSTRINGS ? "enabled" : "disabled", 532 _option_word & SHAREDLIB ? "enabled" : "disabled", 533 _option_word & SWITCH ? "enabled" : "disabled", 534 _option_word & NOTYPE ? "enabled" : "disabled", 535 _option_word & DUP ? "enabled" : "disabled", 536 _option_word & NOLENGTH ? "enabled" : "disabled", 537 _option_word & RANDOM ? "enabled" : "disabled", 538 _option_word & DEBUG ? "enabled" : "disabled", 539 _function_name, _hash_name, _wordlist_name, _lengthtable_name, 540 _stringpool_name, _slot_name, _initializer_suffix, 541 _asso_iterations, _jump, _size_multiple, _initial_asso_value, 542 _delimiters, _total_switches); 543 if (_key_positions.is_useall()) 544 fprintf (stderr, "all characters are used in the hash function\n"); 545 else 546 { 547 fprintf (stderr, "maximum keysig size = %d\nkey positions are: \n", 548 _key_positions.get_size()); 549 550 PositionIterator iter = _key_positions.iterator(); 551 for (int pos; (pos = iter.next()) != PositionIterator::EOS; ) 552 if (pos == Positions::LASTCHAR) 553 fprintf (stderr, "$\n"); 554 else 555 fprintf (stderr, "%d\n", pos + 1); 556 } 557 558 fprintf (stderr, "finished dumping Options\n"); 559 } 560} 561 562 563/* Sets the output language, if not already set. */ 564void 565Options::set_language (const char *language) 566{ 567 if (_language == NULL) 568 { 569 _language = language; 570 _option_word &= ~(KRC | C | ANSIC | CPLUSPLUS); 571 if (!strcmp (language, "KR-C")) 572 _option_word |= KRC; 573 else if (!strcmp (language, "C")) 574 _option_word |= C; 575 else if (!strcmp (language, "ANSI-C")) 576 _option_word |= ANSIC; 577 else if (!strcmp (language, "C++")) 578 _option_word |= CPLUSPLUS; 579 else 580 { 581 fprintf (stderr, "unsupported language option %s, defaulting to C\n", 582 language); 583 _option_word |= C; 584 } 585 } 586} 587 588/* Sets the total number of switch statements, if not already set. */ 589void 590Options::set_total_switches (int total_switches) 591{ 592 if (!(_option_word & SWITCH)) 593 { 594 _option_word |= SWITCH; 595 _total_switches = total_switches; 596 } 597} 598 599/* Sets the generated function name, if not already set. */ 600void 601Options::set_function_name (const char *name) 602{ 603 if (_function_name == DEFAULT_FUNCTION_NAME) 604 _function_name = name; 605} 606 607/* Sets the keyword key name, if not already set. */ 608void 609Options::set_slot_name (const char *name) 610{ 611 if (_slot_name == DEFAULT_SLOT_NAME) 612 _slot_name = name; 613} 614 615/* Sets the struct initializer suffix, if not already set. */ 616void 617Options::set_initializer_suffix (const char *initializers) 618{ 619 if (_initializer_suffix == DEFAULT_INITIALIZER_SUFFIX) 620 _initializer_suffix = initializers; 621} 622 623/* Sets the generated class name, if not already set. */ 624void 625Options::set_class_name (const char *name) 626{ 627 if (_class_name == DEFAULT_CLASS_NAME) 628 _class_name = name; 629} 630 631/* Sets the hash function name, if not already set. */ 632void 633Options::set_hash_name (const char *name) 634{ 635 if (_hash_name == DEFAULT_HASH_NAME) 636 _hash_name = name; 637} 638 639/* Sets the hash table array name, if not already set. */ 640void 641Options::set_wordlist_name (const char *name) 642{ 643 if (_wordlist_name == DEFAULT_WORDLIST_NAME) 644 _wordlist_name = name; 645} 646 647/* Sets the length table array name, if not already set. */ 648void 649Options::set_lengthtable_name (const char *name) 650{ 651 if (_lengthtable_name == DEFAULT_LENGTHTABLE_NAME) 652 _lengthtable_name = name; 653} 654 655/* Sets the string pool name, if not already set. */ 656void 657Options::set_stringpool_name (const char *name) 658{ 659 if (_stringpool_name == DEFAULT_STRINGPOOL_NAME) 660 _stringpool_name = name; 661} 662 663/* Sets the delimiters string, if not already set. */ 664void 665Options::set_delimiters (const char *delimiters) 666{ 667 if (_delimiters == DEFAULT_DELIMITERS) 668 _delimiters = delimiters; 669} 670 671 672/* Parses the command line Options and sets appropriate flags in option_word. */ 673 674static const struct option long_options[] = 675{ 676 { "output-file", required_argument, NULL, CHAR_MAX + 1 }, 677 { "ignore-case", no_argument, NULL, CHAR_MAX + 2 }, 678 { "delimiters", required_argument, NULL, 'e' }, 679 { "struct-type", no_argument, NULL, 't' }, 680 { "language", required_argument, NULL, 'L' }, 681 { "slot-name", required_argument, NULL, 'K' }, 682 { "initializer-suffix", required_argument, NULL, 'F' }, 683 { "hash-fn-name", required_argument, NULL, 'H' }, /* backward compatibility */ 684 { "hash-function-name", required_argument, NULL, 'H' }, 685 { "lookup-fn-name", required_argument, NULL, 'N' }, /* backward compatibility */ 686 { "lookup-function-name", required_argument, NULL, 'N' }, 687 { "class-name", required_argument, NULL, 'Z' }, 688 { "seven-bit", no_argument, NULL, '7' }, 689 { "compare-strncmp", no_argument, NULL, 'c' }, 690 { "readonly-tables", no_argument, NULL, 'C' }, 691 { "enum", no_argument, NULL, 'E' }, 692 { "includes", no_argument, NULL, 'I' }, 693 { "global-table", no_argument, NULL, 'G' }, 694 { "word-array-name", required_argument, NULL, 'W' }, 695 { "length-table-name", required_argument, NULL, CHAR_MAX + 4 }, 696 { "switch", required_argument, NULL, 'S' }, 697 { "omit-struct-type", no_argument, NULL, 'T' }, 698 { "key-positions", required_argument, NULL, 'k' }, 699 { "compare-strlen", no_argument, NULL, 'l' }, /* backward compatibility */ 700 { "compare-lengths", no_argument, NULL, 'l' }, 701 { "duplicates", no_argument, NULL, 'D' }, 702 { "fast", required_argument, NULL, 'f' }, 703 { "initial-asso", required_argument, NULL, 'i' }, 704 { "jump", required_argument, NULL, 'j' }, 705 { "multiple-iterations", required_argument, NULL, 'm' }, 706 { "no-strlen", no_argument, NULL, 'n' }, 707 { "occurrence-sort", no_argument, NULL, 'o' }, 708 { "optimized-collision-resolution", no_argument, NULL, 'O' }, 709 { "pic", no_argument, NULL, 'P' }, 710 { "string-pool-name", required_argument, NULL, 'Q' }, 711 { "null-strings", no_argument, NULL, CHAR_MAX + 3 }, 712 { "random", no_argument, NULL, 'r' }, 713 { "size-multiple", required_argument, NULL, 's' }, 714 { "help", no_argument, NULL, 'h' }, 715 { "version", no_argument, NULL, 'v' }, 716 { "debug", no_argument, NULL, 'd' }, 717 { NULL, no_argument, NULL, 0 } 718}; 719 720void 721Options::parse_options (int argc, char *argv[]) 722{ 723 int option_char; 724 725 program_name = argv[0]; 726 _argument_count = argc; 727 _argument_vector = argv; 728 729 while ((option_char = 730 getopt_long (_argument_count, _argument_vector, 731 "acCdDe:Ef:F:gGhH:i:Ij:k:K:lL:m:nN:oOpPQ:rs:S:tTvW:Z:7", 732 long_options, NULL)) 733 != -1) 734 { 735 switch (option_char) 736 { 737 case 'a': /* Generated code uses the ANSI prototype format. */ 738 break; /* This is now the default. */ 739 case 'c': /* Generate strncmp rather than strcmp. */ 740 { 741 _option_word |= COMP; 742 break; 743 } 744 case 'C': /* Make the generated tables readonly (const). */ 745 { 746 _option_word |= CONST; 747 break; 748 } 749 case 'd': /* Enable debugging option. */ 750 { 751 _option_word |= DEBUG; 752 fprintf (stderr, "Starting program %s, version %s, with debugging on.\n", 753 program_name, version_string); 754 break; 755 } 756 case 'D': /* Enable duplicate option. */ 757 { 758 _option_word |= DUP; 759 break; 760 } 761 case 'e': /* Specify keyword/attribute separator */ 762 { 763 _delimiters = /*getopt*/optarg; 764 break; 765 } 766 case 'E': 767 { 768 _option_word |= ENUM; 769 break; 770 } 771 case 'f': /* Generate the hash table "fast". */ 772 break; /* Not needed any more. */ 773 case 'F': 774 { 775 _initializer_suffix = /*getopt*/optarg; 776 break; 777 } 778 case 'g': /* Use the 'inline' keyword for generated sub-routines, ifdef __GNUC__. */ 779 break; /* This is now the default. */ 780 case 'G': /* Make the keyword table a global variable. */ 781 { 782 _option_word |= GLOBAL; 783 break; 784 } 785 case 'h': /* Displays a list of helpful Options to the user. */ 786 { 787 long_usage (stdout); 788 exit (0); 789 } 790 case 'H': /* Sets the name for the hash function. */ 791 { 792 _hash_name = /*getopt*/optarg; 793 break; 794 } 795 case 'i': /* Sets the initial value for the associated values array. */ 796 { 797 if ((_initial_asso_value = atoi (/*getopt*/optarg)) < 0) 798 fprintf (stderr, "Initial value %d should be non-zero, ignoring and continuing.\n", _initial_asso_value); 799 if (option[RANDOM]) 800 fprintf (stderr, "warning, -r option superceeds -i, ignoring -i option and continuing\n"); 801 break; 802 } 803 case 'I': /* Enable #include statements. */ 804 { 805 _option_word |= INCLUDE; 806 break; 807 } 808 case 'j': /* Sets the jump value, must be odd for later algorithms. */ 809 { 810 if ((_jump = atoi (/*getopt*/optarg)) < 0) 811 { 812 fprintf (stderr, "Jump value %d must be a positive number.\n", _jump); 813 short_usage (stderr); 814 exit (1); 815 } 816 else if (_jump && ((_jump % 2) == 0)) 817 fprintf (stderr, "Jump value %d should be odd, adding 1 and continuing...\n", _jump++); 818 break; 819 } 820 case 'k': /* Sets key positions used for hash function. */ 821 { 822 _option_word |= POSITIONS; 823 const int BAD_VALUE = -3; 824 const int EOS = PositionIterator::EOS; 825 int value; 826 PositionStringParser sparser (/*getopt*/optarg, 1, Positions::MAX_KEY_POS, Positions::LASTCHAR, BAD_VALUE, EOS); 827 828 if (/*getopt*/optarg [0] == '*') /* Use all the characters for hashing!!!! */ 829 _key_positions.set_useall(true); 830 else 831 { 832 _key_positions.set_useall(false); 833 int *key_positions = _key_positions.pointer(); 834 int *key_pos; 835 836 for (key_pos = key_positions; (value = sparser.nextPosition()) != EOS; key_pos++) 837 { 838 if (value == BAD_VALUE) 839 { 840 fprintf (stderr, "Invalid position value or range, use 1,2,3-%d,'$' or '*'.\n", 841 Positions::MAX_KEY_POS); 842 short_usage (stderr); 843 exit (1); 844 } 845 if (key_pos - key_positions == Positions::MAX_SIZE) 846 { 847 /* More than Positions::MAX_SIZE key positions. 848 Since all key positions are in the range 849 0..Positions::MAX_KEY_POS-1 or == Positions::LASTCHAR, 850 there must be duplicates. */ 851 fprintf (stderr, "Duplicate key positions selected\n"); 852 short_usage (stderr); 853 exit (1); 854 } 855 if (value != Positions::LASTCHAR) 856 /* We use 0-based indices in the class Positions. */ 857 value = value - 1; 858 *key_pos = value; 859 } 860 861 unsigned int total_keysig_size = key_pos - key_positions; 862 if (total_keysig_size == 0) 863 { 864 fprintf (stderr, "No key positions selected.\n"); 865 short_usage (stderr); 866 exit (1); 867 } 868 _key_positions.set_size (total_keysig_size); 869 870 /* Sorts the key positions *IN REVERSE ORDER!!* 871 This makes further routines more efficient. Especially 872 when generating code. */ 873 if (! _key_positions.sort()) 874 { 875 fprintf (stderr, "Duplicate key positions selected\n"); 876 short_usage (stderr); 877 exit (1); 878 } 879 } 880 break; 881 } 882 case 'K': /* Make this the keyname for the keyword component field. */ 883 { 884 _slot_name = /*getopt*/optarg; 885 break; 886 } 887 case 'l': /* Create length table to avoid extra string compares. */ 888 { 889 _option_word |= LENTABLE; 890 break; 891 } 892 case 'L': /* Deal with different generated languages. */ 893 { 894 _language = NULL; 895 set_language (/*getopt*/optarg); 896 break; 897 } 898 case 'm': /* Multiple iterations for finding good asso_values. */ 899 { 900 if ((_asso_iterations = atoi (/*getopt*/optarg)) < 0) 901 { 902 fprintf (stderr, "asso_iterations value must not be negative, assuming 0\n"); 903 _asso_iterations = 0; 904 } 905 break; 906 } 907 case 'n': /* Don't include the length when computing hash function. */ 908 { 909 _option_word |= NOLENGTH; 910 break; 911 } 912 case 'N': /* Make generated lookup function name be optarg. */ 913 { 914 _function_name = /*getopt*/optarg; 915 break; 916 } 917 case 'o': /* Order input by frequency of key set occurrence. */ 918 break; /* Not needed any more. */ 919 case 'O': /* Optimized choice during collision resolution. */ 920 break; /* Not needed any more. */ 921 case 'p': /* Generated lookup function a pointer instead of int. */ 922 break; /* This is now the default. */ 923 case 'P': /* Optimize for position-independent code. */ 924 { 925 _option_word |= SHAREDLIB; 926 break; 927 } 928 case 'Q': /* Sets the name for the string pool. */ 929 { 930 _stringpool_name = /*getopt*/optarg; 931 break; 932 } 933 case 'r': /* Utilize randomness to initialize the associated values table. */ 934 { 935 _option_word |= RANDOM; 936 if (_initial_asso_value != 0) 937 fprintf (stderr, "warning, -r option supersedes -i, disabling -i option and continuing\n"); 938 break; 939 } 940 case 's': /* Range of associated values, determines size of final table. */ 941 { 942 float numerator; 943 float denominator = 1; 944 bool invalid = false; 945 char *endptr; 946 947 numerator = strtod (/*getopt*/optarg, &endptr); 948 if (endptr == /*getopt*/optarg) 949 invalid = true; 950 else if (*endptr != '\0') 951 { 952 if (*endptr == '/') 953 { 954 char *denomptr = endptr + 1; 955 denominator = strtod (denomptr, &endptr); 956 if (endptr == denomptr || *endptr != '\0') 957 invalid = true; 958 } 959 else 960 invalid = true; 961 } 962 if (invalid) 963 { 964 fprintf (stderr, "Invalid value for option -s.\n"); 965 short_usage (stderr); 966 exit (1); 967 } 968 _size_multiple = numerator / denominator; 969 /* Backward compatibility: -3 means 1/3. */ 970 if (_size_multiple < 0) 971 _size_multiple = 1 / (-_size_multiple); 972 /* Catch stupid users. */ 973 if (_size_multiple == 0) 974 _size_multiple = 1; 975 /* Warnings. */ 976 if (_size_multiple > 50) 977 fprintf (stderr, "Size multiple %g is excessive, did you really mean this?! (try '%s --help' for help)\n", _size_multiple, program_name); 978 else if (_size_multiple < 0.01f) 979 fprintf (stderr, "Size multiple %g is extremely small, did you really mean this?! (try '%s --help' for help)\n", _size_multiple, program_name); 980 break; 981 } 982 case 'S': /* Generate switch statement output, rather than lookup table. */ 983 { 984 _option_word |= SWITCH; 985 _total_switches = atoi (/*getopt*/optarg); 986 if (_total_switches <= 0) 987 { 988 fprintf (stderr, "number of switches %s must be a positive number\n", /*getopt*/optarg); 989 short_usage (stderr); 990 exit (1); 991 } 992 break; 993 } 994 case 't': /* Enable the TYPE mode, allowing arbitrary user structures. */ 995 { 996 _option_word |= TYPE; 997 break; 998 } 999 case 'T': /* Don't print structure definition. */ 1000 { 1001 _option_word |= NOTYPE; 1002 break; 1003 } 1004 case 'v': /* Print out the version and quit. */ 1005 fprintf (stdout, "GNU gperf %s\n", version_string); 1006 fprintf (stdout, "Copyright (C) %s Free Software Foundation, Inc.\n\ 1007This is free software; see the source for copying conditions. There is NO\n\ 1008warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ 1009", 1010 "1989-1998, 2000-2004, 2006-2007"); 1011 fprintf (stdout, "Written by %s and %s.\n", 1012 "Douglas C. Schmidt", "Bruno Haible"); 1013 exit (0); 1014 case 'W': /* Sets the name for the hash table array. */ 1015 { 1016 _wordlist_name = /*getopt*/optarg; 1017 break; 1018 } 1019 case 'Z': /* Set the class name. */ 1020 { 1021 _class_name = /*getopt*/optarg; 1022 break; 1023 } 1024 case '7': /* Assume 7-bit characters. */ 1025 { 1026 _option_word |= SEVENBIT; 1027 break; 1028 } 1029 case CHAR_MAX + 1: /* Set the output file name. */ 1030 { 1031 _output_file_name = /*getopt*/optarg; 1032 break; 1033 } 1034 case CHAR_MAX + 2: /* Case insignificant. */ 1035 { 1036 _option_word |= UPPERLOWER; 1037 break; 1038 } 1039 case CHAR_MAX + 3: /* Use NULL instead of "". */ 1040 { 1041 _option_word |= NULLSTRINGS; 1042 break; 1043 } 1044 case CHAR_MAX + 4: /* Sets the name for the length table array. */ 1045 { 1046 _lengthtable_name = /*getopt*/optarg; 1047 break; 1048 } 1049 default: 1050 short_usage (stderr); 1051 exit (1); 1052 } 1053 1054 } 1055 1056 if (/*getopt*/optind < argc) 1057 _input_file_name = argv[/*getopt*/optind++]; 1058 1059 if (/*getopt*/optind < argc) 1060 { 1061 fprintf (stderr, "Extra trailing arguments to %s.\n", program_name); 1062 short_usage (stderr); 1063 exit (1); 1064 } 1065} 1066 1067/* ------------------------------------------------------------------------- */ 1068 1069#ifndef __OPTIMIZE__ 1070 1071#define INLINE /* not inline */ 1072#include "options.icc" 1073#undef INLINE 1074 1075#endif /* not defined __OPTIMIZE__ */ 1076