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