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