1 #ifndef GPERF_OPTIONS_C
2 #define GPERF_OPTIONS_C
13 #include "positions.h"
14 /*------------------------------------------------------------------------------------------------*/
15 #include "namespace/globals.h"
16 #include "namespace/options.h"
17 #include "namespace/positions.h"
18 /*------------------------------------------------------------------------------------------------*/
20 /* default struct initializer suffix */
21 static u8
*DEFAULT_INITIALIZER_SUFFIX
= "";
22 /* default name for the key component */
23 static u8
*DEFAULT_SLOT_NAME
= "name";
24 /* default delimiters that separate keywords from their attributes */
25 static u8
*DEFAULT_DELIMITERS
= ",";
26 /* default name for generated hash function */
27 static u8
*DEFAULT_HASH_NAME
= "hash";
28 /* default name for generated lookup function */
29 static u8
*DEFAULT_FUNCTION_NAME
= "in_word_set";
30 /* default name for the generated class */
31 static u8
*DEFAULT_CLASS_NAME
= "Perfect_Hash";
32 /* default name for string pool */
33 static u8
*DEFAULT_STRINGPOOL_NAME
= "stringpool";
34 /* default prefix for constants */
35 static u8
*DEFAULT_CONSTANTS_PREFIX
= "";
36 /* default name for generated hash table array */
37 static u8
*DEFAULT_WORDLIST_NAME
= "wordlist";
38 /* default name for generated length table array */
39 static u8
*DEFAULT_LENGTHTABLE_NAME
= "lengthtable";
40 /*}}} default -- END */
42 static struct Options
*opts_new(void)
46 t
= calloc(1, sizeof(*t
));
47 t
->option_word
= OPTS_ANSIC
;
48 t
->jump
= OPTS_DEFAULT_JUMP_VALUE
;
49 t
->total_switches
= 1;
51 t
->function_name
= DEFAULT_FUNCTION_NAME
;
52 t
->slot_name
= DEFAULT_SLOT_NAME
;
53 t
->initializer_suffix
= DEFAULT_INITIALIZER_SUFFIX
;
54 t
->class_name
= DEFAULT_CLASS_NAME
;
55 t
->hash_name
= DEFAULT_HASH_NAME
;
56 t
->wordlist_name
= DEFAULT_WORDLIST_NAME
;
57 t
->lengthtable_name
= DEFAULT_LENGTHTABLE_NAME
;
58 t
->stringpool_name
= DEFAULT_STRINGPOOL_NAME
;
59 t
->constants_prefix
= DEFAULT_CONSTANTS_PREFIX
;
60 t
->delimiters
= DEFAULT_DELIMITERS
;
61 t
->key_positions
= pos_new();
65 static void opts_del(struct Options
*t
)
68 struct PositionIterator
*iter
;
71 fprintf(stderr
, "\ndumping Options:"
72 "\nTYPE is........: %s"
73 "\nUPPERLOWER is..: %s"
74 "\nKRC is.........: %s"
75 "\nC is...........: %s"
76 "\nANSIC is.......: %s"
77 "\nCPLUSPLUS is...: %s"
78 "\nSEVENBIT is....: %s"
79 "\nLENTABLE is....: %s"
80 "\nCOMP is........: %s"
81 "\nCONST is.......: %s"
82 "\nENUM is........: %s"
83 "\nINCLUDE is.....: %s"
84 "\nGLOBAL is......: %s"
85 "\nNULLSTRINGS is.: %s"
86 "\nSHAREDLIB is...: %s"
87 "\nSWITCH is......: %s"
88 "\nNOTYPE is......: %s"
89 "\nDUP is.........: %s"
90 "\nNOLENGTH is....: %s"
91 "\nRANDOM is......: %s"
92 "\nDEBUG is.......: %s"
93 "\nlookup function name = %s"
94 "\nhash function name = %s"
95 "\nword list name = %s"
96 "\nlength table name = %s"
97 "\nstring pool name = %s"
99 "\ninitializer suffix = %s"
100 "\nasso_values iterations = %d"
102 "\nhash table size multiplier = %g"
103 "\ninitial associated value = %d"
105 "\nnumber of switch statements = %d\n",
106 OPTS(TYPE
) ? "enabled" : "disabled",
107 OPTS(UPPERLOWER
) ? "enabled" : "disabled",
108 OPTS(KRC
) ? "enabled" : "disabled",
109 OPTS(C
) ? "enabled" : "disabled",
110 OPTS(ANSIC
) ? "enabled" : "disabled",
111 OPTS(CPLUSPLUS
) ? "enabled" : "disabled",
112 OPTS(SEVENBIT
) ? "enabled" : "disabled",
113 OPTS(LENTABLE
) ? "enabled" : "disabled",
114 OPTS(COMP
) ? "enabled" : "disabled",
115 OPTS(CONST
) ? "enabled" : "disabled",
116 OPTS(ENUM
) ? "enabled" : "disabled",
117 OPTS(INCLUDE
) ? "enabled" : "disabled",
118 OPTS(GLOBAL
) ? "enabled" : "disabled",
119 OPTS(NULLSTRINGS
) ? "enabled" : "disabled",
120 OPTS(SHAREDLIB
) ? "enabled" : "disabled",
121 OPTS(SWITCH
) ? "enabled" : "disabled",
122 OPTS(NOTYPE
) ? "enabled" : "disabled",
123 OPTS(DUP
) ? "enabled" : "disabled",
124 OPTS(NOLENGTH
) ? "enabled" : "disabled",
125 OPTS(RANDOM
) ? "enabled" : "disabled",
126 OPTS(DEBUG
) ? "enabled" : "disabled",
127 t
->function_name
, t
->hash_name
, t
->wordlist_name
, t
->lengthtable_name
,
128 t
->stringpool_name
, t
->slot_name
, t
->initializer_suffix
,
129 t
->asso_iterations
, t
->jump
, t
->size_multiple
, t
->initial_asso_value
,
130 t
->delimiters
, t
->total_switches
);
131 if (t
->key_positions
->useall
)
132 fprintf(stderr
, "all characters are used in the hash function\n");
134 fprintf(stderr
, "maximum keysig size = %d\nkey positions are: \n", t
->key_positions
->size
);
135 iter
= pos_iterator_all(t
->key_positions
);
137 pos
= positer_next(iter
);
138 if (pos
== POSITER_EOS
)
140 if (pos
== POS_LASTCHAR
)
141 fprintf(stderr
, "$\n");
143 fprintf(stderr
, "%d\n", pos
+ 1);
147 fprintf (stderr
, "finished dumping Options\n");
149 pos_del(t
->key_positions
);
152 /*{{{ opts_long_options
153 Parses the command line Options and sets appropriate flags in option_word. */
154 static const struct option opts_long_options
[] =
156 { "output-file", required_argument
, NULL
, CHAR_MAX
+ 1 },
157 { "ignore-case", no_argument
, NULL
, CHAR_MAX
+ 2 },
158 { "delimiters", required_argument
, NULL
, 'e' },
159 { "struct-type", no_argument
, NULL
, 't' },
160 { "language", required_argument
, NULL
, 'L' },
161 { "slot-name", required_argument
, NULL
, 'K' },
162 { "initializer-suffix", required_argument
, NULL
, 'F' },
163 { "hash-fn-name", required_argument
, NULL
, 'H' }, /* backward compatibility */
164 { "hash-function-name", required_argument
, NULL
, 'H' },
165 { "lookup-fn-name", required_argument
, NULL
, 'N' }, /* backward compatibility */
166 { "lookup-function-name", required_argument
, NULL
, 'N' },
167 { "class-name", required_argument
, NULL
, 'Z' },
168 { "seven-bit", no_argument
, NULL
, '7' },
169 { "compare-strncmp", no_argument
, NULL
, 'c' },
170 { "readonly-tables", no_argument
, NULL
, 'C' },
171 { "enum", no_argument
, NULL
, 'E' },
172 { "includes", no_argument
, NULL
, 'I' },
173 { "global-table", no_argument
, NULL
, 'G' },
174 { "constants-prefix", required_argument
, NULL
, CHAR_MAX
+ 5 },
175 { "word-array-name", required_argument
, NULL
, 'W' },
176 { "length-table-name", required_argument
, NULL
, CHAR_MAX
+ 4 },
177 { "switch", required_argument
, NULL
, 'S' },
178 { "omit-struct-type", no_argument
, NULL
, 'T' },
179 { "key-positions", required_argument
, NULL
, 'k' },
180 { "compare-strlen", no_argument
, NULL
, 'l' }, /* backward compatibility */
181 { "compare-lengths", no_argument
, NULL
, 'l' },
182 { "duplicates", no_argument
, NULL
, 'D' },
183 { "fast", required_argument
, NULL
, 'f' },
184 { "initial-asso", required_argument
, NULL
, 'i' },
185 { "jump", required_argument
, NULL
, 'j' },
186 { "multiple-iterations", required_argument
, NULL
, 'm' },
187 { "no-strlen", no_argument
, NULL
, 'n' },
188 { "occurrence-sort", no_argument
, NULL
, 'o' },
189 { "optimized-collision-resolution", no_argument
, NULL
, 'O' },
190 { "pic", no_argument
, NULL
, 'P' },
191 { "string-pool-name", required_argument
, NULL
, 'Q' },
192 { "null-strings", no_argument
, NULL
, CHAR_MAX
+ 3 },
193 { "random", no_argument
, NULL
, 'r' },
194 { "size-multiple", required_argument
, NULL
, 's' },
195 { "help", no_argument
, NULL
, 'h' },
196 { "version", no_argument
, NULL
, 'v' },
197 { "debug", no_argument
, NULL
, 'd' },
198 { NULL
, no_argument
, NULL
, 0 }
200 /*{{{ opts_parse_options */
201 static void opts_parse_options(struct Options
*t
, u32 argc
, u8
**argv
)
203 opts_program_name
= (u8
*)argv
[0];
204 t
->argument_count
= argc
;
205 t
->argument_vector
= argv
;
210 option_char
= getopt_long(t
->argument_count
, t
->argument_vector
,
211 "acCdDe:Ef:F:gGhH:i:Ij:k:K:lL:m:nN:oOpPQ:rs:S:tTvW:Z:7", opts_long_options
,
213 if (option_char
== -1)
215 switch (option_char
) {
216 case 'a': /* generated code uses the ANSI prototype format */
217 break; /* This is now the default */
218 case 'c': /* generate strncmp rather than strcmp */
219 t
->option_word
|= OPTS_COMP
;
221 case 'C': /* make the generated tables readonly (const) */
222 t
->option_word
|= OPTS_CONST
;
224 case 'd': /* enable debugging option */
225 t
->option_word
|= OPTS_DEBUG
;
226 fprintf(stderr
, "Starting program %s, version %s, with debugging on.\n", opts_program_name
, cgperf_version_string
);
228 case 'D': /* enable duplicate option */
229 t
->option_word
|= OPTS_DUP
;
231 case 'e': /* specify keyword/attribute separator */
232 t
->delimiters
= /*getopt*/(u8
*)optarg
;
235 t
->option_word
|= OPTS_ENUM
;
237 case 'f': /* generate the hash table "fast" */
238 break; /* Not needed any more */
240 t
->initializer_suffix
= /*getopt*/(u8
*)optarg
;
242 case 'g': /* use the 'inline' keyword for generated sub-routines, ifdef __GNUC__ */
243 break; /* This is now the default */
244 case 'G': /* make the keyword table a global variable */
245 t
->option_word
|= OPTS_GLOBAL
;
247 case 'h': /* displays a list of helpful Options to the user */
248 opts_long_usage(stdout
);
250 case 'H': /* sets the name for the hash function */
251 t
->hash_name
= /*getopt*/(u8
*)optarg
;
253 case 'i': /* sets the initial value for the associated values array */
254 t
->initial_asso_value
= atoi(/*getopt*/optarg
);
255 if (t
->initial_asso_value
< 0)
256 fprintf(stderr
, "Initial value %d should be non-zero, ignoring and continuing.\n", t
->initial_asso_value
);
258 fprintf(stderr
, "warning, -r option superceeds -i, ignoring -i option and continuing\n");
260 case 'I': /* enable #include statements */
261 t
->option_word
|= OPTS_INCLUDE
;
263 case 'j': /* sets the jump value, must be odd for later algorithms */
264 t
->jump
= atoi (/*getopt*/optarg
);
266 fprintf(stderr
, "Jump value %d must be a positive number.\n", t
->jump
);
267 opts_short_usage(stderr
);
269 } else if ((t
->jump
!= 0) && ((t
->jump
% 2) == 0))
270 fprintf (stderr
, "Jump value %d should be odd, adding 1 and continuing...\n", t
->jump
++);
272 case 'k': { /* sets key positions used for hash function */
273 t
->option_word
|= OPTS_POSITIONS
;
275 s32 EOS
= POSITER_EOS
;
277 struct PositionStringParser
*sparser
;
279 sparser
= posstrp_new(/*getopt*/(u8
*)optarg
, 1,
280 POS_MAX_KEY_POS
, POS_LASTCHAR
, BAD_VALUE
, EOS
);
282 if (/*getopt*/optarg
[0] == '*') /* use all the characters for hashing!!!! */
283 pos_set_useall(t
->key_positions
, true);
287 u32 total_keysig_size
;
289 pos_set_useall(t
->key_positions
, false);
290 key_positions
= t
->key_positions
->positions
;
292 key_pos
= key_positions
;
294 value
= posstrp_nextPosition(sparser
);
297 if (value
== BAD_VALUE
) {
298 fprintf(stderr
, "Invalid position value or range, use 1,2,3-%d,'$' or '*'.\n", POS_MAX_KEY_POS
);
299 opts_short_usage(stderr
);
302 if ((key_pos
- key_positions
) == POS_MAX_SIZE
) {
304 * More than Positions_max_size key positions.
305 * Since all key positions are in the range
306 * 0..Positions_max_key_pos-1 or == Positions_lastchar,
307 * there must be duplicates.
309 fprintf(stderr
, "Duplicate key positions selected\n");
310 opts_short_usage(stderr
);
313 if (value
!= POS_LASTCHAR
)
314 /* We use 0-based indices in the class Positions */
319 total_keysig_size
= key_pos
- key_positions
;
320 if (total_keysig_size
== 0) {
321 fprintf(stderr
, "No key positions selected.\n");
322 opts_short_usage(stderr
);
325 t
->key_positions
->size
= total_keysig_size
;
327 * Sorts the key positions *IN REVERSE ORDER!!*
328 * This makes further routines more efficient.
329 * Especially when generating code.
331 if (!pos_sort(t
->key_positions
)) {
332 fprintf(stderr
, "Duplicate key positions selected\n");
333 opts_short_usage(stderr
);
338 case 'K':/* make this the keyname for the keyword component field */
339 t
->slot_name
= /*getopt*/optarg
;
341 case 'l':/* create length table to avoid extra string compares */
342 t
->option_word
|= OPTS_LENTABLE
;
344 case 'L':/* deal with different generated languages */
346 opts_set_language(t
,/*getopt*/optarg
);
348 case 'm':/* multiple iterations for finding good asso_values */
349 t
->asso_iterations
= atoi(/*getopt*/optarg
);
350 if (t
->asso_iterations
< 0) {
351 fprintf(stderr
, "asso_iterations value must not be negative, assuming 0\n");
352 t
->asso_iterations
= 0;
355 case 'n':/* don't include the length when computing hash function */
356 t
->option_word
|= OPTS_NOLENGTH
;
358 case 'N':/* make generated lookup function name be optarg */
359 t
->function_name
= /*getopt*/optarg
;
361 case 'o':/* order input by frequency of key set occurrence */
362 break; /* not needed any more */
363 case 'O':/* optimized choice during collision resolution */
364 break; /* not needed any more */
365 case 'p':/* generated lookup function a pointer instead of int */
366 break; /* this is now the default */
367 case 'P':/* optimize for position-independent code */
368 t
->option_word
|= OPTS_SHAREDLIB
;
370 case 'Q':/* sets the name for the string pool */
371 t
->stringpool_name
= /*getopt*/optarg
;
373 case 'r':/* utilize randomness to initialize the associated values table */
374 t
->option_word
|= OPTS_RANDOM
;
375 if (t
->initial_asso_value
!= 0)
376 fprintf(stderr
, "warning, -r option supersedes -i, disabling -i option and continuing\n");
378 case 's':{/* range of associated values, determines size of final table */
386 numerator
= strtod(/*getopt*/optarg
, &endptr
);
387 if (endptr
== /*getopt*/(u8
*)optarg
)
389 else if (*endptr
!= '\0') {
390 if (*endptr
== '/') {
393 denomptr
= endptr
+ 1;
394 denominator
= strtod(denomptr
, &endptr
);
395 if (endptr
== denomptr
|| *endptr
!= '\0')
401 fprintf(stderr
, "Invalid value for option -s.\n");
402 opts_short_usage(stderr
);
405 t
->size_multiple
= numerator
/ denominator
;
406 /* backward compatibility: -3 means 1/3 */
407 if (t
->size_multiple
< 0)
408 t
->size_multiple
= 1 / (-t
->size_multiple
);
409 /* catch stupid users and port to C the c++ from stupid coders */
410 if (t
->size_multiple
== 0)
411 t
->size_multiple
= 1;
413 if (t
->size_multiple
> 50)
414 fprintf(stderr
, "Size multiple %g is excessive, did you really mean this?! (try '%s --help' for help)\n", t
->size_multiple
, opts_program_name
);
415 else if (t
->size_multiple
< 0.01f
)
416 fprintf(stderr
, "Size multiple %g is extremely small, did you really mean this?! (try '%s --help' for help)\n", t
->size_multiple
, opts_program_name
);
418 case 'S':/* generate switch statement output, rather than lookup table */
419 t
->option_word
|= OPTS_SWITCH
;
420 t
->total_switches
= atoi(/*getopt*/optarg
);
421 if (t
->total_switches
<= 0) {
422 fprintf(stderr
, "number of switches %s must be a positive number\n", /*getopt*/optarg
);
423 opts_short_usage (stderr
);
427 case 't':/* enable the TYPE mode, allowing arbitrary user structures */
428 t
->option_word
|= OPTS_TYPE
;
430 case 'T':/* don't print structure definition */
431 t
->option_word
|= OPTS_NOTYPE
;
433 case 'v':/* print out the version and quit */
434 fprintf(stdout
, "GNU gperf %s\n", cgperf_version_string
);
435 fprintf(stdout
, "Copyright (C) %s Free Software Foundation, Inc.\n\
436 License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>\n\
437 This is free software: you are free to change and redistribute it.\n\
438 There is NO WARRANTY, to the extent permitted by law.\n\
441 fprintf(stdout
, "Written by %s and %s. C89 with benign bits of C99/C11 port by Sylvain BERTRAND\n", "Douglas C. Schmidt", "Bruno Haible");
443 case 'W':/* sets the name for the hash table array */
444 t
->wordlist_name
= /*getopt*/optarg
;
446 case 'Z':/* set the class name */
447 t
->class_name
= /*getopt*/optarg
;
449 case '7':/* assume 7-bit characters */
450 t
->option_word
|= OPTS_SEVENBIT
;
452 case CHAR_MAX
+ 1:/* set the output file name */
453 t
->output_file_name
= /*getopt*/optarg
;
455 case CHAR_MAX
+ 2:/* case insignificant */
456 t
->option_word
|= OPTS_UPPERLOWER
;
458 case CHAR_MAX
+ 3:/* use NULL instead of "" */
459 t
->option_word
|= OPTS_NULLSTRINGS
;
461 case CHAR_MAX
+ 4:/* sets the name for the length table array */
462 t
->lengthtable_name
= /*getopt*/optarg
;
464 case CHAR_MAX
+ 5:/* sets the prefix for the constants */
465 t
->constants_prefix
= /*getopt*/optarg
;
468 opts_short_usage(stderr
);
472 if (/*getopt*/optind
< argc
)
473 t
->input_file_name
= argv
[/*getopt*/optind
++];
475 if (/*getopt*/optind
< argc
) {
476 fprintf(stderr
, "Extra trailing arguments to %s.\n", opts_program_name
);
477 opts_short_usage(stderr
);
481 /*{{{ opts_short_usage */
482 static void opts_short_usage(FILE * stream
)
484 fprintf(stream
, "Try '%s --help' for more information.\n", opts_program_name
);
486 /*{{{ opts_long_usage */
487 static void opts_long_usage(FILE * stream
)
490 "GNU 'gperf' generates perfect hash functions.\n");
491 fprintf(stream
, "\n");
493 "Usage: %s [OPTION]... [INPUT-FILE]\n",
495 fprintf(stream
, "\n");
497 "If a long option shows an argument as mandatory, then it is mandatory\n"
498 "for the equivalent short option also.\n");
499 fprintf(stream
, "\n");
501 "Output file location:\n");
503 " --output-file=FILE Write output to specified file.\n");
505 "The results are written to standard output if no output file is specified\n"
507 fprintf(stream
, "\n");
509 "Input file interpretation:\n");
511 " -e, --delimiters=DELIMITER-LIST\n"
512 " Allow user to provide a string containing delimiters\n"
513 " used to separate keywords from their attributes.\n"
514 " Default is \",\".\n");
516 " -t, --struct-type Allows the user to include a structured type\n"
517 " declaration for generated code. Any text before %%%%\n"
518 " is considered part of the type declaration. Key\n"
519 " words and additional fields may follow this, one\n"
520 " group of fields per line.\n");
522 " --ignore-case Consider upper and lower case ASCII characters as\n"
523 " equivalent. Note that locale dependent case mappings\n"
525 fprintf(stream
, "\n");
527 "Language for the output code:\n");
529 " -L, --language=LANGUAGE-NAME\n"
530 " Generates code in the specified language. Languages\n"
531 " handled are currently C++, ANSI-C, C, and KR-C. The\n"
532 " default is ANSI-C.\n");
533 fprintf(stream
, "\n");
535 "Details in the output code:\n");
537 " -K, --slot-name=NAME Select name of the keyword component in the keyword\n"
540 " -F, --initializer-suffix=INITIALIZERS\n"
541 " Initializers for additional components in the keyword\n"
544 " -H, --hash-function-name=NAME\n"
545 " Specify name of generated hash function. Default is\n"
548 " -N, --lookup-function-name=NAME\n"
549 " Specify name of generated lookup function. Default\n"
550 " name is 'in_word_set'.\n");
552 " -Z, --class-name=NAME Specify name of generated C++ class. Default name is\n"
553 " 'Perfect_Hash'.\n");
555 " -7, --seven-bit Assume 7-bit characters.\n");
557 " -l, --compare-lengths Compare key lengths before trying a string\n"
558 " comparison. This is necessary if the keywords\n"
559 " contain NUL bytes. It also helps cut down on the\n"
560 " number of string comparisons made during the lookup.\n");
562 " -c, --compare-strncmp Generate comparison code using strncmp rather than\n"
565 " -C, --readonly-tables Make the contents of generated lookup tables\n"
566 " constant, i.e., readonly.\n");
568 " -E, --enum Define constant values using an enum local to the\n"
569 " lookup function rather than with defines.\n");
571 " -I, --includes Include the necessary system include file <string.h>\n"
572 " at the beginning of the code.\n");
574 " -G, --global-table Generate the static table of keywords as a static\n"
575 " global variable, rather than hiding it inside of the\n"
576 " lookup function (which is the default behavior).\n");
578 " -P, --pic Optimize the generated table for inclusion in shared\n"
579 " libraries. This reduces the startup time of programs\n"
580 " using a shared library containing the generated code.\n");
582 " -Q, --string-pool-name=NAME\n"
583 " Specify name of string pool generated by option --pic.\n"
584 " Default name is 'stringpool'.\n");
586 " --null-strings Use NULL strings instead of empty strings for empty\n"
587 " keyword table entries.\n");
589 " --constants-prefix=PREFIX\n"
590 " Specify prefix for the constants like TOTAL_KEYWORDS.\n");
592 " -W, --word-array-name=NAME\n"
593 " Specify name of word list array. Default name is\n"
596 " --length-table-name=NAME\n"
597 " Specify name of length table array. Default name is\n"
598 " 'lengthtable'.\n");
600 " -S, --switch=COUNT Causes the generated C code to use a switch\n"
601 " statement scheme, rather than an array lookup table.\n"
602 " This can lead to a reduction in both time and space\n"
603 " requirements for some keyfiles. The COUNT argument\n"
604 " determines how many switch statements are generated.\n"
605 " A value of 1 generates 1 switch containing all the\n"
606 " elements, a value of 2 generates 2 tables with 1/2\n"
607 " the elements in each table, etc. If COUNT is very\n"
608 " large, say 1000000, the generated C code does a\n"
609 " binary search.\n");
611 " -T, --omit-struct-type\n"
612 " Prevents the transfer of the type declaration to the\n"
613 " output file. Use this option if the type is already\n"
614 " defined elsewhere.\n");
615 fprintf(stream
, "\n");
617 "Algorithm employed by gperf:\n");
619 " -k, --key-positions=KEYS\n"
620 " Select the key positions used in the hash function.\n"
621 " The allowable choices range between 1-%d, inclusive.\n"
622 " The positions are separated by commas, ranges may be\n"
623 " used, and key positions may occur in any order.\n"
624 " Also, the meta-character '*' causes the generated\n"
625 " hash function to consider ALL key positions, and $\n"
626 " indicates the \"final character\" of a key, e.g.,\n"
630 " -D, --duplicates Handle keywords that hash to duplicate values. This\n"
631 " is useful for certain highly redundant keyword sets.\n");
633 " -m, --multiple-iterations=ITERATIONS\n"
634 " Perform multiple choices of the -i and -j values,\n"
635 " and choose the best results. This increases the\n"
636 " running time by a factor of ITERATIONS but does a\n"
637 " good job minimizing the generated table size.\n");
639 " -i, --initial-asso=N Provide an initial value for the associate values\n"
640 " array. Default is 0. Setting this value larger helps\n"
641 " inflate the size of the final table.\n");
643 " -j, --jump=JUMP-VALUE Affects the \"jump value\", i.e., how far to advance\n"
644 " the associated character value upon collisions. Must\n"
645 " be an odd number, default is %d.\n",
646 OPTS_DEFAULT_JUMP_VALUE
);
648 " -n, --no-strlen Do not include the length of the keyword when\n"
649 " computing the hash function.\n");
651 " -r, --random Utilizes randomness to initialize the associated\n"
654 " -s, --size-multiple=N Affects the size of the generated hash table. The\n"
655 " numeric argument N indicates \"how many times larger\n"
656 " or smaller\" the associated value range should be,\n"
657 " in relationship to the number of keys, e.g. a value\n"
658 " of 3 means \"allow the maximum associated value to\n"
659 " be about 3 times larger than the number of input\n"
660 " keys\". Conversely, a value of 1/3 means \"make the\n"
661 " maximum associated value about 3 times smaller than\n"
662 " the number of input keys\". A larger table should\n"
663 " decrease the time required for an unsuccessful\n"
664 " search, at the expense of extra table space. Default\n"
666 fprintf(stream
, "\n");
668 "Informative output:\n"
669 " -h, --help Print this message.\n"
670 " -v, --version Print the gperf version number.\n"
671 " -d, --debug Enables the debugging option (produces verbose\n"
672 " output to the standard error).\n");
673 fprintf(stream
, "\n");
675 "Report bugs to <bug-gperf@gnu.org>.\n");
677 /*{{{ opts_set_language */
678 /* Sets the output language, if not already set */
679 void opts_set_language(struct Options
*t
, u8
*language
)
681 if (t
->language
!= 0)
683 t
->language
= language
;
684 t
->option_word
&= ~(OPTS_KRC
| OPTS_C
| OPTS_ANSIC
| OPTS_CPLUSPLUS
);
685 if (strcmp(language
, "KR-C") == 0)
686 t
->option_word
|= OPTS_KRC
;
687 else if (strcmp (language
, "C") == 0)
688 t
->option_word
|= OPTS_C
;
689 else if (strcmp (language
, "ANSI-C") == 0)
690 t
->option_word
|= OPTS_ANSIC
;
691 else if (strcmp (language
, "C++") == 0)
692 t
->option_word
|= OPTS_CPLUSPLUS
;
694 fprintf(stderr
, "unsupported language option %s, defaulting to ANSI-C\n", language
);
695 t
->option_word
|= OPTS_ANSIC
;
698 /*{{{ opts_set_delimiters */
699 /* Sets the delimiters string, if not already set. */
700 static void opts_set_delimiters(struct Options
*t
, u8
*delimiters
)
702 if (t
->delimiters
== DEFAULT_DELIMITERS
)
703 t
->delimiters
= delimiters
;
705 /*{{{ opts_set_slot_name */
706 /* sets the keyword key name, if not already set */
707 static void opts_set_slot_name(struct Options
*t
, u8
*name
)
709 if (t
->slot_name
== DEFAULT_SLOT_NAME
)
712 /*{{{ opts_set_initializer_suffix */
713 /* sets the struct initializer suffix, if not already set */
714 static void opts_set_initializer_suffix(struct Options
*t
, u8
*initializers
)
716 if (t
->initializer_suffix
== DEFAULT_INITIALIZER_SUFFIX
)
717 t
->initializer_suffix
= initializers
;
719 /*{{{ opts_set_hash_name */
720 /* sets the hash function name, if not already set */
721 static void opts_set_hash_name(struct Options
*t
, u8
*name
)
723 if (t
->hash_name
== DEFAULT_HASH_NAME
)
726 /*{{{ opts_set_function_name */
727 /* sets the generated function name, if not already set */
728 static void opts_set_function_name(struct Options
*t
, u8
*name
)
730 if (t
->function_name
== DEFAULT_FUNCTION_NAME
)
731 t
->function_name
= name
;
733 /*{{{ opts_set_class_name */
734 /* sets the generated class name, if not already set */
735 static void opts_set_class_name(struct Options
*t
, u8
*name
)
737 if (t
->class_name
== DEFAULT_CLASS_NAME
)
738 t
->class_name
= name
;
740 /*{{{ opts_set_stringpool_name */
741 /* sets the string pool name, if not already set */
742 static void opts_set_stringpool_name(struct Options
*t
, u8
*name
)
744 if (t
->stringpool_name
== DEFAULT_STRINGPOOL_NAME
)
745 t
->stringpool_name
= name
;
747 /*{{{ opts_set_constants_prefix */
748 /* sets the prefix for the constants, if not already set */
749 static void opts_set_constants_prefix(struct Options
*t
, u8
*prefix
)
751 if (t
->constants_prefix
== DEFAULT_CONSTANTS_PREFIX
)
752 t
->constants_prefix
= prefix
;
754 /*{{{ opts_set_wordlist_name */
755 /* sets the hash table array name, if not already set */
756 static void opts_set_wordlist_name(struct Options
*t
, u8
*name
)
758 if (t
->wordlist_name
== DEFAULT_WORDLIST_NAME
)
759 t
->wordlist_name
= name
;
761 /*{{{ opts_set_lengthtable_name */
762 /* sets the length table array name, if not already set */
763 static void opts_set_lengthtable_name(struct Options
*t
, u8
*name
)
765 if (t
->lengthtable_name
== DEFAULT_LENGTHTABLE_NAME
)
766 t
->lengthtable_name
= name
;
768 /*{{{ opts_set_total_switches */
769 /* sets the total number of switch statements, if not already set */
770 static void opts_set_total_switches(struct Options
*t
, s32 total_switches
)
773 t
->option_word
|= OPTS_SWITCH
;
774 t
->total_switches
= total_switches
;
778 static struct PositionStringParser
*posstrp_new(u8
*str
, s32 low_bound
,
779 s32 high_bound
, s32 end_word_marker
, s32 error_value
, s32 end_marker
)
781 struct PositionStringParser
*t
;
783 t
= calloc(1, sizeof(*t
));
785 t
->low_bound
= low_bound
;
786 t
->high_bound
= high_bound
;
787 t
->end_word_marker
= end_word_marker
;
788 t
->error_value
= error_value
;
789 t
->end_marker
= end_marker
;
795 static void posstrp_del(struct PositionStringParser
*t
)
799 /*{{{ posstrp_nextPosition */
800 /* Returns the next key position from the given string */
801 static s32
posstrp_nextPosition(struct PositionStringParser
*t
)
804 /* We are inside a range. Return the next value from the range */
805 if (++t
->range_curr_value
>= t
->range_upper_bound
)
807 return t
->range_curr_value
;
809 /* we are not inside a range */
810 /* Continue parsing the given string */
820 /* Valid key position */
822 return t
->end_word_marker
;
823 case '0': case '1': case '2': case '3': case '4':
824 case '5': case '6': case '7': case '8': case '9': {
825 /* Valid key position */
830 if (!isdigit((int)(t
->str
[0])))
832 curr_value
= curr_value
* 10 + (t
->str
[0] - '0');
835 if (t
->str
[0] == '-') {
837 /* starting a range of key positions */
840 t
->range_upper_bound
= 0;
842 if (!isdigit((int)(t
->str
[0])))
844 t
->range_upper_bound
= t
->range_upper_bound
* 10
848 /* Verify range's upper bound */
849 if (!(t
->range_upper_bound
> curr_value
&& t
->range_upper_bound
851 return t
->error_value
;
852 t
->range_curr_value
= curr_value
;
854 /* Verify range's lower bound */
855 if (!(curr_value
>= t
->low_bound
&& curr_value
<= t
->high_bound
))
856 return t
->error_value
;
860 /* Invalid syntax. */
861 return t
->error_value
;
864 return t
->end_marker
;
867 static void opts_print(struct Options
*t
)
871 printf("/* Command-line: ");
876 if (i
>= t
->argument_count
)
878 arg
= t
->argument_vector
[i
];
879 /* escape arg if it contains shell metacharacters */
883 if ((*arg
>= 'A' && *arg
<= 'Z') || (*arg
>= 'a' && *arg
<= 'z')) {
886 } else if (*arg
== '-') {
890 if (!((*arg
>= 'A' && *arg
<= 'Z') || (*arg
>= 'a'
891 && *arg
<= 'z') || *arg
== '-'))
900 if (strpbrk(arg
, "\t\n !\"#$&'()*;<>?[\\]`{|}~") != 0) {
901 if (strchr(arg
, '\'') != 0) {
906 if (*arg
== '\"' || *arg
== '\\' || *arg
== '$'
933 /*------------------------------------------------------------------------------------------------*/
935 #include "namespace/globals.h"
936 #include "namespace/options.h"
937 #include "namespace/positions.h"
939 /*------------------------------------------------------------------------------------------------*/