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