1/* Output routines.
2 Copyright (C) 1989-1998, 2000, 2002-2004, 2006-2007, 2009, 2011-2012, 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 "output.h"
23
24#include <stdio.h>
25#include <string.h> /* declares strncpy(), strchr() */
26#include <ctype.h> /* declares isprint() */
27#include <assert.h> /* defines assert() */
28#include <limits.h> /* defines SCHAR_MAX etc. */
29#include "options.h"
30#include "version.h"
31#include "config.h"
32
33/* ============================== Portability ============================== */
34
35/* Dynamically allocated array with dynamic extent:
36
37 Example:
38 DYNAMIC_ARRAY (my_array, int, n);
39 ...
40 FREE_DYNAMIC_ARRAY (my_array);
41
42 Attention: depending on your implementation my_array is either the array
43 itself or a pointer to the array! Always use my_array only as expression!
44 */
45#if HAVE_DYNAMIC_ARRAY
46 #define DYNAMIC_ARRAY(var,eltype,size) eltype var[size]
47 #define FREE_DYNAMIC_ARRAY(var)
48#else
49 #define DYNAMIC_ARRAY(var,eltype,size) eltype *var = new eltype[size]
50 #define FREE_DYNAMIC_ARRAY(var) delete[] var
51#endif
52
53/* ========================================================================= */
54
55/* The "register " storage-class specifier. */
56static const char *register_scs;
57
58/* The "const " qualifier. */
59static const char *const_always;
60
61/* The "const " qualifier, for read-only arrays. */
62static const char *const_readonly_array;
63
64/* The "const " qualifier, for the array type. */
65static const char *const_for_struct;
66
67/* Returns the smallest unsigned C type capable of holding integers
68 up to N. */
69
70static const char *
71smallest_integral_type (int n)
72{
73 if (n <= UCHAR_MAX) return "unsigned char";
74 if (n <= USHRT_MAX) return "unsigned short";
75 return "unsigned int";
76}
77
78/* Returns the smallest signed C type capable of holding integers
79 from MIN to MAX. */
80
81static const char *
82smallest_integral_type (int min, int max)
83{
84 if (option[ANSIC] | option[CPLUSPLUS])
85 if (min >= SCHAR_MIN && max <= SCHAR_MAX) return "signed char";
86 if (min >= SHRT_MIN && max <= SHRT_MAX) return "short";
87 return "int";
88}
89
90/* ------------------------------------------------------------------------- */
91
92/* Constructor.
93 Note about the keyword list starting at head:
94 - The list is ordered by increasing _hash_value. This has been achieved
95 by Search::sort().
96 - Duplicates, i.e. keywords with the same _selchars set, are chained
97 through the _duplicate_link pointer. Only one representative per
98 duplicate equivalence class remains on the linear keyword list.
99 - Accidental duplicates, i.e. keywords for which the _asso_values[] search
100 couldn't achieve different hash values, cannot occur on the linear
101 keyword list. Search::optimize would catch this mistake.
102 */
103Output::Output (KeywordExt_List *head, const char *struct_decl,
104 unsigned int struct_decl_lineno, const char *return_type,
105 const char *struct_tag, const char *verbatim_declarations,
106 const char *verbatim_declarations_end,
107 unsigned int verbatim_declarations_lineno,
108 const char *verbatim_code, const char *verbatim_code_end,
109 unsigned int verbatim_code_lineno, bool charset_dependent,
110 int total_keys, int max_key_len, int min_key_len,
111 bool hash_includes_len, const Positions& positions,
112 const unsigned int *alpha_inc, int total_duplicates,
113 unsigned int alpha_size, const int *asso_values)
114 : _head (head), _struct_decl (struct_decl),
115 _struct_decl_lineno (struct_decl_lineno), _return_type (return_type),
116 _struct_tag (struct_tag),
117 _verbatim_declarations (verbatim_declarations),
118 _verbatim_declarations_end (verbatim_declarations_end),
119 _verbatim_declarations_lineno (verbatim_declarations_lineno),
120 _verbatim_code (verbatim_code),
121 _verbatim_code_end (verbatim_code_end),
122 _verbatim_code_lineno (verbatim_code_lineno),
123 _charset_dependent (charset_dependent),
124 _total_keys (total_keys),
125 _max_key_len (max_key_len), _min_key_len (min_key_len),
126 _hash_includes_len (hash_includes_len),
127 _key_positions (positions), _alpha_inc (alpha_inc),
128 _total_duplicates (total_duplicates), _alpha_size (alpha_size),
129 _asso_values (asso_values)
130{
131}
132
133/* ------------------------------------------------------------------------- */
134
135/* Computes the minimum and maximum hash values, and stores them
136 in _min_hash_value and _max_hash_value. */
137
138void
139Output::compute_min_max ()
140{
141 /* Since the list is already sorted by hash value all we need to do is
142 to look at the first and the last element of the list. */
143
144 _min_hash_value = _head->first()->_hash_value;
145
146 KeywordExt_List *temp;
147 for (temp = _head; temp->rest(); temp = temp->rest())
148 ;
149 _max_hash_value = temp->first()->_hash_value;
150}
151
152/* ------------------------------------------------------------------------- */
153
154/* Returns the number of different hash values. */
155
156int
157Output::num_hash_values () const
158{
159 /* Since the list is already sorted by hash value and doesn't contain
160 duplicates, we can simply count the number of keywords on the list. */
161 int count = 0;
162 for (KeywordExt_List *temp = _head; temp; temp = temp->rest())
163 count++;
164 return count;
165}
166
167/* -------------------- Output_Constants and subclasses -------------------- */
168
169/* This class outputs an enumeration defining some constants. */
170
171struct Output_Constants
172{
173 virtual void output_start () = 0;
174 virtual void output_item (const char *name, int value) = 0;
175 virtual void output_end () = 0;
176 Output_Constants () {}
177 virtual ~Output_Constants () {}
178};
179
180/* This class outputs an enumeration in #define syntax. */
181
182struct Output_Defines : public Output_Constants
183{
184 virtual void output_start ();
185 virtual void output_item (const char *name, int value);
186 virtual void output_end ();
187 Output_Defines () {}
188 virtual ~Output_Defines () {}
189};
190
191void Output_Defines::output_start ()
192{
193 printf ("\n");
194}
195
196void Output_Defines::output_item (const char *name, int value)
197{
198 printf ("#define %s %d\n", name, value);
199}
200
201void Output_Defines::output_end ()
202{
203}
204
205/* This class outputs an enumeration using 'enum'. */
206
207struct Output_Enum : public Output_Constants
208{
209 virtual void output_start ();
210 virtual void output_item (const char *name, int value);
211 virtual void output_end ();
212 Output_Enum (const char *indent)
213 : _indentation (indent) {}
214 virtual ~Output_Enum () {}
215private:
216 const char *_indentation;
217 bool _pending_comma;
218};
219
220void Output_Enum::output_start ()
221{
222 printf ("%senum\n"
223 "%s {\n",
224 _indentation, _indentation);
225 _pending_comma = false;
226}
227
228void Output_Enum::output_item (const char *name, int value)
229{
230 if (_pending_comma)
231 printf (",\n");
232 printf ("%s %s = %d", _indentation, name, value);
233 _pending_comma = true;
234}
235
236void Output_Enum::output_end ()
237{
238 if (_pending_comma)
239 printf ("\n");
240 printf ("%s };\n\n", _indentation);
241}
242
243/* Outputs a constant in the given style. */
244
245static void
246output_constant (struct Output_Constants& style, const char *name, int value)
247{
248 const char *prefix = option.get_constants_prefix ();
249 DYNAMIC_ARRAY (combined_name, char, strlen (prefix) + strlen (name) + 1);
250 strcpy (combined_name, prefix);
251 strcpy (combined_name + strlen (prefix), name);
252 style.output_item (combined_name, value);
253 FREE_DYNAMIC_ARRAY (combined_name);
254}
255
256/* Outputs the maximum and minimum hash values etc. */
257
258void
259Output::output_constants (struct Output_Constants& style) const
260{
261 style.output_start ();
262 output_constant (style, "TOTAL_KEYWORDS", _total_keys);
263 output_constant (style, "MIN_WORD_LENGTH", _min_key_len);
264 output_constant (style, "MAX_WORD_LENGTH", _max_key_len);
265 output_constant (style, "MIN_HASH_VALUE", _min_hash_value);
266 output_constant (style, "MAX_HASH_VALUE", _max_hash_value);
267 style.output_end ();
268}
269
270/* ------------------------------------------------------------------------- */
271
272/* We use a downcase table because when called repeatedly, the code
273 gperf_downcase[c]
274 is faster than
275 if (c >= 'A' && c <= 'Z')
276 c += 'a' - 'A';
277 */
278#define USE_DOWNCASE_TABLE 1
279
280#if USE_DOWNCASE_TABLE
281
282/* Output gperf's ASCII-downcase table. */
283
284static void
285output_upperlower_table ()
286{
287 unsigned int c;
288
289 printf ("#ifndef GPERF_DOWNCASE\n"
290 "#define GPERF_DOWNCASE 1\n"
291 "static unsigned char gperf_downcase[256] =\n"
292 " {");
293 for (c = 0; c < 256; c++)
294 {
295 if ((c % 15) == 0)
296 printf ("\n ");
297 printf (" %3d", c >= 'A' && c <= 'Z' ? c + 'a' - 'A' : c);
298 if (c < 255)
299 printf (",");
300 }
301 printf ("\n"
302 " };\n"
303 "#endif\n\n");
304}
305
306#endif
307
308/* Output gperf's ASCII-case insensitive strcmp replacement. */
309
310static void
311output_upperlower_strcmp ()
312{
313 printf ("#ifndef GPERF_CASE_STRCMP\n"
314 "#define GPERF_CASE_STRCMP 1\n"
315 "static int\n"
316 "gperf_case_strcmp ");
317 printf (option[KRC] ?
318 "(s1, s2)\n"
319 " %schar *s1;\n"
320 " %schar *s2;\n" :
321 option[C] ?
322 "(s1, s2)\n"
323 " %sconst char *s1;\n"
324 " %sconst char *s2;\n" :
325 option[ANSIC] | option[CPLUSPLUS] ?
326 "(%sconst char *s1, %sconst char *s2)\n" :
327 "",
328 register_scs, register_scs);
329 #if USE_DOWNCASE_TABLE
330 printf ("{\n"
331 " for (;;)\n"
332 " {\n"
333 " unsigned char c1 = gperf_downcase[(unsigned char)*s1++];\n"
334 " unsigned char c2 = gperf_downcase[(unsigned char)*s2++];\n"
335 " if (c1 != 0 && c1 == c2)\n"
336 " continue;\n"
337 " return (int)c1 - (int)c2;\n"
338 " }\n"
339 "}\n");
340 #else
341 printf ("{\n"
342 " for (;;)\n"
343 " {\n"
344 " unsigned char c1 = *s1++;\n"
345 " unsigned char c2 = *s2++;\n"
346 " if (c1 >= 'A' && c1 <= 'Z')\n"
347 " c1 += 'a' - 'A';\n"
348 " if (c2 >= 'A' && c2 <= 'Z')\n"
349 " c2 += 'a' - 'A';\n"
350 " if (c1 != 0 && c1 == c2)\n"
351 " continue;\n"
352 " return (int)c1 - (int)c2;\n"
353 " }\n"
354 "}\n");
355 #endif
356 printf ("#endif\n\n");
357}
358
359/* Output gperf's ASCII-case insensitive strncmp replacement. */
360
361static void
362output_upperlower_strncmp ()
363{
364 printf ("#ifndef GPERF_CASE_STRNCMP\n"
365 "#define GPERF_CASE_STRNCMP 1\n"
366 "static int\n"
367 "gperf_case_strncmp ");
368 printf (option[KRC] ?
369 "(s1, s2, n)\n"
370 " %schar *s1;\n"
371 " %schar *s2;\n"
372 " %ssize_t n;\n" :
373 option[C] ?
374 "(s1, s2, n)\n"
375 " %sconst char *s1;\n"
376 " %sconst char *s2;\n"
377 " %ssize_t n;\n" :
378 option[ANSIC] | option[CPLUSPLUS] ?
379 "(%sconst char *s1, %sconst char *s2, %ssize_t n)\n" :
380 "",
381 register_scs, register_scs, register_scs);
382 #if USE_DOWNCASE_TABLE
383 printf ("{\n"
384 " for (; n > 0;)\n"
385 " {\n"
386 " unsigned char c1 = gperf_downcase[(unsigned char)*s1++];\n"
387 " unsigned char c2 = gperf_downcase[(unsigned char)*s2++];\n"
388 " if (c1 != 0 && c1 == c2)\n"
389 " {\n"
390 " n--;\n"
391 " continue;\n"
392 " }\n"
393 " return (int)c1 - (int)c2;\n"
394 " }\n"
395 " return 0;\n"
396 "}\n");
397 #else
398 printf ("{\n"
399 " for (; n > 0;)\n"
400 " {\n"
401 " unsigned char c1 = *s1++;\n"
402 " unsigned char c2 = *s2++;\n"
403 " if (c1 >= 'A' && c1 <= 'Z')\n"
404 " c1 += 'a' - 'A';\n"
405 " if (c2 >= 'A' && c2 <= 'Z')\n"
406 " c2 += 'a' - 'A';\n"
407 " if (c1 != 0 && c1 == c2)\n"
408 " {\n"
409 " n--;\n"
410 " continue;\n"
411 " }\n"
412 " return (int)c1 - (int)c2;\n"
413 " }\n"
414 " return 0;\n"
415 "}\n");
416 #endif
417 printf ("#endif\n\n");
418}
419
420/* Output gperf's ASCII-case insensitive memcmp replacement. */
421
422static void
423output_upperlower_memcmp ()
424{
425 printf ("#ifndef GPERF_CASE_MEMCMP\n"
426 "#define GPERF_CASE_MEMCMP 1\n"
427 "static int\n"
428 "gperf_case_memcmp ");
429 printf (option[KRC] ?
430 "(s1, s2, n)\n"
431 " %schar *s1;\n"
432 " %schar *s2;\n"
433 " %ssize_t n;\n" :
434 option[C] ?
435 "(s1, s2, n)\n"
436 " %sconst char *s1;\n"
437 " %sconst char *s2;\n"
438 " %ssize_t n;\n" :
439 option[ANSIC] | option[CPLUSPLUS] ?
440 "(%sconst char *s1, %sconst char *s2, %ssize_t n)\n" :
441 "",
442 register_scs, register_scs, register_scs);
443 #if USE_DOWNCASE_TABLE
444 printf ("{\n"
445 " for (; n > 0;)\n"
446 " {\n"
447 " unsigned char c1 = gperf_downcase[(unsigned char)*s1++];\n"
448 " unsigned char c2 = gperf_downcase[(unsigned char)*s2++];\n"
449 " if (c1 == c2)\n"
450 " {\n"
451 " n--;\n"
452 " continue;\n"
453 " }\n"
454 " return (int)c1 - (int)c2;\n"
455 " }\n"
456 " return 0;\n"
457 "}\n");
458 #else
459 printf ("{\n"
460 " for (; n > 0;)\n"
461 " {\n"
462 " unsigned char c1 = *s1++;\n"
463 " unsigned char c2 = *s2++;\n"
464 " if (c1 >= 'A' && c1 <= 'Z')\n"
465 " c1 += 'a' - 'A';\n"
466 " if (c2 >= 'A' && c2 <= 'Z')\n"
467 " c2 += 'a' - 'A';\n"
468 " if (c1 == c2)\n"
469 " {\n"
470 " n--;\n"
471 " continue;\n"
472 " }\n"
473 " return (int)c1 - (int)c2;\n"
474 " }\n"
475 " return 0;\n"
476 "}\n");
477 #endif
478 printf ("#endif\n\n");
479}
480
481/* ------------------------------------------------------------------------- */
482
483/* Outputs a keyword, as a string: enclosed in double quotes, escaping
484 backslashes, double quote and unprintable characters. */
485
486static void
487output_string (const char *key, int len)
488{
489 putchar ('"');
490 for (; len > 0; len--)
491 {
492 unsigned char c = static_cast<unsigned char>(*key++);
493 if (isprint (c))
494 {
495 if (c == '"' || c == '\\')
496 putchar ('\\');
497 putchar (c);
498 }
499 else
500 {
501 /* Use octal escapes, not hexadecimal escapes, because some old
502 C compilers didn't understand hexadecimal escapes, and because
503 hexadecimal escapes are not limited to 2 digits, thus needing
504 special care if the following character happens to be a digit. */
505 putchar ('\\');
506 putchar ('0' + ((c >> 6) & 7));
507 putchar ('0' + ((c >> 3) & 7));
508 putchar ('0' + (c & 7));
509 }
510 }
511 putchar ('"');
512}
513
514/* ------------------------------------------------------------------------- */
515
516/* Outputs a #line directive, referring to the given line number. */
517
518static void
519output_line_directive (unsigned int lineno)
520{
521 const char *file_name = option.get_input_file_name ();
522 if (file_name != NULL)
523 {
524 printf ("#line %u ", lineno);
525 output_string (file_name, strlen (file_name));
526 printf ("\n");
527 }
528}
529
530/* ------------------------------------------------------------------------- */
531
532/* Outputs a type and a const specifier (i.e. "const " or "").
533 The output is terminated with a space. */
534
535static void
536output_const_type (const char *const_string, const char *type_string)
537{
538 if (type_string[strlen(type_string)-1] == '*')
539 /* For pointer types, put the 'const' after the type. */
540 printf ("%s %s", type_string, const_string);
541 else
542 /* For scalar or struct types, put the 'const' before the type. */
543 printf ("%s%s ", const_string, type_string);
544}
545
546/* ----------------------- Output_Expr and subclasses ----------------------- */
547
548/* This class outputs a general expression. */
549
550struct Output_Expr
551{
552 virtual void output_expr () const = 0;
553 Output_Expr () {}
554 virtual ~Output_Expr () {}
555};
556
557/* This class outputs an expression formed by a single string. */
558
559struct Output_Expr1 : public Output_Expr
560{
561 virtual void output_expr () const;
562 Output_Expr1 (const char *piece1) : _p1 (piece1) {}
563 virtual ~Output_Expr1 () {}
564private:
565 const char *_p1;
566};
567
568void Output_Expr1::output_expr () const
569{
570 printf ("%s", _p1);
571}
572
573#if 0 /* unused */
574
575/* This class outputs an expression formed by the concatenation of two
576 strings. */
577
578struct Output_Expr2 : public Output_Expr
579{
580 virtual void output_expr () const;
581 Output_Expr2 (const char *piece1, const char *piece2)
582 : _p1 (piece1), _p2 (piece2) {}
583 virtual ~Output_Expr2 () {}
584private:
585 const char *_p1;
586 const char *_p2;
587};
588
589void Output_Expr2::output_expr () const
590{
591 printf ("%s%s", _p1, _p2);
592}
593
594#endif
595
596/* --------------------- Output_Compare and subclasses --------------------- */
597
598/* This class outputs a comparison expression. */
599
600struct Output_Compare
601{
602 /* Outputs the comparison expression.
603 expr1 outputs a simple expression of type 'const char *' referring to
604 the string being looked up. expr2 outputs a simple expression of type
605 'const char *' referring to the constant string stored in the gperf
606 generated hash table. */
607 virtual void output_comparison (const Output_Expr& expr1,
608 const Output_Expr& expr2) const = 0;
609 /* Outputs the comparison expression for the first byte.
610 Returns true if the this comparison is complete. */
611 bool output_firstchar_comparison (const Output_Expr& expr1,
612 const Output_Expr& expr2) const;
613 Output_Compare () {}
614 virtual ~Output_Compare () {}
615};
616
617bool Output_Compare::output_firstchar_comparison (const Output_Expr& expr1,
618 const Output_Expr& expr2) const
619{
620 /* First, we emit a comparison of the first byte of the two strings.
621 This catches most cases where the string being looked up is not in the
622 hash table but happens to have the same hash code as an element of the
623 hash table. */
624 if (option[UPPERLOWER])
625 {
626 /* Incomplete comparison, just for speedup. */
627 printf ("(((unsigned char)*");
628 expr1.output_expr ();
629 printf (" ^ (unsigned char)*");
630 expr2.output_expr ();
631 printf (") & ~32) == 0");
632 return false;
633 }
634 else
635 {
636 /* Complete comparison. */
637 printf ("*");
638 expr1.output_expr ();
639 printf (" == *");
640 expr2.output_expr ();
641 return true;
642 }
643}
644
645/* This class outputs a comparison using strcmp. */
646
647struct Output_Compare_Strcmp : public Output_Compare
648{
649 virtual void output_comparison (const Output_Expr& expr1,
650 const Output_Expr& expr2) const;
651 Output_Compare_Strcmp () {}
652 virtual ~Output_Compare_Strcmp () {}
653};
654
655void Output_Compare_Strcmp::output_comparison (const Output_Expr& expr1,
656 const Output_Expr& expr2) const
657{
658 bool firstchar_done = output_firstchar_comparison (expr1, expr2);
659 printf (" && !");
660 if (option[UPPERLOWER])
661 printf ("gperf_case_");
662 printf ("strcmp (");
663 if (firstchar_done)
664 {
665 expr1.output_expr ();
666 printf (" + 1, ");
667 expr2.output_expr ();
668 printf (" + 1");
669 }
670 else
671 {
672 expr1.output_expr ();
673 printf (", ");
674 expr2.output_expr ();
675 }
676 printf (")");
677}
678
679/* This class outputs a comparison using strncmp.
680 Note that the length of expr1 will be available through the local variable
681 'len'. */
682
683struct Output_Compare_Strncmp : public Output_Compare
684{
685 virtual void output_comparison (const Output_Expr& expr1,
686 const Output_Expr& expr2) const;
687 Output_Compare_Strncmp () {}
688 virtual ~Output_Compare_Strncmp () {}
689};
690
691void Output_Compare_Strncmp::output_comparison (const Output_Expr& expr1,
692 const Output_Expr& expr2) const
693{
694 bool firstchar_done = output_firstchar_comparison (expr1, expr2);
695 printf (" && !");
696 if (option[UPPERLOWER])
697 printf ("gperf_case_");
698 printf ("strncmp (");
699 if (firstchar_done)
700 {
701 expr1.output_expr ();
702 printf (" + 1, ");
703 expr2.output_expr ();
704 printf (" + 1, len - 1");
705 }
706 else
707 {
708 expr1.output_expr ();
709 printf (", ");
710 expr2.output_expr ();
711 printf (", len");
712 }
713 printf (") && ");
714 expr2.output_expr ();
715 printf ("[len] == '\\0'");
716}
717
718/* This class outputs a comparison using memcmp.
719 Note that the length of expr1 (available through the local variable 'len')
720 must be verified to be equal to the length of expr2 prior to this
721 comparison. */
722
723struct Output_Compare_Memcmp : public Output_Compare
724{
725 virtual void output_comparison (const Output_Expr& expr1,
726 const Output_Expr& expr2) const;
727 Output_Compare_Memcmp () {}
728 virtual ~Output_Compare_Memcmp () {}
729};
730
731void Output_Compare_Memcmp::output_comparison (const Output_Expr& expr1,
732 const Output_Expr& expr2) const
733{
734 bool firstchar_done = output_firstchar_comparison (expr1, expr2);
735 printf (" && !");
736 if (option[UPPERLOWER])
737 printf ("gperf_case_");
738 printf ("memcmp (");
739 if (firstchar_done)
740 {
741 expr1.output_expr ();
742 printf (" + 1, ");
743 expr2.output_expr ();
744 printf (" + 1, len - 1");
745 }
746 else
747 {
748 expr1.output_expr ();
749 printf (", ");
750 expr2.output_expr ();
751 printf (", len");
752 }
753 printf (")");
754}
755
756/* ------------------------------------------------------------------------- */
757
758/* Generates a C expression for an asso_values[] index. */
759
760void
761Output::output_asso_values_index (int pos) const
762{
763 if (pos == Positions::LASTCHAR)
764 printf ("str[len - 1]");
765 else
766 {
767 printf ("str[%d]", pos);
768 if (_alpha_inc[pos])
769 printf ("+%u", _alpha_inc[pos]);
770 }
771}
772
773/* Generates a C expression for an asso_values[] reference. */
774
775void
776Output::output_asso_values_ref (int pos) const
777{
778 printf ("asso_values[");
779 /* Always cast to unsigned char. This is necessary when the alpha_inc
780 is nonzero, and also avoids a gcc warning "subscript has type 'char'". */
781 if (option[CPLUSPLUS])
782 {
783 /* In C++, a C style cast may lead to a 'warning: use of old-style cast'.
784 Therefore prefer the C++ style cast syntax. */
785 printf ("static_cast<unsigned char>(");
786 output_asso_values_index (pos);
787 printf (")");
788 }
789 else
790 {
791 printf ("(unsigned char)");
792 output_asso_values_index (pos);
793 }
794 printf ("]");
795}
796
797/* Generates C code for the hash function that returns the
798 proper encoding for each keyword.
799 The hash function has the signature
800 unsigned int <hash> (const char *str, size_t len). */
801
802void
803Output::output_hash_function () const
804{
805 /* Output the function's head. */
806 if (option[CPLUSPLUS])
807 printf ("inline ");
808 else if (option[KRC] | option[C] | option[ANSIC])
809 printf ("#ifdef __GNUC__\n"
810 "__inline\n"
811 "#else\n"
812 "#ifdef __cplusplus\n"
813 "inline\n"
814 "#endif\n"
815 "#endif\n");
816
817 if (/* The function does not use the 'str' argument? */
818 _key_positions.get_size() == 0
819 || /* The function uses 'str', but not the 'len' argument? */
820 (!_hash_includes_len
821 && _key_positions[0] < _min_key_len
822 && _key_positions[_key_positions.get_size() - 1] != Positions::LASTCHAR))
823 /* Pacify lint. */
824 printf ("/*ARGSUSED*/\n");
825
826 if (option[KRC] | option[C] | option[ANSIC])
827 printf ("static ");
828 printf ("unsigned int\n");
829 if (option[CPLUSPLUS])
830 printf ("%s::", option.get_class_name ());
831 printf ("%s ", option.get_hash_name ());
832 printf (option[KRC] ?
833 "(str, len)\n"
834 " %schar *str;\n"
835 " %ssize_t len;\n" :
836 option[C] ?
837 "(str, len)\n"
838 " %sconst char *str;\n"
839 " %ssize_t len;\n" :
840 option[ANSIC] | option[CPLUSPLUS] ?
841 "(%sconst char *str, %ssize_t len)\n" :
842 "",
843 register_scs, register_scs);
844
845 /* Note that when the hash function is called, it has already been verified
846 that min_key_len <= len <= max_key_len. */
847
848 /* Output the function's body. */
849 printf ("{\n");
850
851 /* First the asso_values array. */
852 if (_key_positions.get_size() > 0)
853 {
854 printf (" static %s%s asso_values[] =\n"
855 " {",
856 const_readonly_array,
857 smallest_integral_type (_max_hash_value + 1));
858
859 const int columns = 10;
860
861 /* Calculate maximum number of digits required for MAX_HASH_VALUE. */
862 int field_width = 2;
863 for (int trunc = _max_hash_value; (trunc /= 10) > 0;)
864 field_width++;
865
866 for (unsigned int count = 0; count < _alpha_size; count++)
867 {
868 if (count > 0)
869 printf (",");
870 if ((count % columns) == 0)
871 printf ("\n ");
872 printf ("%*d", field_width, _asso_values[count]);
873 }
874
875 printf ("\n"
876 " };\n");
877 }
878
879 if (_key_positions.get_size() == 0)
880 {
881 /* Trivial case: No key positions at all. */
882 printf (" return %s;\n",
883 _hash_includes_len ? "len" : "0");
884 }
885 else
886 {
887 /* Iterate through the key positions. Remember that Positions::sort()
888 has sorted them in decreasing order, with Positions::LASTCHAR coming
889 last. */
890 PositionIterator iter = _key_positions.iterator(_max_key_len);
891 int key_pos;
892
893 /* Get the highest key position. */
894 key_pos = iter.next ();
895
896 if (key_pos == Positions::LASTCHAR || key_pos < _min_key_len)
897 {
898 /* We can perform additional optimizations here:
899 Write it out as a single expression. Note that the values
900 are added as 'int's even though the asso_values array may
901 contain 'unsigned char's or 'unsigned short's. */
902
903 printf (" return %s",
904 _hash_includes_len ? "len + " : "");
905
906 if (_key_positions.get_size() == 2
907 && _key_positions[0] == 0
908 && _key_positions[1] == Positions::LASTCHAR)
909 /* Optimize special case of "-k 1,$". */
910 {
911 output_asso_values_ref (Positions::LASTCHAR);
912 printf (" + ");
913 output_asso_values_ref (0);
914 }
915 else
916 {
917 for (; key_pos != Positions::LASTCHAR; )
918 {
919 output_asso_values_ref (key_pos);
920 if ((key_pos = iter.next ()) != PositionIterator::EOS)
921 printf (" + ");
922 else
923 break;
924 }
925
926 if (key_pos == Positions::LASTCHAR)
927 output_asso_values_ref (Positions::LASTCHAR);
928 }
929
930 printf (";\n");
931 }
932 else
933 {
934 /* We've got to use the correct, but brute force, technique. */
935 /* It doesn't really matter whether hval is an 'int' or
936 'unsigned int', but 'unsigned int' gives fewer warnings. */
937 printf (" %sunsigned int hval = %s;\n\n"
938 " switch (%s)\n"
939 " {\n"
940 " default:\n",
941 register_scs, _hash_includes_len ? "len" : "0",
942 _hash_includes_len ? "hval" : "len");
943
944 while (key_pos != Positions::LASTCHAR && key_pos >= _max_key_len)
945 if ((key_pos = iter.next ()) == PositionIterator::EOS)
946 break;
947
948 if (key_pos != PositionIterator::EOS && key_pos != Positions::LASTCHAR)
949 {
950 int i = key_pos;
951 do
952 {
953 if (i > key_pos)
954 printf (" /*FALLTHROUGH*/\n"); /* Pacify lint. */
955 for ( ; i > key_pos; i--)
956 printf (" case %d:\n", i);
957
958 printf (" hval += ");
959 output_asso_values_ref (key_pos);
960 printf (";\n");
961
962 key_pos = iter.next ();
963 }
964 while (key_pos != PositionIterator::EOS && key_pos != Positions::LASTCHAR);
965
966 if (i >= _min_key_len)
967 printf (" /*FALLTHROUGH*/\n"); /* Pacify lint. */
968 for ( ; i >= _min_key_len; i--)
969 printf (" case %d:\n", i);
970 }
971
972 printf (" break;\n"
973 " }\n"
974 " return hval");
975 if (key_pos == Positions::LASTCHAR)
976 {
977 printf (" + ");
978 output_asso_values_ref (Positions::LASTCHAR);
979 }
980 printf (";\n");
981 }
982 }
983 printf ("}\n\n");
984}
985
986/* ------------------------------------------------------------------------- */
987
988/* Prints out a table of keyword lengths, for use with the
989 comparison code in generated function 'in_word_set'.
990 Only called if option[LENTABLE]. */
991
992void
993Output::output_keylength_table () const
994{
995 const int columns = 14;
996 const char * const indent = option[GLOBAL] ? "" : " ";
997
998 printf ("%sstatic %s%s %s[] =\n"
999 "%s {",
1000 indent, const_readonly_array,
1001 smallest_integral_type (_max_key_len),
1002 option.get_lengthtable_name (),
1003 indent);
1004
1005 /* Generate an array of lengths, similar to output_keyword_table. */
1006 int index;
1007 int column;
1008 KeywordExt_List *temp;
1009
1010 column = 0;
1011 for (temp = _head, index = 0; temp; temp = temp->rest())
1012 {
1013 KeywordExt *keyword = temp->first();
1014
1015 /* If generating a switch statement, and there is no user defined type,
1016 we generate non-duplicates directly in the code. Only duplicates go
1017 into the table. */
1018 if (option[SWITCH] && !option[TYPE] && !keyword->_duplicate_link)
1019 continue;
1020
1021 if (index < keyword->_hash_value && !option[SWITCH] && !option[DUP])
1022 {
1023 /* Some blank entries. */
1024 for ( ; index < keyword->_hash_value; index++)
1025 {
1026 if (index > 0)
1027 printf (",");
1028 if ((column++ % columns) == 0)
1029 printf ("\n%s ", indent);
1030 printf ("%3d", 0);
1031 }
1032 }
1033
1034 if (index > 0)
1035 printf (",");
1036 if ((column++ % columns) == 0)
1037 printf("\n%s ", indent);
1038 printf ("%3d", keyword->_allchars_length);
1039 index++;
1040
1041 /* Deal with duplicates specially. */
1042 if (keyword->_duplicate_link) // implies option[DUP]
1043 for (KeywordExt *links = keyword->_duplicate_link; links; links = links->_duplicate_link)
1044 {
1045 printf (",");
1046 if ((column++ % columns) == 0)
1047 printf("\n%s ", indent);
1048 printf ("%3d", links->_allchars_length);
1049 index++;
1050 }
1051 }
1052
1053 printf ("\n%s };\n", indent);
1054 if (option[GLOBAL])
1055 printf ("\n");
1056}
1057
1058/* ------------------------------------------------------------------------- */
1059
1060/* Prints out the string pool, containing the strings of the keyword table.
1061 Only called if option[SHAREDLIB]. */
1062
1063void
1064Output::output_string_pool () const
1065{
1066 const char * const indent = option[TYPE] || option[GLOBAL] ? "" : " ";
1067 int index;
1068 KeywordExt_List *temp;
1069
1070 printf ("%sstruct %s_t\n"
1071 "%s {\n",
1072 indent, option.get_stringpool_name (), indent);
1073 for (temp = _head, index = 0; temp; temp = temp->rest())
1074 {
1075 KeywordExt *keyword = temp->first();
1076
1077 /* If generating a switch statement, and there is no user defined type,
1078 we generate non-duplicates directly in the code. Only duplicates go
1079 into the table. */
1080 if (option[SWITCH] && !option[TYPE] && !keyword->_duplicate_link)
1081 continue;
1082
1083 if (!option[SWITCH] && !option[DUP])
1084 index = keyword->_hash_value;
1085
1086 printf ("%s char %s_str%d[sizeof(",
1087 indent, option.get_stringpool_name (), index);
1088 output_string (keyword->_allchars, keyword->_allchars_length);
1089 printf (")];\n");
1090
1091 /* Deal with duplicates specially. */
1092 if (keyword->_duplicate_link) // implies option[DUP]
1093 for (KeywordExt *links = keyword->_duplicate_link; links; links = links->_duplicate_link)
1094 if (!(links->_allchars_length == keyword->_allchars_length
1095 && memcmp (links->_allchars, keyword->_allchars,
1096 keyword->_allchars_length) == 0))
1097 {
1098 index++;
1099 printf ("%s char %s_str%d[sizeof(",
1100 indent, option.get_stringpool_name (), index);
1101 output_string (links->_allchars, links->_allchars_length);
1102 printf (")];\n");
1103 }
1104
1105 index++;
1106 }
1107 printf ("%s };\n",
1108 indent);
1109
1110 printf ("%sstatic %sstruct %s_t %s_contents =\n"
1111 "%s {\n",
1112 indent, const_readonly_array, option.get_stringpool_name (),
1113 option.get_stringpool_name (), indent);
1114 for (temp = _head, index = 0; temp; temp = temp->rest())
1115 {
1116 KeywordExt *keyword = temp->first();
1117
1118 /* If generating a switch statement, and there is no user defined type,
1119 we generate non-duplicates directly in the code. Only duplicates go
1120 into the table. */
1121 if (option[SWITCH] && !option[TYPE] && !keyword->_duplicate_link)
1122 continue;
1123
1124 if (index > 0)
1125 printf (",\n");
1126
1127 if (!option[SWITCH] && !option[DUP])
1128 index = keyword->_hash_value;
1129
1130 printf ("%s ",
1131 indent);
1132 output_string (keyword->_allchars, keyword->_allchars_length);
1133
1134 /* Deal with duplicates specially. */
1135 if (keyword->_duplicate_link) // implies option[DUP]
1136 for (KeywordExt *links = keyword->_duplicate_link; links; links = links->_duplicate_link)
1137 if (!(links->_allchars_length == keyword->_allchars_length
1138 && memcmp (links->_allchars, keyword->_allchars,
1139 keyword->_allchars_length) == 0))
1140 {
1141 index++;
1142 printf (",\n");
1143 printf ("%s ",
1144 indent);
1145 output_string (links->_allchars, links->_allchars_length);
1146 }
1147
1148 index++;
1149 }
1150 if (index > 0)
1151 printf ("\n");
1152 printf ("%s };\n",
1153 indent);
1154 printf ("%s#define %s ((%schar *) &%s_contents)\n",
1155 indent, option.get_stringpool_name (), const_always,
1156 option.get_stringpool_name ());
1157 if (option[GLOBAL])
1158 printf ("\n");
1159}
1160
1161/* ------------------------------------------------------------------------- */
1162
1163static void
1164output_keyword_entry (KeywordExt *temp, int stringpool_index, const char *indent)
1165{
1166 if (option[TYPE])
1167 output_line_directive (temp->_lineno);
1168 printf ("%s ", indent);
1169 if (option[TYPE])
1170 printf ("{");
1171 if (option[SHAREDLIB])
1172 /* How to determine a certain offset in stringpool at compile time?
1173 - The standard way would be to use the 'offsetof' macro. But it is only
1174 defined in <stddef.h>, and <stddef.h> is not among the prerequisite
1175 header files that the user must #include.
1176 - The next best way would be to take the address and cast to 'intptr_t'
1177 or 'uintptr_t'. But these types are only defined in <stdint.h>, and
1178 <stdint.h> is not among the prerequisite header files that the user
1179 must #include.
1180 - The next best approximation of 'uintptr_t' is 'size_t'. It is defined
1181 in the prerequisite header <string.h>.
1182 - The types 'long' and 'unsigned long' do work as well, but on 64-bit
1183 native Windows platforms, they don't have the same size as pointers
1184 and therefore generate warnings. */
1185 printf ("(int)(size_t)&((struct %s_t *)0)->%s_str%d",
1186 option.get_stringpool_name (), option.get_stringpool_name (),
1187 stringpool_index);
1188 else
1189 output_string (temp->_allchars, temp->_allchars_length);
1190 if (option[TYPE])
1191 {
1192 if (strlen (temp->_rest) > 0)
1193 printf (",%s", temp->_rest);
1194 printf ("}");
1195 }
1196 if (option[DEBUG])
1197 printf (" /* hash value = %d, index = %d */",
1198 temp->_hash_value, temp->_final_index);
1199}
1200
1201static void
1202output_keyword_blank_entries (int count, const char *indent)
1203{
1204 int columns;
1205 if (option[TYPE])
1206 {
1207 columns = 58 / (4 + (option[SHAREDLIB] ? 2 : option[NULLSTRINGS] ? 8 : 2)
1208 + strlen (option.get_initializer_suffix()));
1209 if (columns == 0)
1210 columns = 1;
1211 }
1212 else
1213 {
1214 columns = (option[SHAREDLIB] ? 9 : option[NULLSTRINGS] ? 4 : 9);
1215 }
1216 int column = 0;
1217 for (int i = 0; i < count; i++)
1218 {
1219 if ((column % columns) == 0)
1220 {
1221 if (i > 0)
1222 printf (",\n");
1223 printf ("%s ", indent);
1224 }
1225 else
1226 {
1227 if (i > 0)
1228 printf (", ");
1229 }
1230 if (option[TYPE])
1231 printf ("{");
1232 if (option[SHAREDLIB])
1233 printf ("-1");
1234 else
1235 {
1236 if (option[NULLSTRINGS])
1237 printf ("(char*)0");
1238 else
1239 printf ("\"\"");
1240 }
1241 if (option[TYPE])
1242 printf ("%s}", option.get_initializer_suffix());
1243 column++;
1244 }
1245}
1246
1247/* Prints out the array containing the keywords for the hash function. */
1248
1249void
1250Output::output_keyword_table () const
1251{
1252 const char *indent = option[GLOBAL] ? "" : " ";
1253 int index;
1254 KeywordExt_List *temp;
1255
1256 printf ("%sstatic ",
1257 indent);
1258 output_const_type (const_readonly_array, _wordlist_eltype);
1259 printf ("%s[] =\n"
1260 "%s {\n",
1261 option.get_wordlist_name (),
1262 indent);
1263
1264 /* Generate an array of reserved words at appropriate locations. */
1265
1266 for (temp = _head, index = 0; temp; temp = temp->rest())
1267 {
1268 KeywordExt *keyword = temp->first();
1269
1270 /* If generating a switch statement, and there is no user defined type,
1271 we generate non-duplicates directly in the code. Only duplicates go
1272 into the table. */
1273 if (option[SWITCH] && !option[TYPE] && !keyword->_duplicate_link)
1274 continue;
1275
1276 if (index > 0)
1277 printf (",\n");
1278
1279 if (index < keyword->_hash_value && !option[SWITCH] && !option[DUP])
1280 {
1281 /* Some blank entries. */
1282 output_keyword_blank_entries (keyword->_hash_value - index, indent);
1283 printf (",\n");
1284 index = keyword->_hash_value;
1285 }
1286
1287 keyword->_final_index = index;
1288
1289 output_keyword_entry (keyword, index, indent);
1290
1291 /* Deal with duplicates specially. */
1292 if (keyword->_duplicate_link) // implies option[DUP]
1293 for (KeywordExt *links = keyword->_duplicate_link; links; links = links->_duplicate_link)
1294 {
1295 links->_final_index = ++index;
1296 printf (",\n");
1297 int stringpool_index =
1298 (links->_allchars_length == keyword->_allchars_length
1299 && memcmp (links->_allchars, keyword->_allchars,
1300 keyword->_allchars_length) == 0
1301 ? keyword->_final_index
1302 : links->_final_index);
1303 output_keyword_entry (links, stringpool_index, indent);
1304 }
1305
1306 index++;
1307 }
1308 if (index > 0)
1309 printf ("\n");
1310
1311 printf ("%s };\n\n", indent);
1312}
1313
1314/* ------------------------------------------------------------------------- */
1315
1316/* Generates the large, sparse table that maps hash values into
1317 the smaller, contiguous range of the keyword table. */
1318
1319void
1320Output::output_lookup_array () const
1321{
1322 if (option[DUP])
1323 {
1324 const int DEFAULT_VALUE = -1;
1325
1326 /* Because of the way output_keyword_table works, every duplicate set is
1327 stored contiguously in the wordlist array. */
1328 struct duplicate_entry
1329 {
1330 int hash_value; /* Hash value for this particular duplicate set. */
1331 int index; /* Index into the main keyword storage array. */
1332 int count; /* Number of consecutive duplicates at this index. */
1333 };
1334
1335 duplicate_entry *duplicates = new duplicate_entry[_total_duplicates];
1336 int *lookup_array = new int[_max_hash_value + 1 + 2*_total_duplicates];
1337 int lookup_array_size = _max_hash_value + 1;
1338 duplicate_entry *dup_ptr = &duplicates[0];
1339 int *lookup_ptr = &lookup_array[_max_hash_value + 1 + 2*_total_duplicates];
1340
1341 while (lookup_ptr > lookup_array)
1342 *--lookup_ptr = DEFAULT_VALUE;
1343
1344 /* Now dup_ptr = &duplicates[0] and lookup_ptr = &lookup_array[0]. */
1345
1346 for (KeywordExt_List *temp = _head; temp; temp = temp->rest())
1347 {
1348 int hash_value = temp->first()->_hash_value;
1349 lookup_array[hash_value] = temp->first()->_final_index;
1350 if (option[DEBUG])
1351 fprintf (stderr, "keyword = %.*s, index = %d\n",
1352 temp->first()->_allchars_length, temp->first()->_allchars, temp->first()->_final_index);
1353 if (temp->first()->_duplicate_link)
1354 {
1355 /* Start a duplicate entry. */
1356 dup_ptr->hash_value = hash_value;
1357 dup_ptr->index = temp->first()->_final_index;
1358 dup_ptr->count = 1;
1359
1360 for (KeywordExt *ptr = temp->first()->_duplicate_link; ptr; ptr = ptr->_duplicate_link)
1361 {
1362 dup_ptr->count++;
1363 if (option[DEBUG])
1364 fprintf (stderr,
1365 "static linked keyword = %.*s, index = %d\n",
1366 ptr->_allchars_length, ptr->_allchars, ptr->_final_index);
1367 }
1368 assert (dup_ptr->count >= 2);
1369 dup_ptr++;
1370 }
1371 }
1372
1373 while (dup_ptr > duplicates)
1374 {
1375 dup_ptr--;
1376
1377 if (option[DEBUG])
1378 fprintf (stderr,
1379 "dup_ptr[%lu]: hash_value = %d, index = %d, count = %d\n",
1380 static_cast<unsigned long>(dup_ptr - duplicates),
1381 dup_ptr->hash_value, dup_ptr->index, dup_ptr->count);
1382
1383 int i;
1384 /* Start searching for available space towards the right part
1385 of the lookup array. */
1386 for (i = dup_ptr->hash_value; i < lookup_array_size-1; i++)
1387 if (lookup_array[i] == DEFAULT_VALUE
1388 && lookup_array[i + 1] == DEFAULT_VALUE)
1389 goto found_i;
1390 /* If we didn't find it to the right look to the left instead... */
1391 for (i = dup_ptr->hash_value-1; i >= 0; i--)
1392 if (lookup_array[i] == DEFAULT_VALUE
1393 && lookup_array[i + 1] == DEFAULT_VALUE)
1394 goto found_i;
1395 /* Append to the end of lookup_array. */
1396 i = lookup_array_size;
1397 lookup_array_size += 2;
1398 found_i:
1399 /* Put in an indirection from dup_ptr->_hash_value to i.
1400 At i and i+1 store dup_ptr->_final_index and dup_ptr->count. */
1401 assert (lookup_array[dup_ptr->hash_value] == dup_ptr->index);
1402 lookup_array[dup_ptr->hash_value] = - 1 - _total_keys - i;
1403 lookup_array[i] = - _total_keys + dup_ptr->index;
1404 lookup_array[i + 1] = - dup_ptr->count;
1405 /* All these three values are <= -2, distinct from DEFAULT_VALUE. */
1406 }
1407
1408 /* The values of the lookup array are now known. */
1409
1410 int min = INT_MAX;
1411 int max = INT_MIN;
1412 lookup_ptr = lookup_array + lookup_array_size;
1413 while (lookup_ptr > lookup_array)
1414 {
1415 int val = *--lookup_ptr;
1416 if (min > val)
1417 min = val;
1418 if (max < val)
1419 max = val;
1420 }
1421
1422 const char *indent = option[GLOBAL] ? "" : " ";
1423 printf ("%sstatic %s%s lookup[] =\n"
1424 "%s {",
1425 indent, const_readonly_array, smallest_integral_type (min, max),
1426 indent);
1427
1428 int field_width;
1429 /* Calculate maximum number of digits required for MIN..MAX. */
1430 {
1431 field_width = 2;
1432 for (int trunc = max; (trunc /= 10) > 0;)
1433 field_width++;
1434 }
1435 if (min < 0)
1436 {
1437 int neg_field_width = 2;
1438 for (int trunc = -min; (trunc /= 10) > 0;)
1439 neg_field_width++;
1440 neg_field_width++; /* account for the minus sign */
1441 if (field_width < neg_field_width)
1442 field_width = neg_field_width;
1443 }
1444
1445 const int columns = 42 / field_width;
1446 int column;
1447
1448 column = 0;
1449 for (int i = 0; i < lookup_array_size; i++)
1450 {
1451 if (i > 0)
1452 printf (",");
1453 if ((column++ % columns) == 0)
1454 printf("\n%s ", indent);
1455 printf ("%*d", field_width, lookup_array[i]);
1456 }
1457 printf ("\n%s };\n\n", indent);
1458
1459 delete[] duplicates;
1460 delete[] lookup_array;
1461 }
1462}
1463
1464/* ------------------------------------------------------------------------- */
1465
1466/* Generate all pools needed for the lookup function. */
1467
1468void
1469Output::output_lookup_pools () const
1470{
1471 if (option[SWITCH])
1472 {
1473 if (option[TYPE] || (option[DUP] && _total_duplicates > 0))
1474 output_string_pool ();
1475 }
1476 else
1477 {
1478 output_string_pool ();
1479 }
1480}
1481
1482/* Generate all the tables needed for the lookup function. */
1483
1484void
1485Output::output_lookup_tables () const
1486{
1487 if (option[SWITCH])
1488 {
1489 /* Use the switch in place of lookup table. */
1490 if (option[LENTABLE] && (option[DUP] && _total_duplicates > 0))
1491 output_keylength_table ();
1492 if (option[TYPE] || (option[DUP] && _total_duplicates > 0))
1493 output_keyword_table ();
1494 }
1495 else
1496 {
1497 /* Use the lookup table, in place of switch. */
1498 if (option[LENTABLE])
1499 output_keylength_table ();
1500 output_keyword_table ();
1501 output_lookup_array ();
1502 }
1503}
1504
1505/* ------------------------------------------------------------------------- */
1506
1507/* Output a single switch case (including duplicates). Advance list. */
1508
1509static KeywordExt_List *
1510output_switch_case (KeywordExt_List *list, int indent, int *jumps_away)
1511{
1512 if (option[DEBUG])
1513 printf ("%*s/* hash value = %4d, keyword = \"%.*s\" */\n",
1514 indent, "", list->first()->_hash_value, list->first()->_allchars_length, list->first()->_allchars);
1515
1516 if (option[DUP] && list->first()->_duplicate_link)
1517 {
1518 if (option[LENTABLE])
1519 printf ("%*slengthptr = &%s[%d];\n",
1520 indent, "", option.get_lengthtable_name (), list->first()->_final_index);
1521 printf ("%*swordptr = &%s[%d];\n",
1522 indent, "", option.get_wordlist_name (), list->first()->_final_index);
1523
1524 int count = 0;
1525 for (KeywordExt *links = list->first(); links; links = links->_duplicate_link)
1526 count++;
1527
1528 printf ("%*swordendptr = wordptr + %d;\n"
1529 "%*sgoto multicompare;\n",
1530 indent, "", count,
1531 indent, "");
1532 *jumps_away = 1;
1533 }
1534 else
1535 {
1536 if (option[LENTABLE])
1537 {
1538 printf ("%*sif (len == %d)\n"
1539 "%*s {\n",
1540 indent, "", list->first()->_allchars_length,
1541 indent, "");
1542 indent += 4;
1543 }
1544 printf ("%*sresword = ",
1545 indent, "");
1546 if (option[TYPE])
1547 printf ("&%s[%d]", option.get_wordlist_name (), list->first()->_final_index);
1548 else
1549 output_string (list->first()->_allchars, list->first()->_allchars_length);
1550 printf (";\n");
1551 printf ("%*sgoto compare;\n",
1552 indent, "");
1553 if (option[LENTABLE])
1554 {
1555 indent -= 4;
1556 printf ("%*s }\n",
1557 indent, "");
1558 }
1559 else
1560 *jumps_away = 1;
1561 }
1562
1563 return list->rest();
1564}
1565
1566/* Output a total of size cases, grouped into num_switches switch statements,
1567 where 0 < num_switches <= size. */
1568
1569static void
1570output_switches (KeywordExt_List *list, int num_switches, int size, int min_hash_value, int max_hash_value, int indent)
1571{
1572 if (option[DEBUG])
1573 printf ("%*s/* know %d <= key <= %d, contains %d cases */\n",
1574 indent, "", min_hash_value, max_hash_value, size);
1575
1576 if (num_switches > 1)
1577 {
1578 int part1 = num_switches / 2;
1579 int part2 = num_switches - part1;
1580 int size1 = static_cast<int>(static_cast<double>(size) / static_cast<double>(num_switches) * static_cast<double>(part1) + 0.5);
1581 int size2 = size - size1;
1582
1583 KeywordExt_List *temp = list;
1584 for (int count = size1; count > 0; count--)
1585 temp = temp->rest();
1586
1587 printf ("%*sif (key < %d)\n"
1588 "%*s {\n",
1589 indent, "", temp->first()->_hash_value,
1590 indent, "");
1591
1592 output_switches (list, part1, size1, min_hash_value, temp->first()->_hash_value-1, indent+4);
1593
1594 printf ("%*s }\n"
1595 "%*selse\n"
1596 "%*s {\n",
1597 indent, "", indent, "", indent, "");
1598
1599 output_switches (temp, part2, size2, temp->first()->_hash_value, max_hash_value, indent+4);
1600
1601 printf ("%*s }\n",
1602 indent, "");
1603 }
1604 else
1605 {
1606 /* Output a single switch. */
1607 int lowest_case_value = list->first()->_hash_value;
1608 if (size == 1)
1609 {
1610 int jumps_away = 0;
1611 assert (min_hash_value <= lowest_case_value);
1612 assert (lowest_case_value <= max_hash_value);
1613 if (min_hash_value == max_hash_value)
1614 output_switch_case (list, indent, &jumps_away);
1615 else
1616 {
1617 printf ("%*sif (key == %d)\n"
1618 "%*s {\n",
1619 indent, "", lowest_case_value,
1620 indent, "");
1621 output_switch_case (list, indent+4, &jumps_away);
1622 printf ("%*s }\n",
1623 indent, "");
1624 }
1625 }
1626 else
1627 {
1628 if (lowest_case_value == 0)
1629 printf ("%*sswitch (key)\n", indent, "");
1630 else
1631 printf ("%*sswitch (key - %d)\n", indent, "", lowest_case_value);
1632 printf ("%*s {\n",
1633 indent, "");
1634 for (; size > 0; size--)
1635 {
1636 int jumps_away = 0;
1637 printf ("%*s case %d:\n",
1638 indent, "", list->first()->_hash_value - lowest_case_value);
1639 list = output_switch_case (list, indent+6, &jumps_away);
1640 if (!jumps_away)
1641 printf ("%*s break;\n",
1642 indent, "");
1643 }
1644 printf ("%*s }\n",
1645 indent, "");
1646 }
1647 }
1648}
1649
1650/* Generates C code to perform the keyword lookup. */
1651
1652void
1653Output::output_lookup_function_body (const Output_Compare& comparison) const
1654{
1655 printf (" if (len <= %sMAX_WORD_LENGTH && len >= %sMIN_WORD_LENGTH)\n"
1656 " {\n"
1657 " %sunsigned int key = %s (str, len);\n\n",
1658 option.get_constants_prefix (), option.get_constants_prefix (),
1659 register_scs, option.get_hash_name ());
1660
1661 if (option[SWITCH])
1662 {
1663 int switch_size = num_hash_values ();
1664 int num_switches = option.get_total_switches ();
1665 if (num_switches > switch_size)
1666 num_switches = switch_size;
1667
1668 printf (" if (key <= %sMAX_HASH_VALUE",
1669 option.get_constants_prefix ());
1670 if (_min_hash_value > 0)
1671 printf (" && key >= %sMIN_HASH_VALUE",
1672 option.get_constants_prefix ());
1673 printf (")\n"
1674 " {\n");
1675 if (option[DUP] && _total_duplicates > 0)
1676 {
1677 if (option[LENTABLE])
1678 printf (" %s%s%s *lengthptr;\n",
1679 register_scs, const_always,
1680 smallest_integral_type (_max_key_len));
1681 printf (" %s",
1682 register_scs);
1683 output_const_type (const_readonly_array, _wordlist_eltype);
1684 printf ("*wordptr;\n");
1685 printf (" %s",
1686 register_scs);
1687 output_const_type (const_readonly_array, _wordlist_eltype);
1688 printf ("*wordendptr;\n");
1689 }
1690 if (option[TYPE])
1691 {
1692 printf (" %s",
1693 register_scs);
1694 output_const_type (const_readonly_array, _struct_tag);
1695 printf ("*resword;\n\n");
1696 }
1697 else
1698 printf (" %s%sresword;\n\n",
1699 register_scs, _struct_tag);
1700
1701 output_switches (_head, num_switches, switch_size, _min_hash_value, _max_hash_value, 10);
1702
1703 printf (" return 0;\n");
1704 if (option[DUP] && _total_duplicates > 0)
1705 {
1706 int indent = 8;
1707 printf ("%*smulticompare:\n"
1708 "%*s while (wordptr < wordendptr)\n"
1709 "%*s {\n",
1710 indent, "", indent, "", indent, "");
1711 if (option[LENTABLE])
1712 {
1713 printf ("%*s if (len == *lengthptr)\n"
1714 "%*s {\n",
1715 indent, "", indent, "");
1716 indent += 4;
1717 }
1718 printf ("%*s %s%schar *s = ",
1719 indent, "", register_scs, const_always);
1720 if (option[TYPE])
1721 printf ("wordptr->%s", option.get_slot_name ());
1722 else
1723 printf ("*wordptr");
1724 if (option[SHAREDLIB])
1725 printf (" + %s",
1726 option.get_stringpool_name ());
1727 printf (";\n\n"
1728 "%*s if (",
1729 indent, "");
1730 comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s"));
1731 printf (")\n"
1732 "%*s return %s;\n",
1733 indent, "",
1734 option[TYPE] ? "wordptr" : "s");
1735 if (option[LENTABLE])
1736 {
1737 indent -= 4;
1738 printf ("%*s }\n",
1739 indent, "");
1740 }
1741 if (option[LENTABLE])
1742 printf ("%*s lengthptr++;\n",
1743 indent, "");
1744 printf ("%*s wordptr++;\n"
1745 "%*s }\n"
1746 "%*s return 0;\n",
1747 indent, "", indent, "", indent, "");
1748 }
1749 printf (" compare:\n");
1750 if (option[TYPE])
1751 {
1752 printf (" {\n"
1753 " %s%schar *s = resword->%s",
1754 register_scs, const_always, option.get_slot_name ());
1755 if (option[SHAREDLIB])
1756 printf (" + %s",
1757 option.get_stringpool_name ());
1758 printf (";\n\n"
1759 " if (");
1760 comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s"));
1761 printf (")\n"
1762 " return resword;\n"
1763 " }\n");
1764 }
1765 else
1766 {
1767 printf (" if (");
1768 comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("resword"));
1769 printf (")\n"
1770 " return resword;\n");
1771 }
1772 printf (" }\n");
1773 }
1774 else
1775 {
1776 printf (" if (key <= %sMAX_HASH_VALUE)\n",
1777 option.get_constants_prefix ());
1778
1779 if (option[DUP])
1780 {
1781 int indent = 8;
1782 printf ("%*s{\n"
1783 "%*s %sint index = lookup[key];\n\n"
1784 "%*s if (index >= 0)\n",
1785 indent, "", indent, "", register_scs, indent, "");
1786 if (option[LENTABLE])
1787 {
1788 printf ("%*s {\n"
1789 "%*s if (len == %s[index])\n",
1790 indent, "", indent, "", option.get_lengthtable_name ());
1791 indent += 4;
1792 }
1793 printf ("%*s {\n"
1794 "%*s %s%schar *s = %s[index]",
1795 indent, "",
1796 indent, "", register_scs, const_always,
1797 option.get_wordlist_name ());
1798 if (option[TYPE])
1799 printf (".%s", option.get_slot_name ());
1800 if (option[SHAREDLIB])
1801 printf (" + %s",
1802 option.get_stringpool_name ());
1803 printf (";\n\n"
1804 "%*s if (",
1805 indent, "");
1806 comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s"));
1807 printf (")\n"
1808 "%*s return ",
1809 indent, "");
1810 if (option[TYPE])
1811 printf ("&%s[index]", option.get_wordlist_name ());
1812 else
1813 printf ("s");
1814 printf (";\n"
1815 "%*s }\n",
1816 indent, "");
1817 if (option[LENTABLE])
1818 {
1819 indent -= 4;
1820 printf ("%*s }\n", indent, "");
1821 }
1822 if (_total_duplicates > 0)
1823 {
1824 printf ("%*s else if (index < -%sTOTAL_KEYWORDS)\n"
1825 "%*s {\n"
1826 "%*s %sint offset = - 1 - %sTOTAL_KEYWORDS - index;\n",
1827 indent, "", option.get_constants_prefix (), indent, "",
1828 indent, "", register_scs, option.get_constants_prefix ());
1829 if (option[LENTABLE])
1830 printf ("%*s %s%s%s *lengthptr = &%s[%sTOTAL_KEYWORDS + lookup[offset]];\n",
1831 indent, "", register_scs, const_always, smallest_integral_type (_max_key_len),
1832 option.get_lengthtable_name (), option.get_constants_prefix ());
1833 printf ("%*s %s",
1834 indent, "", register_scs);
1835 output_const_type (const_readonly_array, _wordlist_eltype);
1836 printf ("*wordptr = &%s[%sTOTAL_KEYWORDS + lookup[offset]];\n",
1837 option.get_wordlist_name (), option.get_constants_prefix ());
1838 printf ("%*s %s",
1839 indent, "", register_scs);
1840 output_const_type (const_readonly_array, _wordlist_eltype);
1841 printf ("*wordendptr = wordptr + -lookup[offset + 1];\n\n");
1842 printf ("%*s while (wordptr < wordendptr)\n"
1843 "%*s {\n",
1844 indent, "", indent, "");
1845 if (option[LENTABLE])
1846 {
1847 printf ("%*s if (len == *lengthptr)\n"
1848 "%*s {\n",
1849 indent, "", indent, "");
1850 indent += 4;
1851 }
1852 printf ("%*s %s%schar *s = ",
1853 indent, "", register_scs, const_always);
1854 if (option[TYPE])
1855 printf ("wordptr->%s", option.get_slot_name ());
1856 else
1857 printf ("*wordptr");
1858 if (option[SHAREDLIB])
1859 printf (" + %s",
1860 option.get_stringpool_name ());
1861 printf (";\n\n"
1862 "%*s if (",
1863 indent, "");
1864 comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s"));
1865 printf (")\n"
1866 "%*s return %s;\n",
1867 indent, "",
1868 option[TYPE] ? "wordptr" : "s");
1869 if (option[LENTABLE])
1870 {
1871 indent -= 4;
1872 printf ("%*s }\n",
1873 indent, "");
1874 }
1875 if (option[LENTABLE])
1876 printf ("%*s lengthptr++;\n",
1877 indent, "");
1878 printf ("%*s wordptr++;\n"
1879 "%*s }\n"
1880 "%*s }\n",
1881 indent, "", indent, "", indent, "");
1882 }
1883 printf ("%*s}\n",
1884 indent, "");
1885 }
1886 else
1887 {
1888 int indent = 8;
1889 if (option[LENTABLE])
1890 {
1891 printf ("%*sif (len == %s[key])\n",
1892 indent, "", option.get_lengthtable_name ());
1893 indent += 2;
1894 }
1895
1896 if (option[SHAREDLIB])
1897 {
1898 if (!option[LENTABLE])
1899 {
1900 printf ("%*s{\n"
1901 "%*s %sint o = %s[key]",
1902 indent, "",
1903 indent, "", register_scs,
1904 option.get_wordlist_name ());
1905 if (option[TYPE])
1906 printf (".%s", option.get_slot_name ());
1907 printf (";\n"
1908 "%*s if (o >= 0)\n"
1909 "%*s {\n",
1910 indent, "",
1911 indent, "");
1912 indent += 4;
1913 printf ("%*s %s%schar *s = o",
1914 indent, "", register_scs, const_always);
1915 }
1916 else
1917 {
1918 /* No need for the (o >= 0) test, because the
1919 (len == lengthtable[key]) test already guarantees that
1920 key points to nonempty table entry. */
1921 printf ("%*s{\n"
1922 "%*s %s%schar *s = %s[key]",
1923 indent, "",
1924 indent, "", register_scs, const_always,
1925 option.get_wordlist_name ());
1926 if (option[TYPE])
1927 printf (".%s", option.get_slot_name ());
1928 }
1929 printf (" + %s",
1930 option.get_stringpool_name ());
1931 }
1932 else
1933 {
1934 printf ("%*s{\n"
1935 "%*s %s%schar *s = %s[key]",
1936 indent, "",
1937 indent, "", register_scs, const_always,
1938 option.get_wordlist_name ());
1939 if (option[TYPE])
1940 printf (".%s", option.get_slot_name ());
1941 }
1942
1943 printf (";\n\n"
1944 "%*s if (",
1945 indent, "");
1946 if (!option[SHAREDLIB] && option[NULLSTRINGS])
1947 printf ("s && ");
1948 comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s"));
1949 printf (")\n"
1950 "%*s return ",
1951 indent, "");
1952 if (option[TYPE])
1953 printf ("&%s[key]", option.get_wordlist_name ());
1954 else
1955 printf ("s");
1956 printf (";\n");
1957 if (option[SHAREDLIB] && !option[LENTABLE])
1958 {
1959 indent -= 4;
1960 printf ("%*s }\n",
1961 indent, "");
1962 }
1963 printf ("%*s}\n",
1964 indent, "");
1965 }
1966 }
1967 printf (" }\n"
1968 " return 0;\n");
1969}
1970
1971/* Generates C code for the lookup function. */
1972
1973void
1974Output::output_lookup_function () const
1975{
1976 /* Output the function's head. */
1977 /* We don't declare the lookup function 'static' because we cannot make
1978 assumptions about the compilation units of the user.
1979 Since we don't make it 'static', it makes no sense to declare it 'inline',
1980 because non-static inline functions must not reference static functions or
1981 variables, see ISO C 99 section 6.7.4.(3). */
1982
1983 printf ("%s%s\n",
1984 const_for_struct, _return_type);
1985 if (option[CPLUSPLUS])
1986 printf ("%s::", option.get_class_name ());
1987 printf ("%s ", option.get_function_name ());
1988 printf (option[KRC] ?
1989 "(str, len)\n"
1990 " %schar *str;\n"
1991 " %ssize_t len;\n" :
1992 option[C] ?
1993 "(str, len)\n"
1994 " %sconst char *str;\n"
1995 " %ssize_t len;\n" :
1996 option[ANSIC] | option[CPLUSPLUS] ?
1997 "(%sconst char *str, %ssize_t len)\n" :
1998 "",
1999 register_scs, register_scs);
2000
2001 /* Output the function's body. */
2002 printf ("{\n");
2003
2004 if (option[ENUM] && !option[GLOBAL])
2005 {
2006 Output_Enum style (" ");
2007 output_constants (style);
2008 }
2009
2010 if (option[SHAREDLIB] && !(option[GLOBAL] || option[TYPE]))
2011 output_lookup_pools ();
2012 if (!option[GLOBAL])
2013 output_lookup_tables ();
2014
2015 if (option[LENTABLE])
2016 output_lookup_function_body (Output_Compare_Memcmp ());
2017 else
2018 {
2019 if (option[COMP])
2020 output_lookup_function_body (Output_Compare_Strncmp ());
2021 else
2022 output_lookup_function_body (Output_Compare_Strcmp ());
2023 }
2024
2025 printf ("}\n");
2026}
2027
2028/* ------------------------------------------------------------------------- */
2029
2030/* Generates the hash function and the key word recognizer function
2031 based upon the user's Options. */
2032
2033void
2034Output::output ()
2035{
2036 compute_min_max ();
2037
2038 if (option[CPLUSPLUS])
2039 /* The 'register' keyword is removed from C++17.
2040 See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4340 */
2041 register_scs = "";
2042 else
2043 register_scs = "register ";
2044
2045 if (option[C] | option[ANSIC] | option[CPLUSPLUS])
2046 {
2047 const_always = "const ";
2048 const_readonly_array = (option[CONST] ? "const " : "");
2049 const_for_struct = ((option[CONST] && option[TYPE]) ? "const " : "");
2050 }
2051 else
2052 {
2053 const_always = "";
2054 const_readonly_array = "";
2055 const_for_struct = "";
2056 }
2057
2058 if (!option[TYPE])
2059 {
2060 _return_type = (const_always[0] ? "const char *" : "char *");
2061 _struct_tag = (const_always[0] ? "const char *" : "char *");
2062 }
2063
2064 _wordlist_eltype = (option[SHAREDLIB] && !option[TYPE] ? "int" : _struct_tag);
2065
2066 printf ("/* ");
2067 if (option[KRC])
2068 printf ("KR-C");
2069 else if (option[C])
2070 printf ("C");
2071 else if (option[ANSIC])
2072 printf ("ANSI-C");
2073 else if (option[CPLUSPLUS])
2074 printf ("C++");
2075 printf (" code produced by gperf version %s */\n", version_string);
2076 option.print_options ();
2077 printf ("\n");
2078 if (!option[POSITIONS])
2079 {
2080 printf ("/* Computed positions: -k'");
2081 _key_positions.print();
2082 printf ("' */\n");
2083 }
2084 printf ("\n");
2085
2086 if (_charset_dependent
2087 && (_key_positions.get_size() > 0 || option[UPPERLOWER]))
2088 {
2089 /* The generated tables assume that the execution character set is
2090 based on ISO-646, not EBCDIC. */
2091 printf ("#if !((' ' == 32) && ('!' == 33) && ('\"' == 34) && ('#' == 35) \\\n"
2092 " && ('%%' == 37) && ('&' == 38) && ('\\'' == 39) && ('(' == 40) \\\n"
2093 " && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \\\n"
2094 " && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \\\n"
2095 " && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \\\n"
2096 " && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \\\n"
2097 " && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \\\n"
2098 " && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \\\n"
2099 " && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \\\n"
2100 " && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \\\n"
2101 " && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \\\n"
2102 " && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \\\n"
2103 " && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \\\n"
2104 " && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \\\n"
2105 " && ('Z' == 90) && ('[' == 91) && ('\\\\' == 92) && (']' == 93) \\\n"
2106 " && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \\\n"
2107 " && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \\\n"
2108 " && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \\\n"
2109 " && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \\\n"
2110 " && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \\\n"
2111 " && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \\\n"
2112 " && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \\\n"
2113 " && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))\n"
2114 "/* The character set is not based on ISO-646. */\n");
2115 printf ("%s \"gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>.\"\n", option[KRC] || option[C] ? "error" : "#error");
2116 printf ("#endif\n\n");
2117 }
2118
2119 if (_verbatim_declarations < _verbatim_declarations_end)
2120 {
2121 output_line_directive (_verbatim_declarations_lineno);
2122 fwrite (_verbatim_declarations, 1,
2123 _verbatim_declarations_end - _verbatim_declarations, stdout);
2124 }
2125
2126 if (option[TYPE] && !option[NOTYPE]) /* Output type declaration now, reference it later on.... */
2127 {
2128 output_line_directive (_struct_decl_lineno);
2129 printf ("%s\n", _struct_decl);
2130 }
2131
2132 if (option[INCLUDE])
2133 printf ("#include <string.h>\n"); /* Declare strlen(), strcmp(), strncmp(). */
2134
2135 if (!option[ENUM])
2136 {
2137 Output_Defines style;
2138 output_constants (style);
2139 }
2140 else if (option[GLOBAL])
2141 {
2142 Output_Enum style ("");
2143 output_constants (style);
2144 }
2145
2146 printf ("/* maximum key range = %d, duplicates = %d */\n\n",
2147 _max_hash_value - _min_hash_value + 1, _total_duplicates);
2148
2149 if (option[UPPERLOWER])
2150 {
2151 #if USE_DOWNCASE_TABLE
2152 output_upperlower_table ();
2153 #endif
2154
2155 if (option[LENTABLE])
2156 output_upperlower_memcmp ();
2157 else
2158 {
2159 if (option[COMP])
2160 output_upperlower_strncmp ();
2161 else
2162 output_upperlower_strcmp ();
2163 }
2164 }
2165
2166 if (option[CPLUSPLUS])
2167 printf ("class %s\n"
2168 "{\n"
2169 "private:\n"
2170 " static inline unsigned int %s (const char *str, size_t len);\n"
2171 "public:\n"
2172 " static %s%s%s (const char *str, size_t len);\n"
2173 "};\n"
2174 "\n",
2175 option.get_class_name (), option.get_hash_name (),
2176 const_for_struct, _return_type, option.get_function_name ());
2177
2178 output_hash_function ();
2179
2180 if (option[SHAREDLIB] && (option[GLOBAL] || option[TYPE]))
2181 output_lookup_pools ();
2182 if (option[GLOBAL])
2183 output_lookup_tables ();
2184
2185 output_lookup_function ();
2186
2187 if (_verbatim_code < _verbatim_code_end)
2188 {
2189 output_line_directive (_verbatim_code_lineno);
2190 fwrite (_verbatim_code, 1, _verbatim_code_end - _verbatim_code, stdout);
2191 }
2192
2193 fflush (stdout);
2194}
2195