4 * Copyright (C) 1989 Free Software Foundation, Inc.
5 * written by Douglas C. Schmidt (d.schmidt@vanderbilt.edu)
7 * This file is part of GNU GPERF.
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #include "Hash_Table.h"
26 #include "ace/Read_Buffer.h"
27 #include "ace/OS_Memory.h"
28 #include "ace/OS_NS_stdio.h"
29 #include "ace/OS_NS_string.h"
32 /// Default type for generated code.
33 const char *const Key_List::default_array_type
= "char *";
35 /// in_word_set return type, by default.
36 const char *const Key_List::default_return_type
= "char *";
41 dup_string (const char *const str
)
45 char [ACE_OS::strlen (str
) + 1],
47 ACE_OS::strcpy (buf
, str
);
52 } // unnamed namespace
54 /// How wide the printed field width must be to contain the maximum
56 int Key_List::field_width
= 0;
57 int Key_List::determined_
[ACE_STANDARD_CHARACTER_SET_SIZE
];
59 /// Destructor dumps diagnostics during debugging.
60 Key_List::~Key_List ()
62 if (option
[DEBUGGING
])
65 // Free up all the nodes in the list.
66 while (this->head
!= 0)
70 // Make sure to delete the linked nodes, as well.
71 for (List_Node
*ptr
= this->head
->link
;
79 temp
= this->head
->next
;
84 delete [] this->array_type_
;
85 delete [] this->return_type
;
86 delete [] this->struct_tag
;
89 /// Gathers the input stream into a buffer until one of two things occur:
91 /// 1. We read a '%' followed by a '%'
92 /// 2. We read a '%' followed by a '}'
94 /// The first symbolizes the beginning of the keyword list proper, The
95 /// second symbolizes the end of the C source code to be generated
96 /// verbatim in the output file.
98 /// I assume that the keys are separated from the optional preceding
99 /// struct declaration by a consecutive % followed by either % or }
100 /// starting in the first column. The code below uses an expandible
101 /// buffer to scan off and return a pointer to all the code (if any)
102 /// appearing before the delimiter.
104 Key_List::special_input (char delimiter
)
113 for (int i
= 0; (c
= getchar ()) != EOF
; i
++)
120 // Discard newline...
121 while ((c
= getchar ()) != '\n')
131 buf
[delimiter
== '%' && buf
[i
- 2] == ';'
142 // Yikes, time to grow the buffer!
145 ACE_NEW_RETURN (temp
,
148 for (int j
= 0; j
< i
; j
++)
154 buf
[i
] = static_cast<char> (c
);
161 /// Stores any C/C++ source code that must be included verbatim into
162 /// the generated code output.
164 Key_List::save_include_src ()
169 ACE_OS::ungetc (c
, stdin
);
170 else if ((c
= getchar ()) != '{')
171 ACE_ERROR_RETURN ((LM_ERROR
,
172 "internal error, %c != '{' on line %l in file %N",
176 return special_input ('}');
180 /// Determines from the input file whether the user wants to build a
181 /// table from a user-defined struct, or whether the user is content to
182 /// simply use the default array of keys.
184 Key_List::array_type ()
186 return special_input ('%');
189 /// Sets up the Return_Type, the Struct_Tag type and the Array_Type
190 /// based upon various user Options.
192 Key_List::output_types ()
196 delete [] array_type_
;
197 array_type_
= array_type ();
198 if (array_type_
== 0)
199 // Something's wrong, but we'll catch it later on....
203 // Yow, we've got a user-defined type...
204 size_t struct_tag_length
= ACE_OS::strcspn (array_type_
,
206 if (option
[POINTER
]) // And it must return a pointer...
208 delete [] return_type
;
209 ACE_NEW_RETURN (return_type
,
210 char[struct_tag_length
+ 2],
212 ACE_OS::strncpy (return_type
,
215 return_type
[struct_tag_length
] = '*';
216 return_type
[struct_tag_length
+ 1] = '\0';
219 delete [] struct_tag
;
220 ACE_NEW_RETURN (struct_tag
,
221 char[struct_tag_length
+ 2],
223 ACE_OS::strncpy (struct_tag
,
226 if (struct_tag
[struct_tag_length
- 1] != ' ')
228 struct_tag
[struct_tag_length
] = ' ';
231 struct_tag
[struct_tag_length
] = '\0';
234 else if (option
[POINTER
]) // Return a char *.
236 delete [] return_type
;
237 return_type
= dup_string (Key_List::default_array_type
);
242 /// Reads in all keys from standard input and creates a linked list
243 /// pointed to by Head. This list is then quickly checked for
244 /// ``links,'' i.e., unhashable elements possessing identical key sets
247 Key_List::read_keys ()
249 this->include_src
= this->save_include_src ();
250 if (this->include_src
== 0)
252 else if (this->output_types () == -1)
256 ACE_Read_Buffer
input (stdin
);
258 char *buffer
= input
.read ('\n');
261 ACE_ERROR_RETURN ((LM_ERROR
,
262 "No words in input file, did you forget to prepend %%%%"
263 " or use -t accidentally?\n"),
265 // Read in all the keywords from the input file.
269 const char *delimiter
= option
.delimiter ();
270 ACE_NEW_RETURN (this->head
,
272 static_cast<int> (ACE_OS::strcspn (buffer
,
275 for (temp
= this->head
;
276 (0 != (buffer
= input
.read ('\n')))
277 && ACE_OS::strcmp (buffer
, "%%");
280 ACE_NEW_RETURN (temp
->next
,
282 static_cast<int> (ACE_OS::strcspn (buffer
,
288 // See if any additional source code is included at end of
293 this->list_len
= this->total_keys
;
295 // Make large hash table for efficiency.
296 Hash_Table
table (this->list_len
* Key_List::TABLE_MULTIPLE
);
297 List_Node
*trail
= 0;
299 // Test whether there are any links and also set the maximum
300 // length an identifier in the keyword list.
306 List_Node
*ptr
= table
.find (temp
, option
[NOLENGTH
]);
308 // Check for static key links. We deal with these by
309 // building an equivalence class of all duplicate values
310 // (i.e., links) so that only 1 keyword is
311 // representative of the entire collection. This
312 // *greatly* simplifies processing during later stages
321 trail
->next
= temp
->next
;
322 temp
->link
= ptr
->link
;
325 // Complain if user hasn't enabled the duplicate
327 if (!option
[DUP
] || option
[DEBUGGING
])
328 ACE_ERROR ((LM_ERROR
,
329 "Static key link: \"%C\" = \"%C\", with key set \"%C\".\n",
335 // Update minimum and maximum keyword length, if needed.
336 if (max_key_len
< temp
->length
)
337 max_key_len
= temp
->length
;
338 if (min_key_len
> temp
->length
)
339 min_key_len
= temp
->length
;
343 // Exit program if links exists and option[DUP] not set, since
344 // we can't continue.
345 if (total_duplicates
)
350 ACE_ERROR_RETURN ((LM_ERROR
,
351 "%d input keysigs have identical hash values, examine output carefully...\n",
356 ACE_ERROR_RETURN ((LM_ERROR
,
357 "%d input keysigs have identical hash values,\ntry different key positions or use option -D.\n",
361 if (option
[ALLCHARS
])
362 option
.keysig_size (max_key_len
);
368 /// Recursively merges two sorted lists together to form one sorted
369 /// list. The ordering criteria is by frequency of occurrence of
370 /// elements in the key set or by the hash value. This is a kludge,
371 /// but permits nice sharing of almost identical code without incurring
372 /// the overhead of a function call comparison.
374 Key_List::merge (List_Node
*list1
, List_Node
*list2
)
384 else if ((occurrence_sort
&& list1
->occurrence
< list2
->occurrence
)
385 || (hash_sort
&& list1
->hash_value
> list2
->hash_value
)
386 || (key_sort
&& ACE_OS::strcmp (list1
->key
, list2
->key
) >= 0))
388 list2
->next
= merge (list2
->next
, list1
);
393 list1
->next
= merge (list1
->next
, list2
);
398 // Applies the merge sort algorithm to recursively sort the key list
399 // by frequency of occurrence of elements in the key set.
401 Key_List::merge_sort (List_Node
*a_head
)
403 if (!a_head
|| !a_head
->next
)
407 List_Node
*middle
= a_head
;
408 List_Node
*temp
= a_head
->next
->next
;
413 middle
= middle
->next
;
420 return merge (merge_sort (a_head
), merge_sort (temp
));
424 // Returns the frequency of occurrence of elements in the key set.
426 Key_List::occurrence (List_Node
*ptr
)
430 for (char *temp
= ptr
->keysig
; *temp
; temp
++)
431 value
+= Vectors::occurrences
[(int) *temp
];
436 // Sets the index location for all keysig characters that are now
439 Key_List::determined (List_Node
*ptr
)
441 for (char *temp
= ptr
->keysig
; *temp
; temp
++)
442 Key_List::determined_
[(int) *temp
] = 1;
445 // Returns TRUE if PTR's key set is already completely determined.
447 Key_List::already_determined (List_Node
*ptr
)
449 int is_determined
= 1;
451 for (char *temp
= ptr
->keysig
; is_determined
&& *temp
; temp
++)
452 is_determined
= determined_
[(int) *temp
];
454 return is_determined
;
456 // Reorders the table by first sorting the list so that frequently
457 // occurring keys appear first, and then the list is reorded so that
458 // keys whose values are already determined will be placed towards the
459 // front of the list. This helps prune the search time by handling
460 // inevitable collisions early in the search process. See Cichelli's
461 // paper from Jan 1980 JACM for details....
468 for (ptr
= head
; ptr
; ptr
= ptr
->next
)
469 ptr
->occurrence
= occurrence (ptr
);
471 // Switch to sorting by occurrence.
475 for (ptr
= head
= merge_sort (head
); ptr
->next
; ptr
= ptr
->next
)
479 if (already_determined (ptr
->next
))
483 List_Node
*trail_ptr
= ptr
->next
;
484 List_Node
*run_ptr
= trail_ptr
->next
;
486 for (; run_ptr
; run_ptr
= trail_ptr
->next
)
488 if (already_determined (run_ptr
))
490 trail_ptr
->next
= run_ptr
->next
;
491 run_ptr
->next
= ptr
->next
;
492 ptr
= ptr
->next
= run_ptr
;
501 // Outputs the maximum and minimum hash values. Since the list is
502 // already sorted by hash value all we need to do is find the final
505 Key_List::output_min_max ()
508 for (temp
= head
; temp
->next
; temp
= temp
->next
)
511 min_hash_value
= head
->hash_value
;
512 max_hash_value
= temp
->hash_value
;
515 ACE_OS::printf ("\n#define TOTAL_KEYWORDS %d\n#define MIN_WORD_LENGTH %d"
516 "\n#define MAX_WORD_LENGTH %d\n#define MIN_HASH_VALUE %d"
517 "\n#define MAX_HASH_VALUE %d\n#define HASH_VALUE_RANGE %d"
518 "\n#define DUPLICATES %d\n#define WORDLIST_SIZE %d\n\n",
519 total_keys
, min_key_len
, max_key_len
, min_hash_value
,
520 max_hash_value
, max_hash_value
- min_hash_value
+ 1,
521 total_duplicates
? total_duplicates
+ 1 : 0, total_keys
+ min_hash_value
);
522 else if (option
[GLOBAL
])
523 ACE_OS::printf ("enum\n{\n"
524 " TOTAL_KEYWORDS = %d,\n"
525 " MIN_WORD_LENGTH = %d,\n"
526 " MAX_WORD_LENGTH = %d,\n"
527 " MIN_HASH_VALUE = %d,\n"
528 " MAX_HASH_VALUE = %d,\n"
529 " HASH_VALUE_RANGE = %d,\n"
531 " WORDLIST_SIZE = %d};\n\n",
532 total_keys
, min_key_len
, max_key_len
, min_hash_value
,
533 max_hash_value
, max_hash_value
- min_hash_value
+ 1,
534 total_duplicates
? total_duplicates
+ 1 : 0, total_keys
+ min_hash_value
);
537 // Generates the output using a C switch. This trades increased
538 // search time for decreased table space (potentially *much* less
539 // space for sparse tables). It the user has specified their own
540 // struct in the keyword file *and* they enable the POINTER option we
541 // have extra work to do. The solution here is to maintain a local
542 // static array of user defined struct's, as with the
543 // Output_Lookup_Function. Then we use for switch statements to
544 // perform either a strcmp or strncmp, returning 0 if the str fails to
545 // match, and otherwise returning a pointer to appropriate index
546 // location in the local static array.
549 Key_List::output_switch (int use_keyword_table
)
551 if (!option
[GLOBAL
] && use_keyword_table
== 0)
553 if (option
[LENTABLE
] && option
[DUP
])
554 output_keylength_table ();
555 if (option
[POINTER
] && option
[TYPE
])
556 output_keyword_table ();
559 std::unique_ptr
<char[]> safe_comp_buffer
;
562 List_Node
*curr
= head
;
563 int pointer_and_type_enabled
= option
[POINTER
] && option
[TYPE
];
564 int total_switches
= option
.total_switches ();
565 int switch_size
= keyword_list_length () / total_switches
;
567 if (pointer_and_type_enabled
)
569 // Keep track of the longest string we'll need!
570 const char *s
= "charmap[*str] == *resword->%s && !ACE_OS::strncasecmp (str + 1, resword->%s + 1, len - 1)";
573 new char[ACE_OS::strlen (s
)
574 + 2 * ACE_OS::strlen (option
.key_name ()) + 1];
575 safe_comp_buffer
.reset (tmp
);
577 comp_buffer
= safe_comp_buffer
.get ();
580 ACE_OS::sprintf (comp_buffer
, "%s == *resword->%s && !ACE_OS::%s (str + 1, resword->%s + 1, len - 1)",
581 option
[STRCASECMP
] ? "charmap[*str]" : "*str", option
.key_name (),
582 option
[STRCASECMP
] ? "strncasecmp" : "strncmp", option
.key_name ());
584 ACE_OS::sprintf (comp_buffer
, "%s == *resword->%s && !ACE_OS::%s (str + 1, resword->%s + 1)",
585 option
[STRCASECMP
] ? "charmap[*str]" : "*str", option
.key_name (),
586 option
[STRCASECMP
] ? "strcasecmp" : "strcmp", option
.key_name ());
591 comp_buffer
= option
[STRCASECMP
]
592 ? (char *) "charmap[*str] == *resword && !ACE_OS::strncasecmp (str + 1, resword + 1, len - 1)"
593 : (char *) "*str == *resword && !ACE_OS::strncmp (str + 1, resword + 1, len - 1)";
595 comp_buffer
= option
[STRCASECMP
]
596 ? (char *) "charmap[*str] == *resword && !ACE_OS::strncasecmp (str + 1, resword + 1, len - 1)"
597 : (char *) "*str == *resword && !ACE_OS::strcmp (str + 1, resword + 1)";
599 if (!option
[OPTIMIZE
])
600 ACE_OS::printf (" if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)\n {\n");
601 ACE_OS::printf (" unsigned int const key = %s (str, len);\n\n", option
.hash_name ());
602 if (!option
[OPTIMIZE
])
603 ACE_OS::printf (" if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE)\n");
605 ACE_OS::printf (" {\n");
607 // Properly deal with user's who request multiple switch statements.
611 List_Node
*temp
= curr
;
612 int lowest_case_value
= curr
->hash_value
;
613 int number_of_cases
= 0;
615 // Figure out a good cut point to end this switch.
617 for (; temp
&& ++number_of_cases
< switch_size
; temp
= temp
->next
)
618 if (temp
->next
&& temp
->hash_value
== temp
->next
->hash_value
)
619 while (temp
->next
&& temp
->hash_value
== temp
->next
->hash_value
)
622 if (temp
&& total_switches
!= 1)
623 ACE_OS::printf (" if (key <= %d)\n {\n", temp
->hash_value
);
625 ACE_OS::printf (" {\n");
627 // Output each keyword as part of a switch statement indexed by
630 if (option
[POINTER
] || option
[DUP
] || use_keyword_table
)
634 ACE_OS::printf (" %s%s *resword; %s\n\n",
635 option
[CONSTANT
] || pointer_and_type_enabled
== 0 ? "const " : "",
636 pointer_and_type_enabled
? struct_tag
: "char",
637 option
[LENTABLE
] && !option
[DUP
] ? "unsigned int key_len;" : "");
638 if (total_switches
== 1)
640 ACE_OS::printf (" switch (key)\n {\n");
641 lowest_case_value
= 0;
644 ACE_OS::printf (" switch (key - %d)\n {\n", lowest_case_value
);
646 for (temp
= curr
; temp
&& ++i
<= number_of_cases
; temp
= temp
->next
)
648 ACE_OS::printf (" case %*d:\n",
649 Key_List::field_width
,
650 temp
->hash_value
- lowest_case_value
);
652 // Handle `static links,' i.e., those that occur during
653 // the initial preprocessing.
657 if (option
[DEBUGGING
])
658 ACE_OS::printf (" /* hash value = %4d, keyword = \"%s\" */\n",
664 List_Node
*links
= 0;
666 for (links
= temp
; links
; links
= links
->link
)
668 if (option
[DEBUGGING
])
669 ACE_OS::printf (" /* hash value = %4d, keyword = \"%s\" */\n",
672 if (pointer_and_type_enabled
)
673 ACE_OS::printf (" resword = &wordlist[%d];\n", links
->slot
);
674 else if (use_keyword_table
)
675 ACE_OS::printf (" resword = wordlist[%d];\n", links
->slot
);
677 ACE_OS::printf (" resword = \"%s\";\n", links
->key
);
678 ACE_OS::printf (" if (%s) return resword;\n", comp_buffer
);
682 // Handle unresolved duplicate hash values. These are
683 // guaranteed to be adjacent since we sorted the keyword
684 // list by increasing hash values.
685 if (temp
->next
&& temp
->hash_value
== temp
->next
->hash_value
)
687 for ( ; temp
->next
&& temp
->hash_value
== temp
->next
->hash_value
;
690 if (pointer_and_type_enabled
)
691 ACE_OS::printf (" resword = &wordlist[%d];\n", temp
->slot
);
692 else if (use_keyword_table
)
693 ACE_OS::printf (" resword = wordlist[%d];", temp
->slot
);
695 ACE_OS::printf (" resword = \"%s\";\n", temp
->key
);
696 ACE_OS::printf (" if (%s) return resword;\n", comp_buffer
);
698 if (pointer_and_type_enabled
)
699 ACE_OS::printf (" resword = &wordlist[%d];\n", temp
->slot
);
700 else if (use_keyword_table
)
701 ACE_OS::printf (" resword = wordlist[%d];", temp
->slot
);
703 ACE_OS::printf (" resword = \"%s\";\n", temp
->key
);
704 ACE_OS::printf (" return %s ? resword : 0;\n", comp_buffer
);
707 ACE_OS::printf (" return 0;\n");
710 if (pointer_and_type_enabled
)
711 ACE_OS::printf (" resword = &wordlist[%d];", temp
->slot
);
712 else if (use_keyword_table
)
713 ACE_OS::printf (" resword = wordlist[%d];", temp
->slot
);
715 ACE_OS::printf (" resword = \"%s\";", temp
->key
);
716 if (option
[LENTABLE
] && !option
[DUP
])
717 ACE_OS::printf (" key_len = %d;", temp
->length
);
718 ACE_OS::printf (" break;\n");
721 ACE_OS::printf (" default: return 0;\n }\n");
722 if (option
[OPTIMIZE
])
723 ACE_OS::printf (" return resword;\n");
726 ACE_OS::printf (option
[LENTABLE
] && !option
[DUP
]
727 ? " if (len == key_len && %s)\n return resword;\n"
728 : " if (%s)\n return resword;\n", comp_buffer
);
729 ACE_OS::printf (" return 0;\n");
731 ACE_OS::printf (" }\n");
734 else // Nothing special required here.
737 ACE_OS::printf (" char *s;\n\n switch (key - %d)\n {\n",
740 for (temp
= curr
; temp
&& ++i
<= number_of_cases
; temp
= temp
->next
)
741 if (option
[LENTABLE
])
742 ACE_OS::printf (" case %*d: if (len == %d) s = \"%s\"; else return 0; break;\n",
743 Key_List::field_width
,
744 temp
->hash_value
- lowest_case_value
,
748 ACE_OS::printf (" case %*d: s = \"%s\"; break;\n",
749 Key_List::field_width
,
750 temp
->hash_value
- lowest_case_value
,
753 ACE_OS::printf (" default: return 0;\n }\n ");
755 ACE_OS::printf ("return %s == *s && !ACE_OS::%s;\n }\n",
756 option
[STRCASECMP
] ? "charmap[*str]" : "*str",
757 option
[STRCASECMP
] ? "strncasecmp (s + 1, str + 1, len - 1)" : "strcmp (s + 1, str + 1)");
759 ACE_OS::printf ("return %s == *s && !ACE_OS::%s;\n }\n",
760 option
[STRCASECMP
] ? "charmap[*str]" : "*str",
761 option
[STRCASECMP
] ? "strcasecmp (s + 1, str + 1, len - 1)" : "strcmp (s + 1, str + 1)");
765 ACE_OS::printf (" }\n %s\n}\n", option
[OPTIMIZE
] ? "" : "}\n return 0;");
768 // Prints out a table of keyword lengths, for use with the comparison
769 // code in generated function ``in_word_set.''
772 Key_List::output_keylength_table ()
774 const int max_column
= 15;
777 const char *indent
= option
[GLOBAL
] ? "" : " ";
780 if (!option
[DUP
] && !option
[SWITCH
])
782 ACE_OS::printf ("\n%sstatic %sunsigned %s lengthtable[] =\n%s%s{\n ",
784 option
[CONSTANT
] ? "const " : "",
785 max_key_len
<= ((int) UCHAR_MAX
) ? "char" : (max_key_len
<= ((int) USHRT_MAX
) ? "short" : "long"),
789 for (temp
= head
; temp
; temp
= temp
->next
, slot
++)
791 if (slot
< temp
->hash_value
)
792 for ( ; slot
< temp
->hash_value
; slot
++)
793 ACE_OS::printf ("%3d,%s", 0, ++column
% (max_column
- 1) ? "" : "\n ");
795 ACE_OS::printf ("%3d,%s", temp
->length
, ++column
% (max_column
- 1 ) ? "" : "\n ");
798 ACE_OS::printf ("\n%s%s};\n",
804 // Prints out the array containing the key words for the Gen_Perf hash
808 Key_List::output_keyword_table ()
810 const char *l_brace
= *head
->rest
? "{" : "";
811 const char *r_brace
= *head
->rest
? "}," : "";
812 const char *indent
= option
[GLOBAL
] ? "" : " ";
816 int pointer_and_type_enabled
= option
[POINTER
] && option
[TYPE
];
817 ACE_OS::printf ("%sstatic %s%swordlist[] =\n%s%s{\n",
819 option
[CONSTANT
] || pointer_and_type_enabled
== 0 ? "const " : "",
824 // Skip over leading blank entries if there are no duplicates.
826 if (0 < head
->hash_value
)
827 ACE_OS::printf (" ");
832 for (column
= 1; slot
< head
->hash_value
; column
++)
834 ACE_OS::printf ("%s\"\",%s%s%s",
836 option
.fill_default (),
838 column
% 9 ? "" : "\n ");
842 if (0 < head
->hash_value
&& column
% 10)
843 ACE_OS::printf ("\n");
845 // Generate an array of reserved words at appropriate locations.
847 for (temp
= head
; temp
; temp
= temp
->next
, slot
++)
851 if (!option
[SWITCH
] && (total_duplicates
== 0 || !option
[DUP
]) && slot
< temp
->hash_value
)
855 ACE_OS::printf (" ");
857 for (column
= 1; slot
< temp
->hash_value
; slot
++, column
++)
858 ACE_OS::printf ("%s\"\",%s%s%s",
860 option
.fill_default (),
862 column
% 9 ? "" : "\n ");
865 ACE_OS::printf ("\n");
868 ACE_OS::printf ("%s\"%s\", %s%s", l_brace
, temp
->key
, temp
->rest
, r_brace
);
869 if (option
[DEBUGGING
])
870 ACE_OS::printf (" /* hash value = %d, slot = %d */",
878 ACE_OS::printf (" %s\"%s\", %s%s", l_brace
, temp
->key
, temp
->rest
, r_brace
);
879 if (option
[DEBUGGING
])
880 ACE_OS::printf (" /* hash value = %d, slot = %d */",
885 // Deal with links specially.
887 for (List_Node
*links
= temp
->link
; links
; links
= links
->link
)
889 links
->slot
= ++slot
;
890 ACE_OS::printf (" %s\"%s\", %s%s", l_brace
, links
->key
, links
->rest
, r_brace
);
891 if (option
[DEBUGGING
])
892 ACE_OS::printf (" /* hash value = %d, slot = %d */",
899 ACE_OS::printf ("%s%s};\n\n", indent
, indent
);
902 // Generates C code for the binary search algorithm that returns
903 // the proper encoding for each key word
906 Key_List::output_binary_search_function ()
908 ACE_OS::printf ("%s\n", include_src
);
910 // Get prototype for strncmp() and strcmp().
911 if (!option
[SKIPSTRINGH
])
912 ACE_OS::printf ("#include \"ace/OS_NS_string.h\"\n");
914 // Output type declaration now, reference it later on....
915 if (option
[TYPE
] && !option
[NOTYPE
])
916 ACE_OS::printf ("%s;\n",
921 if (option
[STRCASECMP
])
922 output_strcasecmp ();
924 // Class definition if -M is *not* enabled.
925 if (option
[CPLUSPLUS
] && !option
[SKIPCLASS
])
926 ACE_OS::printf ("class %s {\npublic:\n"
927 " static %s%s%s (const char *str);\n};\n\n",
928 option
.class_name (),
929 option
[CONSTANT
] ? "const " : "",
931 option
.function_name ());
933 // Use the inline keyword to remove function overhead.
935 ACE_OS::printf ("inline\n");
937 ACE_OS::printf ("%s%s\n", option
[CONSTANT
] ? "const " : "", return_type
);
938 if (option
[CPLUSPLUS
])
939 ACE_OS::printf ("%s::", option
.class_name ());
941 ACE_OS::printf (option
[ANSI
]
942 ? "%s (const char *str)\n{\n"
943 : "%s (str)\n char *str;\n{\n",
944 option
.function_name ());
946 // Use the switch in place of lookup table.
951 // Use the lookup table, in place of switch.
956 if (option
[LENTABLE
])
957 output_keylength_table ();
958 output_keyword_table ();
962 // Logic to handle the Binary Search.
964 ACE_OS::printf ("int first = 0, last = 0, middle = 0;\n");
966 if (option
[DUP
] && total_duplicates
> 0)
968 ACE_OS::printf ("%s*base = 0;\n",struct_tag
);
971 ACE_OS::printf ("\nlast = %d;\n",total_keys
- 1);
972 ACE_OS::printf ("while (last >= first)\n");
973 ACE_OS::printf ("\t{\n");
974 ACE_OS::printf ("\t middle = (last + first) / 2;\n");
975 ACE_OS::printf ("\t if (ACE_OS::strcmp (wordlist[middle].%s, str) == 0)\n break;\n", option
.key_name());
976 ACE_OS::printf ("\t if (ACE_OS::strcmp (wordlist[middle].%s, str) < 0)\n first = middle + 1;\n", option
.key_name());
977 ACE_OS::printf ("\t else last = middle - 1;\n");
978 ACE_OS::printf ("\t}\n");
979 ACE_OS::printf ("if (last < first)\n return 0;\n");
980 ACE_OS::printf ("else\n return (&wordlist[middle]);\n}\n");
995 ACE_OS::fflush(stdout
);
1000 // Generates C code for the linear search algorithm that returns
1001 // the proper encoding for each key word
1004 Key_List::output_linear_search_function ()
1006 ACE_OS::printf ("%s\n", include_src
);
1008 // Get prototype for strncmp() and strcmp().
1009 if (!option
[SKIPSTRINGH
])
1010 ACE_OS::printf ("#include \"ace/OS_NS_string.h\"\n");
1012 // Output type declaration now, reference it later on....
1013 if (option
[TYPE
] && !option
[NOTYPE
])
1014 ACE_OS::printf ("%s;\n",
1019 if (option
[STRCASECMP
])
1020 output_strcasecmp ();
1022 // Class definition if -M is *not* enabled.
1023 if (option
[CPLUSPLUS
] && !option
[SKIPCLASS
])
1024 ACE_OS::printf ("class %s {\npublic:\n"
1025 " static %s%s%s (const char *str);\n};\n\n",
1026 option
.class_name (),
1027 option
[CONSTANT
] ? "const " : "",
1029 option
.function_name ());
1031 // Use the inline keyword to remove function overhead.
1033 ACE_OS::printf ("inline\n");
1035 ACE_OS::printf ("%s%s\n",
1036 option
[CONSTANT
] ? "const " : "",
1038 if (option
[CPLUSPLUS
])
1039 ACE_OS::printf ("%s::", option
.class_name ());
1041 ACE_OS::printf (option
[ANSI
]
1042 ? "%s (const char *str)\n{\n"
1043 : "%s (str)\n char *str;\n{\n",
1044 option
.function_name ());
1046 // Use the switch in place of lookup table.
1050 // Use the lookup table, in place of switch.
1053 if (!option
[GLOBAL
])
1055 if (option
[LENTABLE
])
1056 output_keylength_table ();
1057 output_keyword_table ();
1061 // Logic to handle the Linear Search.
1063 ACE_OS::printf ("for (int i=0; i<=%d; i++)",total_keys
-1);
1064 ACE_OS::printf ("\t{\n");
1065 ACE_OS::printf ("\t if (ACE_OS::strcmp (wordlist[i].%s, str) == 0)\n", option
.key_name());
1066 ACE_OS::printf ("\t return &wordlist[i];\n");
1067 ACE_OS::printf ("\t}\n");
1068 ACE_OS::printf ("return 0;\n}\n");
1070 if (additional_code
)
1083 ACE_OS::fflush (stdout
);
1087 // Generates C code for the hash function that returns the proper
1088 // encoding for each key word.
1091 Key_List::output_hash_function ()
1093 const int max_column
= 10;
1094 int count
= max_hash_value
;
1096 #if ACE_STANDARD_CHARACTER_SET_SIZE == ACE_EBCDIC_SIZE
1097 // Lookup table for converting ASCII to EBCDIC.
1098 static const int ascii_to_ebcdic
[ACE_ASCII_SIZE
] =
1100 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
1101 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
1102 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
1103 0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F,
1105 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
1106 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
1107 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
1108 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
1110 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
1111 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
1112 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
1113 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
1115 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
1116 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
1117 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
1118 0xA7, 0xA8, 0xA9, 0xC0, 0x6A, 0xD0, 0xA1, 0x07};
1120 int ebcdic_to_ascii
[ACE_EBCDIC_SIZE
];
1122 #endif /* ACE_STANDARD_CHARACTER_SET_SIZE == ACE_EBCDIC_SIZE */
1124 // Calculate maximum number of digits required for MAX_HASH_VALUE.
1126 for (Key_List::field_width
= 2;
1128 Key_List::field_width
++)
1132 ACE_OS::printf ("inline\n");
1135 ACE_OS::printf ("static ");
1136 ACE_OS::printf ("unsigned int\n");
1137 if (option
[CPLUSPLUS
])
1138 ACE_OS::printf ("%s::", option
.class_name ());
1140 ACE_OS::printf (option
[ANSI
]
1141 ? "%s (const char *str, unsigned int len)\n{\n"
1142 : "%s (str, len)\n char *str;\n unsigned int len;\n{\n",
1143 option
.hash_name ());
1145 // Generate the asso_values table.
1146 ACE_OS::printf (" static %sunsigned %s asso_values[] =\n {",
1147 option
[CONSTANT
] ? "constexpr " : "",
1148 max_hash_value
< ((int) UCHAR_MAX
) ? "char" : (max_hash_value
< ((int) USHRT_MAX
) ? "short" : "int"));
1150 #if ACE_STANDARD_CHARACTER_SET_SIZE == ACE_EBCDIC_SIZE
1152 for (count
= 0; count
< ACE_ASCII_SIZE
; ++count
)
1154 if (!(count
% max_column
))
1155 ACE_OS::printf ("\n ");
1157 target
= ascii_to_ebcdic
[count
];
1158 ACE_OS::printf ("%*d,",
1159 Key_List::field_width
,
1160 Vectors::occurrences
[target
] ? Vectors::asso_values
[target
] : max_hash_value
+ 1);
1165 for (count
= 0; count
< ACE_ASCII_SIZE
; ++count
)
1167 if (!(count
% max_column
))
1168 ACE_OS::printf ("\n ");
1170 ACE_OS::printf ("%*d,",
1171 Key_List::field_width
,
1172 Vectors::occurrences
[count
] ? Vectors::asso_values
[count
] : max_hash_value
+ 1);
1175 #endif /* ACE_STANDARD_CHARACTER_SET_SIZE == ACE_EBCDIC_SIZE */
1177 // Optimize special case of ``-k 1,$''
1178 if (option
[DEFAULTCHARS
])
1180 if (option
[STRCASECMP
])
1181 ACE_OS::printf ("\n };\n return %sasso_values[static_cast<int>(charmap[str[len - 1]]]) + asso_values[static_cast<int>(charmap[str[0]])];\n}\n\n",
1182 option
[NOLENGTH
] ? "" : "len + ");
1184 ACE_OS::printf ("\n };\n return %sasso_values[static_cast<int>(str[len - 1])] + asso_values[static_cast<int>(str[0])];\n}\n\n",
1185 option
[NOLENGTH
] ? "" : "len + ");
1193 // Get first (also highest) key position.
1194 key_pos
= option
.get ();
1196 // We can perform additional optimizations here.
1197 if (!option
[ALLCHARS
] && key_pos
<= min_key_len
)
1199 ACE_OS::printf ("\n };\n return %s", option
[NOLENGTH
] ? "" : "len + ");
1201 for (; key_pos
!= WORD_END
; )
1203 ACE_OS::printf (option
[STRCASECMP
] ? "asso_values[static_cast<int>(charmap[str[%d]])]" : "asso_values[static_cast<int>(str[%d])]", key_pos
- 1);
1204 if ((key_pos
= option
.get ()) != EOS
)
1205 ACE_OS::printf (" + ");
1210 ACE_OS::printf ("%s;\n}\n\n", key_pos
== WORD_END
1211 ? (option
[STRCASECMP
] ? "asso_values[static_cast<int>(charmap[str[len - 1]])]" : "asso_values[static_cast<int>(str[len - 1])]")
1215 // We've got to use the correct, but brute force, technique.
1218 ACE_OS::printf ("\n };\n unsigned int hval = %s;\n\n switch (%s)\n {\n default:\n",
1219 option
[NOLENGTH
] ? "0" : "len", option
[NOLENGTH
] ? "len" : "hval");
1221 // User wants *all* characters considered in hash.
1222 if (option
[ALLCHARS
])
1226 // Break these options up for speed (gee, is this misplaced efficiency or what?!
1227 if (option
[STRCASECMP
])
1229 for (i
= max_key_len
; i
> 0; i
--)
1230 ACE_OS::printf (" case %d:\n hval += asso_values[static_cast<int>(charmap[static_cast<int>(str[%d])])];\n", i
, i
- 1);
1234 for (i
= max_key_len
; i
> 0; i
--)
1235 ACE_OS::printf (" case %d:\n hval += asso_values[static_cast<int>(str[%d])];\n", i
, i
- 1);
1237 ACE_OS::printf (" }\n return hval;\n}\n\n");
1239 else // do the hard part...
1241 count
= key_pos
+ 1;
1245 while (--count
> key_pos
)
1246 ACE_OS::printf (" case %d:\n", count
);
1248 ACE_OS::printf (option
[STRCASECMP
]
1249 ? " case %d:\n hval += asso_values[static_cast<int>(charmap[static_cast<int>(str[%d])])];\n // Fallthrough\n"
1250 : " case %d:\n hval += asso_values[static_cast<int>(str[%d])];\n // Fallthrough \n",
1251 key_pos
, key_pos
- 1);
1253 while ((key_pos
= option
.get ()) != EOS
&& key_pos
!= WORD_END
);
1255 ACE_OS::printf (" }\n return hval%s;\n}\n\n",
1257 ? (option
[STRCASECMP
] ? " + asso_values[static_cast<int>(charmap[static_cast<int>(str[len - 1])])]" : " + asso_values[static_cast<int>(str[len - 1])]")
1265 Key_List::count_duplicates (List_Node
*link
,
1270 // Count the number of "static" duplicates for this hash value.
1271 for (List_Node
*ptr
= link
;
1277 if (option
[DEBUGGING
])
1278 ACE_DEBUG ((LM_DEBUG
,
1279 "%s linked keyword = %s, slot = %d, hash_value = %d\n",
1290 Key_List::update_lookup_array (int lookup_array
[],
1293 Duplicate_Entry
*dup_ptr
,
1296 lookup_array
[i1
] = -dup_ptr
->slot
;
1297 lookup_array
[i2
] = -dup_ptr
->count
;
1298 lookup_array
[dup_ptr
->hash_value
] = value
;
1301 // Generates the large, sparse table that maps hash values in the
1302 // smaller, contiguous range of the keyword table.
1305 Key_List::output_lookup_array ()
1307 if (total_duplicates
> 0)
1309 const int DEFAULT_VALUE
= -1;
1311 Duplicate_Entry
*duplicates
= 0;
1312 ACE_NEW_RETURN (duplicates
,
1313 Duplicate_Entry
[total_duplicates
],
1316 int *lookup_array
= 0;
1317 ACE_NEW_RETURN (lookup_array
,
1318 int[max_hash_value
+ 1],
1321 Duplicate_Entry
*dup_ptr
= duplicates
;
1322 int *lookup_ptr
= lookup_array
+ max_hash_value
+ 1;
1324 // Initialize the lookup array to the DEFAULT_VALUE (-1).
1325 while (lookup_ptr
> lookup_array
)
1326 *--lookup_ptr
= DEFAULT_VALUE
;
1328 // Iterate through the keylist and handle the static and dynamic
1329 // duplicate entries.
1330 for (List_Node
*temp
= head
; temp
; temp
= temp
->next
)
1332 int hash_value
= temp
->hash_value
;
1333 // Store the keyword's slot location into the
1334 // <lookup_array> at the <hash_value>. If this is a
1335 // non-duplicate, then this value will point directly to the
1337 lookup_array
[hash_value
] = temp
->slot
;
1339 if (option
[DEBUGGING
])
1340 ACE_DEBUG ((LM_DEBUG
,
1341 "keyword = %s, slot = %d, hash_value = %d, lookup_array[hash_value] = %d\n",
1345 lookup_array
[temp
->hash_value
]));
1347 if (temp
->link
== 0 &&
1348 (temp
->next
== 0 || hash_value
!= temp
->next
->hash_value
))
1349 // This isn't a duplicate. Note that we know this because
1350 // we sorted the keys by their hash value.
1354 // We'll handle the duplicates here.
1355 dup_ptr
->hash_value
= hash_value
;
1356 dup_ptr
->slot
= temp
->slot
;
1359 // Count the number of "static" duplicates, i.e.,
1360 // keywords that had the same keysig when the keyfile
1362 dup_ptr
->count
+= this->count_duplicates (temp
->link
,
1365 // Count the number of "dynamic" duplicates, i.e.,
1366 // keywords that ended up with the same hash value as a
1367 // result of the <asso_values> contents.
1369 temp
->next
&& hash_value
== temp
->next
->hash_value
;
1371 dup_ptr
->count
+= this->count_duplicates (temp
->next
,
1377 // Compute the values in the lookup array.
1378 while (--dup_ptr
>= duplicates
)
1380 if (option
[DEBUGGING
])
1381 ACE_DEBUG ((LM_DEBUG
,
1382 "dup_ptr[%d]: hash_value = %d, slot = %d, count = %d\n",
1383 dup_ptr
- duplicates
,
1384 dup_ptr
->hash_value
,
1389 // Look to the left first.
1390 for (i
= dup_ptr
->hash_value
; i
> 0; i
--)
1391 if (lookup_array
[i
] == DEFAULT_VALUE
&& lookup_array
[i
- 1] == DEFAULT_VALUE
)
1393 this->update_lookup_array (lookup_array
,
1397 -(max_hash_value
+ (dup_ptr
->hash_value
- i
+ 1)));
1401 // If we didn't find it to the left look to the right
1405 for (i
= dup_ptr
->hash_value
; i
< max_hash_value
; i
++)
1406 if (lookup_array
[i
] == DEFAULT_VALUE
&& lookup_array
[i
+ 1] == DEFAULT_VALUE
)
1408 this->update_lookup_array (lookup_array
,
1412 max_hash_value
+ (i
- dup_ptr
->hash_value
));
1416 // If this happens, we can't use the output array scheme...
1417 if (i
>= max_hash_value
)
1420 ACE_DEBUG ((LM_DEBUG
,
1421 "GPERF: Automatically changing to -S1 switch option\n"));
1422 // Since we've already generated the keyword table
1423 // we need to use it!
1424 this->output_switch (1);
1426 delete [] duplicates
;
1427 delete [] lookup_array
;
1428 return 1; // 1 indicates that we've changed our mind...
1433 lookup_ptr
= lookup_array
+ max_hash_value
+ 1;
1436 while (lookup_ptr
> lookup_array
)
1438 int val
= abs (*--lookup_ptr
);
1443 const char *indent
= option
[GLOBAL
] ? "" : " ";
1445 ACE_OS::printf ("%sstatic %ssigned %s lookup[] =\n%s%s{\n%s", indent
, option
[CONSTANT
] ? "constexpr " : "",
1446 max
<= SCHAR_MAX
? "char" : (max
<= SHRT_MAX
? "short" : "int"),
1447 indent
, indent
, option
[DEBUGGING
] ? "" : " ");
1451 // Calculate maximum number of digits required for LOOKUP_ARRAY_SIZE.
1453 for (Key_List::field_width
= 2; (count
/= 10) > 0; Key_List::field_width
++)
1456 const int max_column
= 15;
1459 for (lookup_ptr
= lookup_array
;
1460 lookup_ptr
< lookup_array
+ max_hash_value
+ 1;
1463 if (option
[DEBUGGING
])
1464 ACE_OS::printf (" %*d, /* slot = %d */\n",
1465 Key_List::field_width
,
1467 (int)(lookup_ptr
- lookup_array
));
1469 ACE_OS::printf ("%*d, %s",
1470 Key_List::field_width
,
1472 ++column
% (max_column
- 1) ? "" : "\n ");
1474 ACE_OS::printf ("%s%s%s};\n\n", option
[DEBUGGING
] ? "" : "\n", indent
, indent
);
1476 delete [] duplicates
;
1477 delete [] lookup_array
;
1482 // Generates C code to perform the keyword lookup.
1485 Key_List::output_lookup_function ()
1487 if (!option
[OPTIMIZE
])
1488 ACE_OS::printf (" if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)\n {\n");
1489 ACE_OS::printf (" unsigned int const key = %s (str, len);\n\n", option
.hash_name ());
1490 if (!option
[OPTIMIZE
])
1491 ACE_OS::printf (" if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE)\n");
1492 ACE_OS::printf (" {\n");
1494 if (option
[DUP
] && total_duplicates
> 0)
1496 int pointer_and_type_enabled
= option
[POINTER
] && option
[TYPE
];
1498 ACE_OS::printf (" int slot = lookup[key];\n\n"
1499 " if (slot >= 0 && slot < WORDLIST_SIZE)\n");
1500 if (option
[OPTIMIZE
])
1501 ACE_OS::printf (" return %swordlist[slot];\n", option
[TYPE
] && option
[POINTER
] ? "&" : "");
1504 ACE_OS::printf (" {\n"
1505 " %schar *s = wordlist[slot]", option
[CONSTANT
] || pointer_and_type_enabled
== 0 ? "const " : "");
1506 if (ACE_OS::strcmp (array_type_
, Key_List::default_array_type
) != 0)
1507 ACE_OS::printf (".%s", option
.key_name ());
1509 ACE_OS::printf (";\n\n if (%s%s == *s && !ACE_OS::%s)\n return %s;\n }\n",
1510 option
[LENTABLE
] ? "len == lengthtable[key]\n && " : "",
1511 option
[STRCASECMP
] ? "charmap[*str]" : "*str",
1512 option
[COMP
] ? (option
[STRCASECMP
] ? "strncasecmp (str + 1, s + 1, len - 1)" : "strncmp (str + 1, s + 1, len - 1)")
1513 : (option
[STRCASECMP
] ? "strcasecmp (str + 1, s + 1)" : "strcmp (str + 1, s + 1)"),
1514 option
[TYPE
] && option
[POINTER
] ? "&wordlist[slot]" : "s");
1515 ACE_OS::printf (" else if (slot < 0 && slot >= -MAX_HASH_VALUE)\n"
1518 ACE_OS::printf (" else\n {\n"
1519 " unsigned int offset = key + slot + (slot > 0 ? -MAX_HASH_VALUE : MAX_HASH_VALUE);\n"
1520 " %s%s*base = &wordlist[-lookup[offset]];\n"
1521 " %s%s*ptr = base + -lookup[offset + 1];\n\n"
1522 " while (--ptr >= base)\n ",
1523 option
[CONSTANT
] || pointer_and_type_enabled
== 0 ? "const " : "", struct_tag
,
1524 option
[CONSTANT
] || pointer_and_type_enabled
== 0 ? "const " : "", struct_tag
);
1525 if (ACE_OS::strcmp (array_type_
, Key_List::default_array_type
) != 0)
1528 ACE_OS::printf ("if (%s == *ptr->%s && !ACE_OS::%s (str + 1, ptr->%s + 1, len - 1",
1529 option
[STRCASECMP
] ? "charmap[*str]" : "*str", option
.key_name (),
1530 option
[STRCASECMP
] ? "strncasecmp" : "strncmp", option
.key_name ());
1532 ACE_OS::printf ("if (%s == *ptr->%s && !ACE_OS::%s (str + 1, ptr->%s + 1",
1533 option
[STRCASECMP
] ? "charmap[*str]" : "*str", option
.key_name (),
1534 option
[STRCASECMP
] ? "strcasecmp" : "strcmp", option
.key_name ());
1537 ACE_OS::printf (option
[STRCASECMP
] ? "if (charmap[*str] == **ptr && !ACE_OS::%s" : "if (*str == **ptr && !ACE_OS::%s",
1539 ? (option
[STRCASECMP
] ? "strncasecmp (str + 1, *ptr + 1, len - 1" : "strncmp (str + 1, *ptr + 1, len - 1")
1540 : (option
[STRCASECMP
] ? "strcasecmp (str + 1, *ptr + 1" : "strcmp (str + 1, *ptr + 1"));
1541 ACE_OS::printf ("))\n return %sptr;"
1542 "\n }\n }\n %s\n}\n", ACE_OS::strcmp (array_type_
,
1543 Key_List::default_array_type
) == 0 ? "*" : "", option
[OPTIMIZE
] ? "" : "}\n return 0;");
1547 if (option
[OPTIMIZE
])
1548 ACE_OS::printf (" return %swordlist[key]", option
[TYPE
] && option
[POINTER
] ? "&" : "");
1551 int pointer_and_type_enabled
= option
[POINTER
] && option
[TYPE
];
1553 ACE_OS::printf (" %schar *s = wordlist[key]", option
[CONSTANT
] || pointer_and_type_enabled
== 0 ? "const " : "");
1555 if (ACE_OS::strcmp (array_type_
, Key_List::default_array_type
) != 0)
1556 ACE_OS::printf (".%s", option
.key_name ());
1558 ACE_OS::printf (";\n\n if (%s%s == *s && !ACE_OS::%s)\n return %s",
1559 option
[LENTABLE
] ? "len == lengthtable[key]\n && " : "",
1560 option
[STRCASECMP
] ? "charmap[*str]" : "*str",
1562 ? (option
[STRCASECMP
] ? "strncasecmp (str + 1, s + 1, len - 1)" : "strncmp (str + 1, s + 1, len - 1)")
1563 : (option
[STRCASECMP
] ? "strcasecmp (str + 1, s + 1)" : "strcmp (str + 1, s + 1)"),
1564 option
[TYPE
] && option
[POINTER
] ? "&wordlist[key]" : "s");
1566 ACE_OS::printf (";\n }\n %s\n}\n", option
[OPTIMIZE
] ? "" : "}\n return 0;");
1570 // Output the table and the functions that map upper case into lower case!
1573 Key_List::output_strcasecmp ()
1575 ACE_OS::printf ("%s",
1576 "/* This array is designed for mapping upper and lower case letter\n"
1577 " * together for a case independent comparison. The mappings are\n"
1578 " * based upon ascii character sequences.\n */"
1579 "static char charmap[] = {\n"
1580 " '\\000', '\\001', '\\002', '\\003', '\\004', '\\005', '\\006', '\\007',\n"
1581 " '\\010', '\\011', '\\012', '\\013', '\\014', '\\015', '\\016', '\\017',\n"
1582 " '\\020', '\\021', '\\022', '\\023', '\\024', '\\025', '\\026', '\\027',\n"
1583 " '\\030', '\\031', '\\032', '\\033', '\\034', '\\035', '\\036', '\\037',\n"
1584 " '\\040', '\\041', '\\042', '\\043', '\\044', '\\045', '\\046', '\\047',\n"
1585 " '\\050', '\\051', '\\052', '\\053', '\\054', '\\055', '\\056', '\\057',\n"
1586 " '\\060', '\\061', '\\062', '\\063', '\\064', '\\065', '\\066', '\\067',\n"
1587 " '\\070', '\\071', '\\072', '\\073', '\\074', '\\075', '\\076', '\\077',\n"
1588 " '\\100', '\\141', '\\142', '\\143', '\\144', '\\145', '\\146', '\\147',\n"
1589 " '\\150', '\\151', '\\152', '\\153', '\\154', '\\155', '\\156', '\\157',\n"
1590 " '\\160', '\\161', '\\162', '\\163', '\\164', '\\165', '\\166', '\\167',\n"
1591 " '\\170', '\\171', '\\172', '\\133', '\\134', '\\135', '\\136', '\\137',\n"
1592 " '\\140', '\\141', '\\142', '\\143', '\\144', '\\145', '\\146', '\\147',\n"
1593 " '\\150', '\\151', '\\152', '\\153', '\\154', '\\155', '\\156', '\\157',\n"
1594 " '\\160', '\\161', '\\162', '\\163', '\\164', '\\165', '\\166', '\\167',\n"
1595 " '\\170', '\\171', '\\172', '\\173', '\\174', '\\175', '\\176', '\\177',\n"
1596 " '\\200', '\\201', '\\202', '\\203', '\\204', '\\205', '\\206', '\\207',\n"
1597 " '\\210', '\\211', '\\212', '\\213', '\\214', '\\215', '\\216', '\\217',\n"
1598 " '\\220', '\\221', '\\222', '\\223', '\\224', '\\225', '\\226', '\\227',\n"
1599 " '\\230', '\\231', '\\232', '\\233', '\\234', '\\235', '\\236', '\\237',\n"
1600 " '\\240', '\\241', '\\242', '\\243', '\\244', '\\245', '\\246', '\\247',\n"
1601 " '\\250', '\\251', '\\252', '\\253', '\\254', '\\255', '\\256', '\\257',\n"
1602 " '\\260', '\\261', '\\262', '\\263', '\\264', '\\265', '\\266', '\\267',\n"
1603 " '\\270', '\\271', '\\272', '\\273', '\\274', '\\275', '\\276', '\\277',\n"
1604 " '\\300', '\\341', '\\342', '\\343', '\\344', '\\345', '\\346', '\\347',\n"
1605 " '\\350', '\\351', '\\352', '\\353', '\\354', '\\355', '\\356', '\\357',\n"
1606 " '\\360', '\\361', '\\362', '\\363', '\\364', '\\365', '\\366', '\\367',\n"
1607 " '\\370', '\\371', '\\372', '\\333', '\\334', '\\335', '\\336', '\\337',\n"
1608 " '\\340', '\\341', '\\342', '\\343', '\\344', '\\345', '\\346', '\\347',\n"
1609 " '\\350', '\\351', '\\352', '\\353', '\\354', '\\355', '\\356', '\\357',\n"
1610 " '\\360', '\\361', '\\362', '\\363', '\\364', '\\365', '\\366', '\\367',\n"
1611 " '\\370', '\\371', '\\372', '\\373', '\\374', '\\375', '\\376', '\\377',\n};\n\nstatic int\n");
1614 ACE_OS::printf ("%s", option
[ANSI
]
1615 ? "strncasecmp (char *s1, char *s2, int n)"
1616 : "strncasecmp (s1, s2, n)\n char *s1, *s2;\n int n;");
1617 ACE_OS::printf ("\n{\n char *cm = charmap;\n\n while (--n >= 0 && cm[*s1] == cm[*s2++])\n"
1618 " if (*s1++ == '\\0')\n return 0;\n"
1619 "\n return n < 0 ? 0 : cm[*s1] - cm[*--s2];\n}\n\n");
1623 ACE_OS::printf ("%s", option
[ANSI
]
1624 ? "strcasecmp (char *s1, char *s2)"
1625 : "strcasecmp (s1, s2)\n char *s1, *s2;");
1626 ACE_OS::printf ("\n{\n char *cm = charmap;\n\n while (cm[*s1] == cm[*s2++])\n"
1627 " if (*s1++ == '\\0')\n return 0;\n"
1628 "\n return cm[*s1] - cm[*--s2];\n}\n\n");
1632 // Generates the hash function and the key word recognizer function
1633 // based upon the user's Options.
1638 if (option
[BINARYSEARCH
])
1639 // Generate code binary search.
1640 this->output_binary_search_function ();
1641 else if (option
[LINEARSEARCH
])
1642 // Generate code for linear search.
1643 this->output_linear_search_function ();
1646 // Generate the usual GPERF things.
1647 ACE_OS::printf ("%s\n", include_src
);
1649 // Get prototype for strncmp() and strcmp().
1650 if (!option
[SKIPSTRINGH
])
1651 ACE_OS::printf ("#include \"ace/OS_NS_string.h\"\n");
1653 // Output type declaration now, reference it later on....
1654 if (option
[TYPE
] && !option
[NOTYPE
])
1655 ACE_OS::printf ("%s;\n",
1660 if (option
[STRCASECMP
])
1661 output_strcasecmp ();
1663 // Class definition if -M is *not* enabled.
1664 if (option
[CPLUSPLUS
] && !option
[SKIPCLASS
])
1665 ACE_OS::printf ("class %s\n{\nprivate:\n"
1666 " static unsigned int %s (const char *str, unsigned int len);\npublic:\n"
1667 " static %s%s%s (const char *str, unsigned int len);\n};\n\n",
1668 option
.class_name (),
1669 option
.hash_name (),
1670 option
[CONSTANT
] ? "const " : "",
1672 option
.function_name ());
1674 output_hash_function ();
1680 if (option
[LENTABLE
] && option
[DUP
])
1682 output_keylength_table ();
1685 if (option
[POINTER
] && option
[TYPE
])
1687 output_keyword_table ();
1692 if (option
[LENTABLE
])
1694 output_keylength_table ();
1697 output_keyword_table ();
1699 if (output_lookup_array () == -1)
1701 ACE_ERROR_RETURN ((LM_DEBUG
,
1703 "output_lookup_array"),
1709 // Use the inline keyword to remove function overhead.
1712 ACE_OS::printf ("inline\n");
1715 int pointer_and_type_enabled
= option
[POINTER
] && option
[TYPE
];
1717 ACE_OS::printf ("%s%s\n",
1718 option
[CONSTANT
] || pointer_and_type_enabled
== 0 ? "const " : "",
1720 if (option
[CPLUSPLUS
])
1721 ACE_OS::printf ("%s::", option
.class_name ());
1723 ACE_OS::printf (option
[ANSI
]
1724 ? "%s (const char *str, unsigned int len)\n{\n"
1725 : "%s (str, len)\n char *str;\n unsigned int len;\n{\n",
1726 option
.function_name ());
1728 if (option
[ENUM
] && !option
[GLOBAL
])
1729 ACE_OS::printf (" enum\n {\n"
1730 " TOTAL_KEYWORDS = %d,\n"
1731 " MIN_WORD_LENGTH = %d,\n"
1732 " MAX_WORD_LENGTH = %d,\n"
1733 " MIN_HASH_VALUE = %d,\n"
1734 " MAX_HASH_VALUE = %d,\n"
1735 " HASH_VALUE_RANGE = %d,\n"
1736 " DUPLICATES = %d,\n"
1737 " WORDLIST_SIZE = %d\n };\n\n",
1738 total_keys
, min_key_len
, max_key_len
, min_hash_value
,
1739 max_hash_value
, max_hash_value
- min_hash_value
+ 1,
1740 total_duplicates
? total_duplicates
+ 1 : 0, total_keys
+ min_hash_value
);
1741 // Use the switch in place of lookup table.
1744 // Use the lookup table, in place of switch.
1747 if (!option
[GLOBAL
])
1749 if (option
[LENTABLE
])
1750 output_keylength_table ();
1751 output_keyword_table ();
1753 if (!option
[GLOBAL
])
1755 switch (output_lookup_array ())
1758 ACE_ERROR_RETURN ((LM_DEBUG
,
1760 "output_lookup_array"),
1764 output_lookup_function ();
1773 output_lookup_function ();
1776 if (additional_code
)
1788 ACE_OS::fflush (stdout
);
1793 // Sorts the keys by hash value.
1798 // By default, we sort via hashing.
1800 occurrence_sort
= 0;
1802 this->head
= merge_sort (this->head
);
1805 // Sorts the keys by normal strcmp.
1807 Key_List::string_sort ()
1809 // Flatten the equivalence class list to a linear list.
1812 for(ptr
=head
;ptr
;ptr
=ptr
->next
)
1817 List_Node
*last_node
= 0;
1819 for(curr
= ptr
->link
; curr
; curr
= curr
->link
)
1821 // Chnage the link to next pointer.
1822 curr
->next
= curr
->link
;
1824 // Save the pointer for the last node.
1825 if (curr
->link
== 0)
1829 // Set the pointers, correctly.
1830 last_node
->next
= ptr
->next
;
1831 ptr
->next
= ptr
->link
;
1836 // Set all links to Null.
1838 for(ptr
=head
;ptr
;ptr
=ptr
->next
)
1843 // Set the sorting options.
1847 occurrence_sort
= 0;
1851 this->head
= merge_sort (head
);
1856 // Dumps the key list to stderr stream.
1861 ACE_DEBUG ((LM_DEBUG
,
1862 "\nDumping key list information:\ntotal non-static linked keywords = %d"
1863 "\ntotal keywords = %d\ntotal duplicates = %d\nmaximum key length = %d\n",
1866 total_duplicates
? total_duplicates
+ 1 : 0,
1869 u_int keysig_width
= option
.max_keysig_size () > ACE_OS::strlen ("keysig")
1870 ? option
.max_keysig_size ()
1871 : static_cast<u_int
> (ACE_OS::strlen ("keysig"));
1873 size_t key_length
= this->max_key_length ();
1874 size_t keyword_width
= key_length
> ACE_OS::strlen ("keysig")
1876 : ACE_OS::strlen ("keysig");
1878 ACE_DEBUG ((LM_DEBUG
,
1879 "\nList contents are:\n(hash value, key length, slot, %*s, %*s, duplicates):\n",
1885 for (List_Node
*ptr
= head
; ptr
; ptr
= ptr
->next
)
1887 ACE_DEBUG ((LM_DEBUG
,
1888 "%11d,%11d,%6d, %*s, %*s",
1897 List_Node
*dup
= ptr
->link
;
1903 ACE_DEBUG ((LM_DEBUG
,
1907 ACE_DEBUG ((LM_DEBUG
,
1910 ACE_DEBUG ((LM_DEBUG
,
1911 "End dumping list.\n\n"));
1914 // Simple-minded constructor action here...
1916 Key_List::Key_List ()
1918 total_duplicates (0),
1919 array_type_ (dup_string (Key_List::default_array_type
)),
1920 return_type (dup_string (Key_List::default_return_type
)),
1921 struct_tag (dup_string (Key_List::default_array_type
)),
1922 max_key_len (INT_MIN
),
1923 min_key_len (INT_MAX
),
1925 additional_code (0),
1930 // Returns the length of entire key list.
1933 Key_List::keyword_list_length ()
1938 // Returns length of longest key read.
1941 Key_List::max_key_length ()