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. */
35 Options option;
36
37 /* Records the program name. */
38 const char *program_name;
39
40 /* Size to jump on a collision. */
41 static const int DEFAULT_JUMP_VALUE = 5;
42
43 /* Default name for generated lookup function. */
44 static const char *const DEFAULT_FUNCTION_NAME = "in_word_set";
45
46 /* Default name for the key component. */
47 static const char *const DEFAULT_SLOT_NAME = "name";
48
49 /* Default struct initializer suffix. */
50 static const char *const DEFAULT_INITIALIZER_SUFFIX = "";
51
52 /* Default name for the generated class. */
53 static const char *const DEFAULT_CLASS_NAME = "Perfect_Hash";
54
55 /* Default name for generated hash function. */
56 static const char *const DEFAULT_HASH_NAME = "hash";
57
58 /* Default name for generated hash table array. */
59 static const char *const DEFAULT_WORDLIST_NAME = "wordlist";
60
61 /* Default name for generated length table array. */
62 static const char *const DEFAULT_LENGTHTABLE_NAME = "lengthtable";
63
64 /* Default name for string pool. */
65 static const char *const DEFAULT_STRINGPOOL_NAME = "stringpool";
66
67 /* Default delimiters that separate keywords from their attributes. */
68 static const char *const DEFAULT_DELIMITERS = ",";
69
70 /* Prints program usage to given stream. */
71
72 void
short_usage(FILE * stream)73 Options::short_usage (FILE * stream)
74 {
75 fprintf (stream,
76 "Try '%s --help' for more information.\n", program_name);
77 }
78
79 void
long_usage(FILE * stream)80 Options::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
270 void
print_options() const271 Options::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
344 class PositionStringParser
345 {
346 public:
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 ();
353 private:
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. */
PositionStringParser(const char * str,int low_bound,int high_bound,int end_word_marker,int error_value,int end_marker)373 PositionStringParser::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. */
387 int
nextPosition()388 PositionStringParser::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
Options()454 Options::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
~Options()479 Options::~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. */
564 void
set_language(const char * language)565 Options::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. */
589 void
set_total_switches(int total_switches)590 Options::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. */
600 void
set_function_name(const char * name)601 Options::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. */
608 void
set_slot_name(const char * name)609 Options::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. */
616 void
set_initializer_suffix(const char * initializers)617 Options::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. */
624 void
set_class_name(const char * name)625 Options::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. */
632 void
set_hash_name(const char * name)633 Options::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. */
640 void
set_wordlist_name(const char * name)641 Options::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. */
648 void
set_lengthtable_name(const char * name)649 Options::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. */
656 void
set_stringpool_name(const char * name)657 Options::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. */
664 void
set_delimiters(const char * delimiters)665 Options::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
674 static 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
720 void
parse_options(int argc,char * argv[])721 Options::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\
1007 This is free software; see the source for copying conditions. There is NO\n\
1008 warranty; 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