output.cc revision 228060
1228060Sbapt/* Output routines. 2228060Sbapt Copyright (C) 1989-1998, 2000, 2002-2004, 2006-2007 Free Software Foundation, Inc. 3228060Sbapt Written by Douglas C. Schmidt <schmidt@ics.uci.edu> 4228060Sbapt and Bruno Haible <bruno@clisp.org>. 5228060Sbapt 6228060Sbapt This file is part of GNU GPERF. 7228060Sbapt 8228060Sbapt GNU GPERF is free software; you can redistribute it and/or modify 9228060Sbapt it under the terms of the GNU General Public License as published by 10228060Sbapt the Free Software Foundation; either version 2, or (at your option) 11228060Sbapt any later version. 12228060Sbapt 13228060Sbapt GNU GPERF is distributed in the hope that it will be useful, 14228060Sbapt but WITHOUT ANY WARRANTY; without even the implied warranty of 15228060Sbapt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16228060Sbapt GNU General Public License for more details. 17228060Sbapt 18228060Sbapt You should have received a copy of the GNU General Public License 19228060Sbapt along with this program; see the file COPYING. 20228060Sbapt If not, write to the Free Software Foundation, Inc., 21228060Sbapt 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 22228060Sbapt 23228060Sbapt/* Specification. */ 24228060Sbapt#include "output.h" 25228060Sbapt 26228060Sbapt#include <stdio.h> 27228060Sbapt#include <string.h> /* declares strncpy(), strchr() */ 28228060Sbapt#include <ctype.h> /* declares isprint() */ 29228060Sbapt#include <assert.h> /* defines assert() */ 30228060Sbapt#include <limits.h> /* defines SCHAR_MAX etc. */ 31228060Sbapt#include "options.h" 32228060Sbapt#include "version.h" 33228060Sbapt 34228060Sbapt/* The "const " qualifier. */ 35228060Sbaptstatic const char *const_always; 36228060Sbapt 37228060Sbapt/* The "const " qualifier, for read-only arrays. */ 38228060Sbaptstatic const char *const_readonly_array; 39228060Sbapt 40228060Sbapt/* The "const " qualifier, for the array type. */ 41228060Sbaptstatic const char *const_for_struct; 42228060Sbapt 43228060Sbapt/* Returns the smallest unsigned C type capable of holding integers 44228060Sbapt up to N. */ 45228060Sbapt 46228060Sbaptstatic const char * 47228060Sbaptsmallest_integral_type (int n) 48228060Sbapt{ 49228060Sbapt if (n <= UCHAR_MAX) return "unsigned char"; 50228060Sbapt if (n <= USHRT_MAX) return "unsigned short"; 51228060Sbapt return "unsigned int"; 52228060Sbapt} 53228060Sbapt 54228060Sbapt/* Returns the smallest signed C type capable of holding integers 55228060Sbapt from MIN to MAX. */ 56228060Sbapt 57228060Sbaptstatic const char * 58228060Sbaptsmallest_integral_type (int min, int max) 59228060Sbapt{ 60228060Sbapt if (option[ANSIC] | option[CPLUSPLUS]) 61228060Sbapt if (min >= SCHAR_MIN && max <= SCHAR_MAX) return "signed char"; 62228060Sbapt if (min >= SHRT_MIN && max <= SHRT_MAX) return "short"; 63228060Sbapt return "int"; 64228060Sbapt} 65228060Sbapt 66228060Sbapt/* ------------------------------------------------------------------------- */ 67228060Sbapt 68228060Sbapt/* Constructor. 69228060Sbapt Note about the keyword list starting at head: 70228060Sbapt - The list is ordered by increasing _hash_value. This has been achieved 71228060Sbapt by Search::sort(). 72228060Sbapt - Duplicates, i.e. keywords with the same _selchars set, are chained 73228060Sbapt through the _duplicate_link pointer. Only one representative per 74228060Sbapt duplicate equivalence class remains on the linear keyword list. 75228060Sbapt - Accidental duplicates, i.e. keywords for which the _asso_values[] search 76228060Sbapt couldn't achieve different hash values, cannot occur on the linear 77228060Sbapt keyword list. Search::optimize would catch this mistake. 78228060Sbapt */ 79228060SbaptOutput::Output (KeywordExt_List *head, const char *struct_decl, 80228060Sbapt unsigned int struct_decl_lineno, const char *return_type, 81228060Sbapt const char *struct_tag, const char *verbatim_declarations, 82228060Sbapt const char *verbatim_declarations_end, 83228060Sbapt unsigned int verbatim_declarations_lineno, 84228060Sbapt const char *verbatim_code, const char *verbatim_code_end, 85228060Sbapt unsigned int verbatim_code_lineno, bool charset_dependent, 86228060Sbapt int total_keys, int max_key_len, int min_key_len, 87228060Sbapt const Positions& positions, const unsigned int *alpha_inc, 88228060Sbapt int total_duplicates, unsigned int alpha_size, 89228060Sbapt const int *asso_values) 90228060Sbapt : _head (head), _struct_decl (struct_decl), 91228060Sbapt _struct_decl_lineno (struct_decl_lineno), _return_type (return_type), 92228060Sbapt _struct_tag (struct_tag), 93228060Sbapt _verbatim_declarations (verbatim_declarations), 94228060Sbapt _verbatim_declarations_end (verbatim_declarations_end), 95228060Sbapt _verbatim_declarations_lineno (verbatim_declarations_lineno), 96228060Sbapt _verbatim_code (verbatim_code), 97228060Sbapt _verbatim_code_end (verbatim_code_end), 98228060Sbapt _verbatim_code_lineno (verbatim_code_lineno), 99228060Sbapt _charset_dependent (charset_dependent), 100228060Sbapt _total_keys (total_keys), 101228060Sbapt _max_key_len (max_key_len), _min_key_len (min_key_len), 102228060Sbapt _key_positions (positions), _alpha_inc (alpha_inc), 103228060Sbapt _total_duplicates (total_duplicates), _alpha_size (alpha_size), 104228060Sbapt _asso_values (asso_values) 105228060Sbapt{ 106228060Sbapt} 107228060Sbapt 108228060Sbapt/* ------------------------------------------------------------------------- */ 109228060Sbapt 110228060Sbapt/* Computes the minimum and maximum hash values, and stores them 111228060Sbapt in _min_hash_value and _max_hash_value. */ 112228060Sbapt 113228060Sbaptvoid 114228060SbaptOutput::compute_min_max () 115228060Sbapt{ 116228060Sbapt /* Since the list is already sorted by hash value all we need to do is 117228060Sbapt to look at the first and the last element of the list. */ 118228060Sbapt 119228060Sbapt _min_hash_value = _head->first()->_hash_value; 120228060Sbapt 121228060Sbapt KeywordExt_List *temp; 122228060Sbapt for (temp = _head; temp->rest(); temp = temp->rest()) 123228060Sbapt ; 124228060Sbapt _max_hash_value = temp->first()->_hash_value; 125228060Sbapt} 126228060Sbapt 127228060Sbapt/* ------------------------------------------------------------------------- */ 128228060Sbapt 129228060Sbapt/* Returns the number of different hash values. */ 130228060Sbapt 131228060Sbaptint 132228060SbaptOutput::num_hash_values () const 133228060Sbapt{ 134228060Sbapt /* Since the list is already sorted by hash value and doesn't contain 135228060Sbapt duplicates, we can simply count the number of keywords on the list. */ 136228060Sbapt int count = 0; 137228060Sbapt for (KeywordExt_List *temp = _head; temp; temp = temp->rest()) 138228060Sbapt count++; 139228060Sbapt return count; 140228060Sbapt} 141228060Sbapt 142228060Sbapt/* -------------------- Output_Constants and subclasses -------------------- */ 143228060Sbapt 144228060Sbapt/* This class outputs an enumeration defining some constants. */ 145228060Sbapt 146228060Sbaptstruct Output_Constants 147228060Sbapt{ 148228060Sbapt virtual void output_start () = 0; 149228060Sbapt virtual void output_item (const char *name, int value) = 0; 150228060Sbapt virtual void output_end () = 0; 151228060Sbapt Output_Constants () {} 152228060Sbapt virtual ~Output_Constants () {} 153228060Sbapt}; 154228060Sbapt 155228060Sbapt/* This class outputs an enumeration in #define syntax. */ 156228060Sbapt 157228060Sbaptstruct Output_Defines : public Output_Constants 158228060Sbapt{ 159228060Sbapt virtual void output_start (); 160228060Sbapt virtual void output_item (const char *name, int value); 161228060Sbapt virtual void output_end (); 162228060Sbapt Output_Defines () {} 163228060Sbapt virtual ~Output_Defines () {} 164228060Sbapt}; 165228060Sbapt 166228060Sbaptvoid Output_Defines::output_start () 167228060Sbapt{ 168228060Sbapt printf ("\n"); 169228060Sbapt} 170228060Sbapt 171228060Sbaptvoid Output_Defines::output_item (const char *name, int value) 172228060Sbapt{ 173228060Sbapt printf ("#define %s %d\n", name, value); 174228060Sbapt} 175228060Sbapt 176228060Sbaptvoid Output_Defines::output_end () 177228060Sbapt{ 178228060Sbapt} 179228060Sbapt 180228060Sbapt/* This class outputs an enumeration using 'enum'. */ 181228060Sbapt 182228060Sbaptstruct Output_Enum : public Output_Constants 183228060Sbapt{ 184228060Sbapt virtual void output_start (); 185228060Sbapt virtual void output_item (const char *name, int value); 186228060Sbapt virtual void output_end (); 187228060Sbapt Output_Enum (const char *indent) 188228060Sbapt : _indentation (indent) {} 189228060Sbapt virtual ~Output_Enum () {} 190228060Sbaptprivate: 191228060Sbapt const char *_indentation; 192228060Sbapt bool _pending_comma; 193228060Sbapt}; 194228060Sbapt 195228060Sbaptvoid Output_Enum::output_start () 196228060Sbapt{ 197228060Sbapt printf ("%senum\n" 198228060Sbapt "%s {\n", 199228060Sbapt _indentation, _indentation); 200228060Sbapt _pending_comma = false; 201228060Sbapt} 202228060Sbapt 203228060Sbaptvoid Output_Enum::output_item (const char *name, int value) 204228060Sbapt{ 205228060Sbapt if (_pending_comma) 206228060Sbapt printf (",\n"); 207228060Sbapt printf ("%s %s = %d", _indentation, name, value); 208228060Sbapt _pending_comma = true; 209228060Sbapt} 210228060Sbapt 211228060Sbaptvoid Output_Enum::output_end () 212228060Sbapt{ 213228060Sbapt if (_pending_comma) 214228060Sbapt printf ("\n"); 215228060Sbapt printf ("%s };\n\n", _indentation); 216228060Sbapt} 217228060Sbapt 218228060Sbapt/* Outputs the maximum and minimum hash values etc. */ 219228060Sbapt 220228060Sbaptvoid 221228060SbaptOutput::output_constants (struct Output_Constants& style) const 222228060Sbapt{ 223228060Sbapt style.output_start (); 224228060Sbapt style.output_item ("TOTAL_KEYWORDS", _total_keys); 225228060Sbapt style.output_item ("MIN_WORD_LENGTH", _min_key_len); 226228060Sbapt style.output_item ("MAX_WORD_LENGTH", _max_key_len); 227228060Sbapt style.output_item ("MIN_HASH_VALUE", _min_hash_value); 228228060Sbapt style.output_item ("MAX_HASH_VALUE", _max_hash_value); 229228060Sbapt style.output_end (); 230228060Sbapt} 231228060Sbapt 232228060Sbapt/* ------------------------------------------------------------------------- */ 233228060Sbapt 234228060Sbapt/* We use a downcase table because when called repeatedly, the code 235228060Sbapt gperf_downcase[c] 236228060Sbapt is faster than 237228060Sbapt if (c >= 'A' && c <= 'Z') 238228060Sbapt c += 'a' - 'A'; 239228060Sbapt */ 240228060Sbapt#define USE_DOWNCASE_TABLE 1 241228060Sbapt 242228060Sbapt#if USE_DOWNCASE_TABLE 243228060Sbapt 244228060Sbapt/* Output gperf's ASCII-downcase table. */ 245228060Sbapt 246228060Sbaptstatic void 247228060Sbaptoutput_upperlower_table () 248228060Sbapt{ 249228060Sbapt unsigned int c; 250228060Sbapt 251228060Sbapt printf ("#ifndef GPERF_DOWNCASE\n" 252228060Sbapt "#define GPERF_DOWNCASE 1\n" 253228060Sbapt "static unsigned char gperf_downcase[256] =\n" 254228060Sbapt " {"); 255228060Sbapt for (c = 0; c < 256; c++) 256228060Sbapt { 257228060Sbapt if ((c % 15) == 0) 258228060Sbapt printf ("\n "); 259228060Sbapt printf (" %3d", c >= 'A' && c <= 'Z' ? c + 'a' - 'A' : c); 260228060Sbapt if (c < 255) 261228060Sbapt printf (","); 262228060Sbapt } 263228060Sbapt printf ("\n" 264228060Sbapt " };\n" 265228060Sbapt "#endif\n\n"); 266228060Sbapt} 267228060Sbapt 268228060Sbapt#endif 269228060Sbapt 270228060Sbapt/* Output gperf's ASCII-case insensitive strcmp replacement. */ 271228060Sbapt 272228060Sbaptstatic void 273228060Sbaptoutput_upperlower_strcmp () 274228060Sbapt{ 275228060Sbapt printf ("#ifndef GPERF_CASE_STRCMP\n" 276228060Sbapt "#define GPERF_CASE_STRCMP 1\n" 277228060Sbapt "static int\n" 278228060Sbapt "gperf_case_strcmp "); 279228060Sbapt printf (option[KRC] ? 280228060Sbapt "(s1, s2)\n" 281228060Sbapt " register char *s1;\n" 282228060Sbapt " register char *s2;\n" : 283228060Sbapt option[C] ? 284228060Sbapt "(s1, s2)\n" 285228060Sbapt " register const char *s1;\n" 286228060Sbapt " register const char *s2;\n" : 287228060Sbapt option[ANSIC] | option[CPLUSPLUS] ? 288228060Sbapt "(register const char *s1, register const char *s2)\n" : 289228060Sbapt ""); 290228060Sbapt #if USE_DOWNCASE_TABLE 291228060Sbapt printf ("{\n" 292228060Sbapt " for (;;)\n" 293228060Sbapt " {\n" 294228060Sbapt " unsigned char c1 = gperf_downcase[(unsigned char)*s1++];\n" 295228060Sbapt " unsigned char c2 = gperf_downcase[(unsigned char)*s2++];\n" 296228060Sbapt " if (c1 != 0 && c1 == c2)\n" 297228060Sbapt " continue;\n" 298228060Sbapt " return (int)c1 - (int)c2;\n" 299228060Sbapt " }\n" 300228060Sbapt "}\n"); 301228060Sbapt #else 302228060Sbapt printf ("{\n" 303228060Sbapt " for (;;)\n" 304228060Sbapt " {\n" 305228060Sbapt " unsigned char c1 = *s1++;\n" 306228060Sbapt " unsigned char c2 = *s2++;\n" 307228060Sbapt " if (c1 >= 'A' && c1 <= 'Z')\n" 308228060Sbapt " c1 += 'a' - 'A';\n" 309228060Sbapt " if (c2 >= 'A' && c2 <= 'Z')\n" 310228060Sbapt " c2 += 'a' - 'A';\n" 311228060Sbapt " if (c1 != 0 && c1 == c2)\n" 312228060Sbapt " continue;\n" 313228060Sbapt " return (int)c1 - (int)c2;\n" 314228060Sbapt " }\n" 315228060Sbapt "}\n"); 316228060Sbapt #endif 317228060Sbapt printf ("#endif\n\n"); 318228060Sbapt} 319228060Sbapt 320228060Sbapt/* Output gperf's ASCII-case insensitive strncmp replacement. */ 321228060Sbapt 322228060Sbaptstatic void 323228060Sbaptoutput_upperlower_strncmp () 324228060Sbapt{ 325228060Sbapt printf ("#ifndef GPERF_CASE_STRNCMP\n" 326228060Sbapt "#define GPERF_CASE_STRNCMP 1\n" 327228060Sbapt "static int\n" 328228060Sbapt "gperf_case_strncmp "); 329228060Sbapt printf (option[KRC] ? 330228060Sbapt "(s1, s2, n)\n" 331228060Sbapt " register char *s1;\n" 332228060Sbapt " register char *s2;\n" 333228060Sbapt " register unsigned int n;\n" : 334228060Sbapt option[C] ? 335228060Sbapt "(s1, s2, n)\n" 336228060Sbapt " register const char *s1;\n" 337228060Sbapt " register const char *s2;\n" 338228060Sbapt " register unsigned int n;\n" : 339228060Sbapt option[ANSIC] | option[CPLUSPLUS] ? 340228060Sbapt "(register const char *s1, register const char *s2, register unsigned int n)\n" : 341228060Sbapt ""); 342228060Sbapt #if USE_DOWNCASE_TABLE 343228060Sbapt printf ("{\n" 344228060Sbapt " for (; n > 0;)\n" 345228060Sbapt " {\n" 346228060Sbapt " unsigned char c1 = gperf_downcase[(unsigned char)*s1++];\n" 347228060Sbapt " unsigned char c2 = gperf_downcase[(unsigned char)*s2++];\n" 348228060Sbapt " if (c1 != 0 && c1 == c2)\n" 349228060Sbapt " {\n" 350228060Sbapt " n--;\n" 351228060Sbapt " continue;\n" 352228060Sbapt " }\n" 353228060Sbapt " return (int)c1 - (int)c2;\n" 354228060Sbapt " }\n" 355228060Sbapt " return 0;\n" 356228060Sbapt "}\n"); 357228060Sbapt #else 358228060Sbapt printf ("{\n" 359228060Sbapt " for (; n > 0;)\n" 360228060Sbapt " {\n" 361228060Sbapt " unsigned char c1 = *s1++;\n" 362228060Sbapt " unsigned char c2 = *s2++;\n" 363228060Sbapt " if (c1 >= 'A' && c1 <= 'Z')\n" 364228060Sbapt " c1 += 'a' - 'A';\n" 365228060Sbapt " if (c2 >= 'A' && c2 <= 'Z')\n" 366228060Sbapt " c2 += 'a' - 'A';\n" 367228060Sbapt " if (c1 != 0 && c1 == c2)\n" 368228060Sbapt " {\n" 369228060Sbapt " n--;\n" 370228060Sbapt " continue;\n" 371228060Sbapt " }\n" 372228060Sbapt " return (int)c1 - (int)c2;\n" 373228060Sbapt " }\n" 374228060Sbapt " return 0;\n" 375228060Sbapt "}\n"); 376228060Sbapt #endif 377228060Sbapt printf ("#endif\n\n"); 378228060Sbapt} 379228060Sbapt 380228060Sbapt/* Output gperf's ASCII-case insensitive memcmp replacement. */ 381228060Sbapt 382228060Sbaptstatic void 383228060Sbaptoutput_upperlower_memcmp () 384228060Sbapt{ 385228060Sbapt printf ("#ifndef GPERF_CASE_MEMCMP\n" 386228060Sbapt "#define GPERF_CASE_MEMCMP 1\n" 387228060Sbapt "static int\n" 388228060Sbapt "gperf_case_memcmp "); 389228060Sbapt printf (option[KRC] ? 390228060Sbapt "(s1, s2, n)\n" 391228060Sbapt " register char *s1;\n" 392228060Sbapt " register char *s2;\n" 393228060Sbapt " register unsigned int n;\n" : 394228060Sbapt option[C] ? 395228060Sbapt "(s1, s2, n)\n" 396228060Sbapt " register const char *s1;\n" 397228060Sbapt " register const char *s2;\n" 398228060Sbapt " register unsigned int n;\n" : 399228060Sbapt option[ANSIC] | option[CPLUSPLUS] ? 400228060Sbapt "(register const char *s1, register const char *s2, register unsigned int n)\n" : 401228060Sbapt ""); 402228060Sbapt #if USE_DOWNCASE_TABLE 403228060Sbapt printf ("{\n" 404228060Sbapt " for (; n > 0;)\n" 405228060Sbapt " {\n" 406228060Sbapt " unsigned char c1 = gperf_downcase[(unsigned char)*s1++];\n" 407228060Sbapt " unsigned char c2 = gperf_downcase[(unsigned char)*s2++];\n" 408228060Sbapt " if (c1 == c2)\n" 409228060Sbapt " {\n" 410228060Sbapt " n--;\n" 411228060Sbapt " continue;\n" 412228060Sbapt " }\n" 413228060Sbapt " return (int)c1 - (int)c2;\n" 414228060Sbapt " }\n" 415228060Sbapt " return 0;\n" 416228060Sbapt "}\n"); 417228060Sbapt #else 418228060Sbapt printf ("{\n" 419228060Sbapt " for (; n > 0;)\n" 420228060Sbapt " {\n" 421228060Sbapt " unsigned char c1 = *s1++;\n" 422228060Sbapt " unsigned char c2 = *s2++;\n" 423228060Sbapt " if (c1 >= 'A' && c1 <= 'Z')\n" 424228060Sbapt " c1 += 'a' - 'A';\n" 425228060Sbapt " if (c2 >= 'A' && c2 <= 'Z')\n" 426228060Sbapt " c2 += 'a' - 'A';\n" 427228060Sbapt " if (c1 == c2)\n" 428228060Sbapt " {\n" 429228060Sbapt " n--;\n" 430228060Sbapt " continue;\n" 431228060Sbapt " }\n" 432228060Sbapt " return (int)c1 - (int)c2;\n" 433228060Sbapt " }\n" 434228060Sbapt " return 0;\n" 435228060Sbapt "}\n"); 436228060Sbapt #endif 437228060Sbapt printf ("#endif\n\n"); 438228060Sbapt} 439228060Sbapt 440228060Sbapt/* ------------------------------------------------------------------------- */ 441228060Sbapt 442228060Sbapt/* Outputs a keyword, as a string: enclosed in double quotes, escaping 443228060Sbapt backslashes, double quote and unprintable characters. */ 444228060Sbapt 445228060Sbaptstatic void 446228060Sbaptoutput_string (const char *key, int len) 447228060Sbapt{ 448228060Sbapt putchar ('"'); 449228060Sbapt for (; len > 0; len--) 450228060Sbapt { 451228060Sbapt unsigned char c = static_cast<unsigned char>(*key++); 452228060Sbapt if (isprint (c)) 453228060Sbapt { 454228060Sbapt if (c == '"' || c == '\\') 455228060Sbapt putchar ('\\'); 456228060Sbapt putchar (c); 457228060Sbapt } 458228060Sbapt else 459228060Sbapt { 460228060Sbapt /* Use octal escapes, not hexadecimal escapes, because some old 461228060Sbapt C compilers didn't understand hexadecimal escapes, and because 462228060Sbapt hexadecimal escapes are not limited to 2 digits, thus needing 463228060Sbapt special care if the following character happens to be a digit. */ 464228060Sbapt putchar ('\\'); 465228060Sbapt putchar ('0' + ((c >> 6) & 7)); 466228060Sbapt putchar ('0' + ((c >> 3) & 7)); 467228060Sbapt putchar ('0' + (c & 7)); 468228060Sbapt } 469228060Sbapt } 470228060Sbapt putchar ('"'); 471228060Sbapt} 472228060Sbapt 473228060Sbapt/* ------------------------------------------------------------------------- */ 474228060Sbapt 475228060Sbapt/* Outputs a #line directive, referring to the given line number. */ 476228060Sbapt 477228060Sbaptstatic void 478228060Sbaptoutput_line_directive (unsigned int lineno) 479228060Sbapt{ 480228060Sbapt const char *file_name = option.get_input_file_name (); 481228060Sbapt if (file_name != NULL) 482228060Sbapt { 483228060Sbapt printf ("#line %u ", lineno); 484228060Sbapt output_string (file_name, strlen (file_name)); 485228060Sbapt printf ("\n"); 486228060Sbapt } 487228060Sbapt} 488228060Sbapt 489228060Sbapt/* ------------------------------------------------------------------------- */ 490228060Sbapt 491228060Sbapt/* Outputs a type and a const specifier (i.e. "const " or ""). 492228060Sbapt The output is terminated with a space. */ 493228060Sbapt 494228060Sbaptstatic void 495228060Sbaptoutput_const_type (const char *const_string, const char *type_string) 496228060Sbapt{ 497228060Sbapt if (type_string[strlen(type_string)-1] == '*') 498228060Sbapt /* For pointer types, put the 'const' after the type. */ 499228060Sbapt printf ("%s %s", type_string, const_string); 500228060Sbapt else 501228060Sbapt /* For scalar or struct types, put the 'const' before the type. */ 502228060Sbapt printf ("%s%s ", const_string, type_string); 503228060Sbapt} 504228060Sbapt 505228060Sbapt/* ----------------------- Output_Expr and subclasses ----------------------- */ 506228060Sbapt 507228060Sbapt/* This class outputs a general expression. */ 508228060Sbapt 509228060Sbaptstruct Output_Expr 510228060Sbapt{ 511228060Sbapt virtual void output_expr () const = 0; 512228060Sbapt Output_Expr () {} 513228060Sbapt virtual ~Output_Expr () {} 514228060Sbapt}; 515228060Sbapt 516228060Sbapt/* This class outputs an expression formed by a single string. */ 517228060Sbapt 518228060Sbaptstruct Output_Expr1 : public Output_Expr 519228060Sbapt{ 520228060Sbapt virtual void output_expr () const; 521228060Sbapt Output_Expr1 (const char *piece1) : _p1 (piece1) {} 522228060Sbapt virtual ~Output_Expr1 () {} 523228060Sbaptprivate: 524228060Sbapt const char *_p1; 525228060Sbapt}; 526228060Sbapt 527228060Sbaptvoid Output_Expr1::output_expr () const 528228060Sbapt{ 529228060Sbapt printf ("%s", _p1); 530228060Sbapt} 531228060Sbapt 532228060Sbapt#if 0 /* unused */ 533228060Sbapt 534228060Sbapt/* This class outputs an expression formed by the concatenation of two 535228060Sbapt strings. */ 536228060Sbapt 537228060Sbaptstruct Output_Expr2 : public Output_Expr 538228060Sbapt{ 539228060Sbapt virtual void output_expr () const; 540228060Sbapt Output_Expr2 (const char *piece1, const char *piece2) 541228060Sbapt : _p1 (piece1), _p2 (piece2) {} 542228060Sbapt virtual ~Output_Expr2 () {} 543228060Sbaptprivate: 544228060Sbapt const char *_p1; 545228060Sbapt const char *_p2; 546228060Sbapt}; 547228060Sbapt 548228060Sbaptvoid Output_Expr2::output_expr () const 549228060Sbapt{ 550228060Sbapt printf ("%s%s", _p1, _p2); 551228060Sbapt} 552228060Sbapt 553228060Sbapt#endif 554228060Sbapt 555228060Sbapt/* --------------------- Output_Compare and subclasses --------------------- */ 556228060Sbapt 557228060Sbapt/* This class outputs a comparison expression. */ 558228060Sbapt 559228060Sbaptstruct Output_Compare 560228060Sbapt{ 561228060Sbapt /* Outputs the comparison expression. 562228060Sbapt expr1 outputs a simple expression of type 'const char *' referring to 563228060Sbapt the string being looked up. expr2 outputs a simple expression of type 564228060Sbapt 'const char *' referring to the constant string stored in the gperf 565228060Sbapt generated hash table. */ 566228060Sbapt virtual void output_comparison (const Output_Expr& expr1, 567228060Sbapt const Output_Expr& expr2) const = 0; 568228060Sbapt /* Outputs the comparison expression for the first byte. 569228060Sbapt Returns true if the this comparison is complete. */ 570228060Sbapt bool output_firstchar_comparison (const Output_Expr& expr1, 571228060Sbapt const Output_Expr& expr2) const; 572228060Sbapt Output_Compare () {} 573228060Sbapt virtual ~Output_Compare () {} 574228060Sbapt}; 575228060Sbapt 576228060Sbaptbool Output_Compare::output_firstchar_comparison (const Output_Expr& expr1, 577228060Sbapt const Output_Expr& expr2) const 578228060Sbapt{ 579228060Sbapt /* First, we emit a comparison of the first byte of the two strings. 580228060Sbapt This catches most cases where the string being looked up is not in the 581228060Sbapt hash table but happens to have the same hash code as an element of the 582228060Sbapt hash table. */ 583228060Sbapt if (option[UPPERLOWER]) 584228060Sbapt { 585228060Sbapt /* Incomplete comparison, just for speedup. */ 586228060Sbapt printf ("(((unsigned char)*"); 587228060Sbapt expr1.output_expr (); 588228060Sbapt printf (" ^ (unsigned char)*"); 589228060Sbapt expr2.output_expr (); 590228060Sbapt printf (") & ~32) == 0"); 591228060Sbapt return false; 592228060Sbapt } 593228060Sbapt else 594228060Sbapt { 595228060Sbapt /* Complete comparison. */ 596228060Sbapt printf ("*"); 597228060Sbapt expr1.output_expr (); 598228060Sbapt printf (" == *"); 599228060Sbapt expr2.output_expr (); 600228060Sbapt return true; 601228060Sbapt } 602228060Sbapt} 603228060Sbapt 604228060Sbapt/* This class outputs a comparison using strcmp. */ 605228060Sbapt 606228060Sbaptstruct Output_Compare_Strcmp : public Output_Compare 607228060Sbapt{ 608228060Sbapt virtual void output_comparison (const Output_Expr& expr1, 609228060Sbapt const Output_Expr& expr2) const; 610228060Sbapt Output_Compare_Strcmp () {} 611228060Sbapt virtual ~Output_Compare_Strcmp () {} 612228060Sbapt}; 613228060Sbapt 614228060Sbaptvoid Output_Compare_Strcmp::output_comparison (const Output_Expr& expr1, 615228060Sbapt const Output_Expr& expr2) const 616228060Sbapt{ 617228060Sbapt bool firstchar_done = output_firstchar_comparison (expr1, expr2); 618228060Sbapt printf (" && !"); 619228060Sbapt if (option[UPPERLOWER]) 620228060Sbapt printf ("gperf_case_"); 621228060Sbapt printf ("strcmp ("); 622228060Sbapt if (firstchar_done) 623228060Sbapt { 624228060Sbapt expr1.output_expr (); 625228060Sbapt printf (" + 1, "); 626228060Sbapt expr2.output_expr (); 627228060Sbapt printf (" + 1"); 628228060Sbapt } 629228060Sbapt else 630228060Sbapt { 631228060Sbapt expr1.output_expr (); 632228060Sbapt printf (", "); 633228060Sbapt expr2.output_expr (); 634228060Sbapt } 635228060Sbapt printf (")"); 636228060Sbapt} 637228060Sbapt 638228060Sbapt/* This class outputs a comparison using strncmp. 639228060Sbapt Note that the length of expr1 will be available through the local variable 640228060Sbapt 'len'. */ 641228060Sbapt 642228060Sbaptstruct Output_Compare_Strncmp : public Output_Compare 643228060Sbapt{ 644228060Sbapt virtual void output_comparison (const Output_Expr& expr1, 645228060Sbapt const Output_Expr& expr2) const; 646228060Sbapt Output_Compare_Strncmp () {} 647228060Sbapt virtual ~Output_Compare_Strncmp () {} 648228060Sbapt}; 649228060Sbapt 650228060Sbaptvoid Output_Compare_Strncmp::output_comparison (const Output_Expr& expr1, 651228060Sbapt const Output_Expr& expr2) const 652228060Sbapt{ 653228060Sbapt bool firstchar_done = output_firstchar_comparison (expr1, expr2); 654228060Sbapt printf (" && !"); 655228060Sbapt if (option[UPPERLOWER]) 656228060Sbapt printf ("gperf_case_"); 657228060Sbapt printf ("strncmp ("); 658228060Sbapt if (firstchar_done) 659228060Sbapt { 660228060Sbapt expr1.output_expr (); 661228060Sbapt printf (" + 1, "); 662228060Sbapt expr2.output_expr (); 663228060Sbapt printf (" + 1, len - 1"); 664228060Sbapt } 665228060Sbapt else 666228060Sbapt { 667228060Sbapt expr1.output_expr (); 668228060Sbapt printf (", "); 669228060Sbapt expr2.output_expr (); 670228060Sbapt printf (", len"); 671228060Sbapt } 672228060Sbapt printf (") && "); 673228060Sbapt expr2.output_expr (); 674228060Sbapt printf ("[len] == '\\0'"); 675228060Sbapt} 676228060Sbapt 677228060Sbapt/* This class outputs a comparison using memcmp. 678228060Sbapt Note that the length of expr1 (available through the local variable 'len') 679228060Sbapt must be verified to be equal to the length of expr2 prior to this 680228060Sbapt comparison. */ 681228060Sbapt 682228060Sbaptstruct Output_Compare_Memcmp : public Output_Compare 683228060Sbapt{ 684228060Sbapt virtual void output_comparison (const Output_Expr& expr1, 685228060Sbapt const Output_Expr& expr2) const; 686228060Sbapt Output_Compare_Memcmp () {} 687228060Sbapt virtual ~Output_Compare_Memcmp () {} 688228060Sbapt}; 689228060Sbapt 690228060Sbaptvoid Output_Compare_Memcmp::output_comparison (const Output_Expr& expr1, 691228060Sbapt const Output_Expr& expr2) const 692228060Sbapt{ 693228060Sbapt bool firstchar_done = output_firstchar_comparison (expr1, expr2); 694228060Sbapt printf (" && !"); 695228060Sbapt if (option[UPPERLOWER]) 696228060Sbapt printf ("gperf_case_"); 697228060Sbapt printf ("memcmp ("); 698228060Sbapt if (firstchar_done) 699228060Sbapt { 700228060Sbapt expr1.output_expr (); 701228060Sbapt printf (" + 1, "); 702228060Sbapt expr2.output_expr (); 703228060Sbapt printf (" + 1, len - 1"); 704228060Sbapt } 705228060Sbapt else 706228060Sbapt { 707228060Sbapt expr1.output_expr (); 708228060Sbapt printf (", "); 709228060Sbapt expr2.output_expr (); 710228060Sbapt printf (", len"); 711228060Sbapt } 712228060Sbapt printf (")"); 713228060Sbapt} 714228060Sbapt 715228060Sbapt/* ------------------------------------------------------------------------- */ 716228060Sbapt 717228060Sbapt/* Generates a C expression for an asso_values[] reference. */ 718228060Sbapt 719228060Sbaptvoid 720228060SbaptOutput::output_asso_values_ref (int pos) const 721228060Sbapt{ 722228060Sbapt printf ("asso_values["); 723228060Sbapt /* Always cast to unsigned char. This is necessary when the alpha_inc 724228060Sbapt is nonzero, and also avoids a gcc warning "subscript has type 'char'". */ 725228060Sbapt printf ("(unsigned char)"); 726228060Sbapt if (pos == Positions::LASTCHAR) 727228060Sbapt printf ("str[len - 1]"); 728228060Sbapt else 729228060Sbapt { 730228060Sbapt printf ("str[%d]", pos); 731228060Sbapt if (_alpha_inc[pos]) 732228060Sbapt printf ("+%u", _alpha_inc[pos]); 733228060Sbapt } 734228060Sbapt printf ("]"); 735228060Sbapt} 736228060Sbapt 737228060Sbapt/* Generates C code for the hash function that returns the 738228060Sbapt proper encoding for each keyword. 739228060Sbapt The hash function has the signature 740228060Sbapt unsigned int <hash> (const char *str, unsigned int len). */ 741228060Sbapt 742228060Sbaptvoid 743228060SbaptOutput::output_hash_function () const 744228060Sbapt{ 745228060Sbapt /* Output the function's head. */ 746228060Sbapt if (option[CPLUSPLUS]) 747228060Sbapt printf ("inline "); 748228060Sbapt else if (option[KRC] | option[C] | option[ANSIC]) 749228060Sbapt printf ("#ifdef __GNUC__\n" 750228060Sbapt "__inline\n" 751228060Sbapt "#else\n" 752228060Sbapt "#ifdef __cplusplus\n" 753228060Sbapt "inline\n" 754228060Sbapt "#endif\n" 755228060Sbapt "#endif\n"); 756228060Sbapt 757228060Sbapt if (/* The function does not use the 'str' argument? */ 758228060Sbapt _key_positions.get_size() == 0 759228060Sbapt || /* The function uses 'str', but not the 'len' argument? */ 760228060Sbapt (option[NOLENGTH] 761228060Sbapt && _key_positions[0] < _min_key_len 762228060Sbapt && _key_positions[_key_positions.get_size() - 1] != Positions::LASTCHAR)) 763228060Sbapt /* Pacify lint. */ 764228060Sbapt printf ("/*ARGSUSED*/\n"); 765228060Sbapt 766228060Sbapt if (option[KRC] | option[C] | option[ANSIC]) 767228060Sbapt printf ("static "); 768228060Sbapt printf ("unsigned int\n"); 769228060Sbapt if (option[CPLUSPLUS]) 770228060Sbapt printf ("%s::", option.get_class_name ()); 771228060Sbapt printf ("%s ", option.get_hash_name ()); 772228060Sbapt printf (option[KRC] ? 773228060Sbapt "(str, len)\n" 774228060Sbapt " register char *str;\n" 775228060Sbapt " register unsigned int len;\n" : 776228060Sbapt option[C] ? 777228060Sbapt "(str, len)\n" 778228060Sbapt " register const char *str;\n" 779228060Sbapt " register unsigned int len;\n" : 780228060Sbapt option[ANSIC] | option[CPLUSPLUS] ? 781228060Sbapt "(register const char *str, register unsigned int len)\n" : 782228060Sbapt ""); 783228060Sbapt 784228060Sbapt /* Note that when the hash function is called, it has already been verified 785228060Sbapt that min_key_len <= len <= max_key_len. */ 786228060Sbapt 787228060Sbapt /* Output the function's body. */ 788228060Sbapt printf ("{\n"); 789228060Sbapt 790228060Sbapt /* First the asso_values array. */ 791228060Sbapt if (_key_positions.get_size() > 0) 792228060Sbapt { 793228060Sbapt printf (" static %s%s asso_values[] =\n" 794228060Sbapt " {", 795228060Sbapt const_readonly_array, 796228060Sbapt smallest_integral_type (_max_hash_value + 1)); 797228060Sbapt 798228060Sbapt const int columns = 10; 799228060Sbapt 800228060Sbapt /* Calculate maximum number of digits required for MAX_HASH_VALUE. */ 801228060Sbapt int field_width = 2; 802228060Sbapt for (int trunc = _max_hash_value; (trunc /= 10) > 0;) 803228060Sbapt field_width++; 804228060Sbapt 805228060Sbapt for (unsigned int count = 0; count < _alpha_size; count++) 806228060Sbapt { 807228060Sbapt if (count > 0) 808228060Sbapt printf (","); 809228060Sbapt if ((count % columns) == 0) 810228060Sbapt printf ("\n "); 811228060Sbapt printf ("%*d", field_width, _asso_values[count]); 812228060Sbapt } 813228060Sbapt 814228060Sbapt printf ("\n" 815228060Sbapt " };\n"); 816228060Sbapt } 817228060Sbapt 818228060Sbapt if (_key_positions.get_size() == 0) 819228060Sbapt { 820228060Sbapt /* Trivial case: No key positions at all. */ 821228060Sbapt printf (" return %s;\n", 822228060Sbapt option[NOLENGTH] ? "0" : "len"); 823228060Sbapt } 824228060Sbapt else 825228060Sbapt { 826228060Sbapt /* Iterate through the key positions. Remember that Positions::sort() 827228060Sbapt has sorted them in decreasing order, with Positions::LASTCHAR coming 828228060Sbapt last. */ 829228060Sbapt PositionIterator iter = _key_positions.iterator(_max_key_len); 830228060Sbapt int key_pos; 831228060Sbapt 832228060Sbapt /* Get the highest key position. */ 833228060Sbapt key_pos = iter.next (); 834228060Sbapt 835228060Sbapt if (key_pos == Positions::LASTCHAR || key_pos < _min_key_len) 836228060Sbapt { 837228060Sbapt /* We can perform additional optimizations here: 838228060Sbapt Write it out as a single expression. Note that the values 839228060Sbapt are added as 'int's even though the asso_values array may 840228060Sbapt contain 'unsigned char's or 'unsigned short's. */ 841228060Sbapt 842228060Sbapt printf (" return %s", 843228060Sbapt option[NOLENGTH] ? "" : "len + "); 844228060Sbapt 845228060Sbapt if (_key_positions.get_size() == 2 846228060Sbapt && _key_positions[0] == 0 847228060Sbapt && _key_positions[1] == Positions::LASTCHAR) 848228060Sbapt /* Optimize special case of "-k 1,$". */ 849228060Sbapt { 850228060Sbapt output_asso_values_ref (Positions::LASTCHAR); 851228060Sbapt printf (" + "); 852228060Sbapt output_asso_values_ref (0); 853228060Sbapt } 854228060Sbapt else 855228060Sbapt { 856228060Sbapt for (; key_pos != Positions::LASTCHAR; ) 857228060Sbapt { 858228060Sbapt output_asso_values_ref (key_pos); 859228060Sbapt if ((key_pos = iter.next ()) != PositionIterator::EOS) 860228060Sbapt printf (" + "); 861228060Sbapt else 862228060Sbapt break; 863228060Sbapt } 864228060Sbapt 865228060Sbapt if (key_pos == Positions::LASTCHAR) 866228060Sbapt output_asso_values_ref (Positions::LASTCHAR); 867228060Sbapt } 868228060Sbapt 869228060Sbapt printf (";\n"); 870228060Sbapt } 871228060Sbapt else 872228060Sbapt { 873228060Sbapt /* We've got to use the correct, but brute force, technique. */ 874228060Sbapt printf (" register int hval = %s;\n\n" 875228060Sbapt " switch (%s)\n" 876228060Sbapt " {\n" 877228060Sbapt " default:\n", 878228060Sbapt option[NOLENGTH] ? "0" : "len", 879228060Sbapt option[NOLENGTH] ? "len" : "hval"); 880228060Sbapt 881228060Sbapt while (key_pos != Positions::LASTCHAR && key_pos >= _max_key_len) 882228060Sbapt if ((key_pos = iter.next ()) == PositionIterator::EOS) 883228060Sbapt break; 884228060Sbapt 885228060Sbapt if (key_pos != PositionIterator::EOS && key_pos != Positions::LASTCHAR) 886228060Sbapt { 887228060Sbapt int i = key_pos; 888228060Sbapt do 889228060Sbapt { 890228060Sbapt if (i > key_pos) 891228060Sbapt printf (" /*FALLTHROUGH*/\n"); /* Pacify lint. */ 892228060Sbapt for ( ; i > key_pos; i--) 893228060Sbapt printf (" case %d:\n", i); 894228060Sbapt 895228060Sbapt printf (" hval += "); 896228060Sbapt output_asso_values_ref (key_pos); 897228060Sbapt printf (";\n"); 898228060Sbapt 899228060Sbapt key_pos = iter.next (); 900228060Sbapt } 901228060Sbapt while (key_pos != PositionIterator::EOS && key_pos != Positions::LASTCHAR); 902228060Sbapt 903228060Sbapt if (i >= _min_key_len) 904228060Sbapt printf (" /*FALLTHROUGH*/\n"); /* Pacify lint. */ 905228060Sbapt for ( ; i >= _min_key_len; i--) 906228060Sbapt printf (" case %d:\n", i); 907228060Sbapt } 908228060Sbapt 909228060Sbapt printf (" break;\n" 910228060Sbapt " }\n" 911228060Sbapt " return hval"); 912228060Sbapt if (key_pos == Positions::LASTCHAR) 913228060Sbapt { 914228060Sbapt printf (" + "); 915228060Sbapt output_asso_values_ref (Positions::LASTCHAR); 916228060Sbapt } 917228060Sbapt printf (";\n"); 918228060Sbapt } 919228060Sbapt } 920228060Sbapt printf ("}\n\n"); 921228060Sbapt} 922228060Sbapt 923228060Sbapt/* ------------------------------------------------------------------------- */ 924228060Sbapt 925228060Sbapt/* Prints out a table of keyword lengths, for use with the 926228060Sbapt comparison code in generated function 'in_word_set'. 927228060Sbapt Only called if option[LENTABLE]. */ 928228060Sbapt 929228060Sbaptvoid 930228060SbaptOutput::output_keylength_table () const 931228060Sbapt{ 932228060Sbapt const int columns = 14; 933228060Sbapt const char * const indent = option[GLOBAL] ? "" : " "; 934228060Sbapt 935228060Sbapt printf ("%sstatic %s%s %s[] =\n" 936228060Sbapt "%s {", 937228060Sbapt indent, const_readonly_array, 938228060Sbapt smallest_integral_type (_max_key_len), 939228060Sbapt option.get_lengthtable_name (), 940228060Sbapt indent); 941228060Sbapt 942228060Sbapt /* Generate an array of lengths, similar to output_keyword_table. */ 943228060Sbapt int index; 944228060Sbapt int column; 945228060Sbapt KeywordExt_List *temp; 946228060Sbapt 947228060Sbapt column = 0; 948228060Sbapt for (temp = _head, index = 0; temp; temp = temp->rest()) 949228060Sbapt { 950228060Sbapt KeywordExt *keyword = temp->first(); 951228060Sbapt 952228060Sbapt /* If generating a switch statement, and there is no user defined type, 953228060Sbapt we generate non-duplicates directly in the code. Only duplicates go 954228060Sbapt into the table. */ 955228060Sbapt if (option[SWITCH] && !option[TYPE] && !keyword->_duplicate_link) 956228060Sbapt continue; 957228060Sbapt 958228060Sbapt if (index < keyword->_hash_value && !option[SWITCH] && !option[DUP]) 959228060Sbapt { 960228060Sbapt /* Some blank entries. */ 961228060Sbapt for ( ; index < keyword->_hash_value; index++) 962228060Sbapt { 963228060Sbapt if (index > 0) 964228060Sbapt printf (","); 965228060Sbapt if ((column++ % columns) == 0) 966228060Sbapt printf ("\n%s ", indent); 967228060Sbapt printf ("%3d", 0); 968228060Sbapt } 969228060Sbapt } 970228060Sbapt 971228060Sbapt if (index > 0) 972228060Sbapt printf (","); 973228060Sbapt if ((column++ % columns) == 0) 974228060Sbapt printf("\n%s ", indent); 975228060Sbapt printf ("%3d", keyword->_allchars_length); 976228060Sbapt index++; 977228060Sbapt 978228060Sbapt /* Deal with duplicates specially. */ 979228060Sbapt if (keyword->_duplicate_link) // implies option[DUP] 980228060Sbapt for (KeywordExt *links = keyword->_duplicate_link; links; links = links->_duplicate_link) 981228060Sbapt { 982228060Sbapt printf (","); 983228060Sbapt if ((column++ % columns) == 0) 984228060Sbapt printf("\n%s ", indent); 985228060Sbapt printf ("%3d", links->_allchars_length); 986228060Sbapt index++; 987228060Sbapt } 988228060Sbapt } 989228060Sbapt 990228060Sbapt printf ("\n%s };\n", indent); 991228060Sbapt if (option[GLOBAL]) 992228060Sbapt printf ("\n"); 993228060Sbapt} 994228060Sbapt 995228060Sbapt/* ------------------------------------------------------------------------- */ 996228060Sbapt 997228060Sbapt/* Prints out the string pool, containing the strings of the keyword table. 998228060Sbapt Only called if option[SHAREDLIB]. */ 999228060Sbapt 1000228060Sbaptvoid 1001228060SbaptOutput::output_string_pool () const 1002228060Sbapt{ 1003228060Sbapt const char * const indent = option[TYPE] || option[GLOBAL] ? "" : " "; 1004228060Sbapt int index; 1005228060Sbapt KeywordExt_List *temp; 1006228060Sbapt 1007228060Sbapt printf ("%sstruct %s_t\n" 1008228060Sbapt "%s {\n", 1009228060Sbapt indent, option.get_stringpool_name (), indent); 1010228060Sbapt for (temp = _head, index = 0; temp; temp = temp->rest()) 1011228060Sbapt { 1012228060Sbapt KeywordExt *keyword = temp->first(); 1013228060Sbapt 1014228060Sbapt /* If generating a switch statement, and there is no user defined type, 1015228060Sbapt we generate non-duplicates directly in the code. Only duplicates go 1016228060Sbapt into the table. */ 1017228060Sbapt if (option[SWITCH] && !option[TYPE] && !keyword->_duplicate_link) 1018228060Sbapt continue; 1019228060Sbapt 1020228060Sbapt if (!option[SWITCH] && !option[DUP]) 1021228060Sbapt index = keyword->_hash_value; 1022228060Sbapt 1023228060Sbapt printf ("%s char %s_str%d[sizeof(", 1024228060Sbapt indent, option.get_stringpool_name (), index); 1025228060Sbapt output_string (keyword->_allchars, keyword->_allchars_length); 1026228060Sbapt printf (")];\n"); 1027228060Sbapt 1028228060Sbapt /* Deal with duplicates specially. */ 1029228060Sbapt if (keyword->_duplicate_link) // implies option[DUP] 1030228060Sbapt for (KeywordExt *links = keyword->_duplicate_link; links; links = links->_duplicate_link) 1031228060Sbapt if (!(links->_allchars_length == keyword->_allchars_length 1032228060Sbapt && memcmp (links->_allchars, keyword->_allchars, 1033228060Sbapt keyword->_allchars_length) == 0)) 1034228060Sbapt { 1035228060Sbapt index++; 1036228060Sbapt printf ("%s char %s_str%d[sizeof(", 1037228060Sbapt indent, option.get_stringpool_name (), index); 1038228060Sbapt output_string (links->_allchars, links->_allchars_length); 1039228060Sbapt printf (")];\n"); 1040228060Sbapt } 1041228060Sbapt 1042228060Sbapt index++; 1043228060Sbapt } 1044228060Sbapt printf ("%s };\n", 1045228060Sbapt indent); 1046228060Sbapt 1047228060Sbapt printf ("%sstatic %sstruct %s_t %s_contents =\n" 1048228060Sbapt "%s {\n", 1049228060Sbapt indent, const_readonly_array, option.get_stringpool_name (), 1050228060Sbapt option.get_stringpool_name (), indent); 1051228060Sbapt for (temp = _head, index = 0; temp; temp = temp->rest()) 1052228060Sbapt { 1053228060Sbapt KeywordExt *keyword = temp->first(); 1054228060Sbapt 1055228060Sbapt /* If generating a switch statement, and there is no user defined type, 1056228060Sbapt we generate non-duplicates directly in the code. Only duplicates go 1057228060Sbapt into the table. */ 1058228060Sbapt if (option[SWITCH] && !option[TYPE] && !keyword->_duplicate_link) 1059228060Sbapt continue; 1060228060Sbapt 1061228060Sbapt if (index > 0) 1062228060Sbapt printf (",\n"); 1063228060Sbapt 1064228060Sbapt if (!option[SWITCH] && !option[DUP]) 1065228060Sbapt index = keyword->_hash_value; 1066228060Sbapt 1067228060Sbapt printf ("%s ", 1068228060Sbapt indent); 1069228060Sbapt output_string (keyword->_allchars, keyword->_allchars_length); 1070228060Sbapt 1071228060Sbapt /* Deal with duplicates specially. */ 1072228060Sbapt if (keyword->_duplicate_link) // implies option[DUP] 1073228060Sbapt for (KeywordExt *links = keyword->_duplicate_link; links; links = links->_duplicate_link) 1074228060Sbapt if (!(links->_allchars_length == keyword->_allchars_length 1075228060Sbapt && memcmp (links->_allchars, keyword->_allchars, 1076228060Sbapt keyword->_allchars_length) == 0)) 1077228060Sbapt { 1078228060Sbapt index++; 1079228060Sbapt printf (",\n"); 1080228060Sbapt printf ("%s ", 1081228060Sbapt indent); 1082228060Sbapt output_string (links->_allchars, links->_allchars_length); 1083228060Sbapt } 1084228060Sbapt 1085228060Sbapt index++; 1086228060Sbapt } 1087228060Sbapt if (index > 0) 1088228060Sbapt printf ("\n"); 1089228060Sbapt printf ("%s };\n", 1090228060Sbapt indent); 1091228060Sbapt printf ("%s#define %s ((%schar *) &%s_contents)\n", 1092228060Sbapt indent, option.get_stringpool_name (), const_always, 1093228060Sbapt option.get_stringpool_name ()); 1094228060Sbapt if (option[GLOBAL]) 1095228060Sbapt printf ("\n"); 1096228060Sbapt} 1097228060Sbapt 1098228060Sbapt/* ------------------------------------------------------------------------- */ 1099228060Sbapt 1100228060Sbaptstatic void 1101228060Sbaptoutput_keyword_entry (KeywordExt *temp, int stringpool_index, const char *indent) 1102228060Sbapt{ 1103228060Sbapt if (option[TYPE]) 1104228060Sbapt output_line_directive (temp->_lineno); 1105228060Sbapt printf ("%s ", indent); 1106228060Sbapt if (option[TYPE]) 1107228060Sbapt printf ("{"); 1108228060Sbapt if (option[SHAREDLIB]) 1109228060Sbapt printf ("(int)(long)&((struct %s_t *)0)->%s_str%d", 1110228060Sbapt option.get_stringpool_name (), option.get_stringpool_name (), 1111228060Sbapt stringpool_index); 1112228060Sbapt else 1113228060Sbapt output_string (temp->_allchars, temp->_allchars_length); 1114228060Sbapt if (option[TYPE]) 1115228060Sbapt { 1116228060Sbapt if (strlen (temp->_rest) > 0) 1117228060Sbapt printf (",%s", temp->_rest); 1118228060Sbapt printf ("}"); 1119228060Sbapt } 1120228060Sbapt if (option[DEBUG]) 1121228060Sbapt printf (" /* hash value = %d, index = %d */", 1122228060Sbapt temp->_hash_value, temp->_final_index); 1123228060Sbapt} 1124228060Sbapt 1125228060Sbaptstatic void 1126228060Sbaptoutput_keyword_blank_entries (int count, const char *indent) 1127228060Sbapt{ 1128228060Sbapt int columns; 1129228060Sbapt if (option[TYPE]) 1130228060Sbapt { 1131228060Sbapt columns = 58 / (4 + (option[SHAREDLIB] ? 2 : option[NULLSTRINGS] ? 8 : 2) 1132228060Sbapt + strlen (option.get_initializer_suffix())); 1133228060Sbapt if (columns == 0) 1134228060Sbapt columns = 1; 1135228060Sbapt } 1136228060Sbapt else 1137228060Sbapt { 1138228060Sbapt columns = (option[SHAREDLIB] ? 9 : option[NULLSTRINGS] ? 4 : 9); 1139228060Sbapt } 1140228060Sbapt int column = 0; 1141228060Sbapt for (int i = 0; i < count; i++) 1142228060Sbapt { 1143228060Sbapt if ((column % columns) == 0) 1144228060Sbapt { 1145228060Sbapt if (i > 0) 1146228060Sbapt printf (",\n"); 1147228060Sbapt printf ("%s ", indent); 1148228060Sbapt } 1149228060Sbapt else 1150228060Sbapt { 1151228060Sbapt if (i > 0) 1152228060Sbapt printf (", "); 1153228060Sbapt } 1154228060Sbapt if (option[TYPE]) 1155228060Sbapt printf ("{"); 1156228060Sbapt if (option[SHAREDLIB]) 1157228060Sbapt printf ("-1"); 1158228060Sbapt else 1159228060Sbapt { 1160228060Sbapt if (option[NULLSTRINGS]) 1161228060Sbapt printf ("(char*)0"); 1162228060Sbapt else 1163228060Sbapt printf ("\"\""); 1164228060Sbapt } 1165228060Sbapt if (option[TYPE]) 1166228060Sbapt printf ("%s}", option.get_initializer_suffix()); 1167228060Sbapt column++; 1168228060Sbapt } 1169228060Sbapt} 1170228060Sbapt 1171228060Sbapt/* Prints out the array containing the keywords for the hash function. */ 1172228060Sbapt 1173228060Sbaptvoid 1174228060SbaptOutput::output_keyword_table () const 1175228060Sbapt{ 1176228060Sbapt const char *indent = option[GLOBAL] ? "" : " "; 1177228060Sbapt int index; 1178228060Sbapt KeywordExt_List *temp; 1179228060Sbapt 1180228060Sbapt printf ("%sstatic ", 1181228060Sbapt indent); 1182228060Sbapt output_const_type (const_readonly_array, _wordlist_eltype); 1183228060Sbapt printf ("%s[] =\n" 1184228060Sbapt "%s {\n", 1185228060Sbapt option.get_wordlist_name (), 1186228060Sbapt indent); 1187228060Sbapt 1188228060Sbapt /* Generate an array of reserved words at appropriate locations. */ 1189228060Sbapt 1190228060Sbapt for (temp = _head, index = 0; temp; temp = temp->rest()) 1191228060Sbapt { 1192228060Sbapt KeywordExt *keyword = temp->first(); 1193228060Sbapt 1194228060Sbapt /* If generating a switch statement, and there is no user defined type, 1195228060Sbapt we generate non-duplicates directly in the code. Only duplicates go 1196228060Sbapt into the table. */ 1197228060Sbapt if (option[SWITCH] && !option[TYPE] && !keyword->_duplicate_link) 1198228060Sbapt continue; 1199228060Sbapt 1200228060Sbapt if (index > 0) 1201228060Sbapt printf (",\n"); 1202228060Sbapt 1203228060Sbapt if (index < keyword->_hash_value && !option[SWITCH] && !option[DUP]) 1204228060Sbapt { 1205228060Sbapt /* Some blank entries. */ 1206228060Sbapt output_keyword_blank_entries (keyword->_hash_value - index, indent); 1207228060Sbapt printf (",\n"); 1208228060Sbapt index = keyword->_hash_value; 1209228060Sbapt } 1210228060Sbapt 1211228060Sbapt keyword->_final_index = index; 1212228060Sbapt 1213228060Sbapt output_keyword_entry (keyword, index, indent); 1214228060Sbapt 1215228060Sbapt /* Deal with duplicates specially. */ 1216228060Sbapt if (keyword->_duplicate_link) // implies option[DUP] 1217228060Sbapt for (KeywordExt *links = keyword->_duplicate_link; links; links = links->_duplicate_link) 1218228060Sbapt { 1219228060Sbapt links->_final_index = ++index; 1220228060Sbapt printf (",\n"); 1221228060Sbapt int stringpool_index = 1222228060Sbapt (links->_allchars_length == keyword->_allchars_length 1223228060Sbapt && memcmp (links->_allchars, keyword->_allchars, 1224228060Sbapt keyword->_allchars_length) == 0 1225228060Sbapt ? keyword->_final_index 1226228060Sbapt : links->_final_index); 1227228060Sbapt output_keyword_entry (links, stringpool_index, indent); 1228228060Sbapt } 1229228060Sbapt 1230228060Sbapt index++; 1231228060Sbapt } 1232228060Sbapt if (index > 0) 1233228060Sbapt printf ("\n"); 1234228060Sbapt 1235228060Sbapt printf ("%s };\n\n", indent); 1236228060Sbapt} 1237228060Sbapt 1238228060Sbapt/* ------------------------------------------------------------------------- */ 1239228060Sbapt 1240228060Sbapt/* Generates the large, sparse table that maps hash values into 1241228060Sbapt the smaller, contiguous range of the keyword table. */ 1242228060Sbapt 1243228060Sbaptvoid 1244228060SbaptOutput::output_lookup_array () const 1245228060Sbapt{ 1246228060Sbapt if (option[DUP]) 1247228060Sbapt { 1248228060Sbapt const int DEFAULT_VALUE = -1; 1249228060Sbapt 1250228060Sbapt /* Because of the way output_keyword_table works, every duplicate set is 1251228060Sbapt stored contiguously in the wordlist array. */ 1252228060Sbapt struct duplicate_entry 1253228060Sbapt { 1254228060Sbapt int hash_value; /* Hash value for this particular duplicate set. */ 1255228060Sbapt int index; /* Index into the main keyword storage array. */ 1256228060Sbapt int count; /* Number of consecutive duplicates at this index. */ 1257228060Sbapt }; 1258228060Sbapt 1259228060Sbapt duplicate_entry *duplicates = new duplicate_entry[_total_duplicates]; 1260228060Sbapt int *lookup_array = new int[_max_hash_value + 1 + 2*_total_duplicates]; 1261228060Sbapt int lookup_array_size = _max_hash_value + 1; 1262228060Sbapt duplicate_entry *dup_ptr = &duplicates[0]; 1263228060Sbapt int *lookup_ptr = &lookup_array[_max_hash_value + 1 + 2*_total_duplicates]; 1264228060Sbapt 1265228060Sbapt while (lookup_ptr > lookup_array) 1266228060Sbapt *--lookup_ptr = DEFAULT_VALUE; 1267228060Sbapt 1268228060Sbapt /* Now dup_ptr = &duplicates[0] and lookup_ptr = &lookup_array[0]. */ 1269228060Sbapt 1270228060Sbapt for (KeywordExt_List *temp = _head; temp; temp = temp->rest()) 1271228060Sbapt { 1272228060Sbapt int hash_value = temp->first()->_hash_value; 1273228060Sbapt lookup_array[hash_value] = temp->first()->_final_index; 1274228060Sbapt if (option[DEBUG]) 1275228060Sbapt fprintf (stderr, "keyword = %.*s, index = %d\n", 1276228060Sbapt temp->first()->_allchars_length, temp->first()->_allchars, temp->first()->_final_index); 1277228060Sbapt if (temp->first()->_duplicate_link) 1278228060Sbapt { 1279228060Sbapt /* Start a duplicate entry. */ 1280228060Sbapt dup_ptr->hash_value = hash_value; 1281228060Sbapt dup_ptr->index = temp->first()->_final_index; 1282228060Sbapt dup_ptr->count = 1; 1283228060Sbapt 1284228060Sbapt for (KeywordExt *ptr = temp->first()->_duplicate_link; ptr; ptr = ptr->_duplicate_link) 1285228060Sbapt { 1286228060Sbapt dup_ptr->count++; 1287228060Sbapt if (option[DEBUG]) 1288228060Sbapt fprintf (stderr, 1289228060Sbapt "static linked keyword = %.*s, index = %d\n", 1290228060Sbapt ptr->_allchars_length, ptr->_allchars, ptr->_final_index); 1291228060Sbapt } 1292228060Sbapt assert (dup_ptr->count >= 2); 1293228060Sbapt dup_ptr++; 1294228060Sbapt } 1295228060Sbapt } 1296228060Sbapt 1297228060Sbapt while (dup_ptr > duplicates) 1298228060Sbapt { 1299228060Sbapt dup_ptr--; 1300228060Sbapt 1301228060Sbapt if (option[DEBUG]) 1302228060Sbapt fprintf (stderr, 1303228060Sbapt "dup_ptr[%d]: hash_value = %d, index = %d, count = %d\n", 1304228060Sbapt dup_ptr - duplicates, 1305228060Sbapt dup_ptr->hash_value, dup_ptr->index, dup_ptr->count); 1306228060Sbapt 1307228060Sbapt int i; 1308228060Sbapt /* Start searching for available space towards the right part 1309228060Sbapt of the lookup array. */ 1310228060Sbapt for (i = dup_ptr->hash_value; i < lookup_array_size-1; i++) 1311228060Sbapt if (lookup_array[i] == DEFAULT_VALUE 1312228060Sbapt && lookup_array[i + 1] == DEFAULT_VALUE) 1313228060Sbapt goto found_i; 1314228060Sbapt /* If we didn't find it to the right look to the left instead... */ 1315228060Sbapt for (i = dup_ptr->hash_value-1; i >= 0; i--) 1316228060Sbapt if (lookup_array[i] == DEFAULT_VALUE 1317228060Sbapt && lookup_array[i + 1] == DEFAULT_VALUE) 1318228060Sbapt goto found_i; 1319228060Sbapt /* Append to the end of lookup_array. */ 1320228060Sbapt i = lookup_array_size; 1321228060Sbapt lookup_array_size += 2; 1322228060Sbapt found_i: 1323228060Sbapt /* Put in an indirection from dup_ptr->_hash_value to i. 1324228060Sbapt At i and i+1 store dup_ptr->_final_index and dup_ptr->count. */ 1325228060Sbapt assert (lookup_array[dup_ptr->hash_value] == dup_ptr->index); 1326228060Sbapt lookup_array[dup_ptr->hash_value] = - 1 - _total_keys - i; 1327228060Sbapt lookup_array[i] = - _total_keys + dup_ptr->index; 1328228060Sbapt lookup_array[i + 1] = - dup_ptr->count; 1329228060Sbapt /* All these three values are <= -2, distinct from DEFAULT_VALUE. */ 1330228060Sbapt } 1331228060Sbapt 1332228060Sbapt /* The values of the lookup array are now known. */ 1333228060Sbapt 1334228060Sbapt int min = INT_MAX; 1335228060Sbapt int max = INT_MIN; 1336228060Sbapt lookup_ptr = lookup_array + lookup_array_size; 1337228060Sbapt while (lookup_ptr > lookup_array) 1338228060Sbapt { 1339228060Sbapt int val = *--lookup_ptr; 1340228060Sbapt if (min > val) 1341228060Sbapt min = val; 1342228060Sbapt if (max < val) 1343228060Sbapt max = val; 1344228060Sbapt } 1345228060Sbapt 1346228060Sbapt const char *indent = option[GLOBAL] ? "" : " "; 1347228060Sbapt printf ("%sstatic %s%s lookup[] =\n" 1348228060Sbapt "%s {", 1349228060Sbapt indent, const_readonly_array, smallest_integral_type (min, max), 1350228060Sbapt indent); 1351228060Sbapt 1352228060Sbapt int field_width; 1353228060Sbapt /* Calculate maximum number of digits required for MIN..MAX. */ 1354228060Sbapt { 1355228060Sbapt field_width = 2; 1356228060Sbapt for (int trunc = max; (trunc /= 10) > 0;) 1357228060Sbapt field_width++; 1358228060Sbapt } 1359228060Sbapt if (min < 0) 1360228060Sbapt { 1361228060Sbapt int neg_field_width = 2; 1362228060Sbapt for (int trunc = -min; (trunc /= 10) > 0;) 1363228060Sbapt neg_field_width++; 1364228060Sbapt neg_field_width++; /* account for the minus sign */ 1365228060Sbapt if (field_width < neg_field_width) 1366228060Sbapt field_width = neg_field_width; 1367228060Sbapt } 1368228060Sbapt 1369228060Sbapt const int columns = 42 / field_width; 1370228060Sbapt int column; 1371228060Sbapt 1372228060Sbapt column = 0; 1373228060Sbapt for (int i = 0; i < lookup_array_size; i++) 1374228060Sbapt { 1375228060Sbapt if (i > 0) 1376228060Sbapt printf (","); 1377228060Sbapt if ((column++ % columns) == 0) 1378228060Sbapt printf("\n%s ", indent); 1379228060Sbapt printf ("%*d", field_width, lookup_array[i]); 1380228060Sbapt } 1381228060Sbapt printf ("\n%s };\n\n", indent); 1382228060Sbapt 1383228060Sbapt delete[] duplicates; 1384228060Sbapt delete[] lookup_array; 1385228060Sbapt } 1386228060Sbapt} 1387228060Sbapt 1388228060Sbapt/* ------------------------------------------------------------------------- */ 1389228060Sbapt 1390228060Sbapt/* Generate all pools needed for the lookup function. */ 1391228060Sbapt 1392228060Sbaptvoid 1393228060SbaptOutput::output_lookup_pools () const 1394228060Sbapt{ 1395228060Sbapt if (option[SWITCH]) 1396228060Sbapt { 1397228060Sbapt if (option[TYPE] || (option[DUP] && _total_duplicates > 0)) 1398228060Sbapt output_string_pool (); 1399228060Sbapt } 1400228060Sbapt else 1401228060Sbapt { 1402228060Sbapt output_string_pool (); 1403228060Sbapt } 1404228060Sbapt} 1405228060Sbapt 1406228060Sbapt/* Generate all the tables needed for the lookup function. */ 1407228060Sbapt 1408228060Sbaptvoid 1409228060SbaptOutput::output_lookup_tables () const 1410228060Sbapt{ 1411228060Sbapt if (option[SWITCH]) 1412228060Sbapt { 1413228060Sbapt /* Use the switch in place of lookup table. */ 1414228060Sbapt if (option[LENTABLE] && (option[DUP] && _total_duplicates > 0)) 1415228060Sbapt output_keylength_table (); 1416228060Sbapt if (option[TYPE] || (option[DUP] && _total_duplicates > 0)) 1417228060Sbapt output_keyword_table (); 1418228060Sbapt } 1419228060Sbapt else 1420228060Sbapt { 1421228060Sbapt /* Use the lookup table, in place of switch. */ 1422228060Sbapt if (option[LENTABLE]) 1423228060Sbapt output_keylength_table (); 1424228060Sbapt output_keyword_table (); 1425228060Sbapt output_lookup_array (); 1426228060Sbapt } 1427228060Sbapt} 1428228060Sbapt 1429228060Sbapt/* ------------------------------------------------------------------------- */ 1430228060Sbapt 1431228060Sbapt/* Output a single switch case (including duplicates). Advance list. */ 1432228060Sbapt 1433228060Sbaptstatic KeywordExt_List * 1434228060Sbaptoutput_switch_case (KeywordExt_List *list, int indent, int *jumps_away) 1435228060Sbapt{ 1436228060Sbapt if (option[DEBUG]) 1437228060Sbapt printf ("%*s/* hash value = %4d, keyword = \"%.*s\" */\n", 1438228060Sbapt indent, "", list->first()->_hash_value, list->first()->_allchars_length, list->first()->_allchars); 1439228060Sbapt 1440228060Sbapt if (option[DUP] && list->first()->_duplicate_link) 1441228060Sbapt { 1442228060Sbapt if (option[LENTABLE]) 1443228060Sbapt printf ("%*slengthptr = &%s[%d];\n", 1444228060Sbapt indent, "", option.get_lengthtable_name (), list->first()->_final_index); 1445228060Sbapt printf ("%*swordptr = &%s[%d];\n", 1446228060Sbapt indent, "", option.get_wordlist_name (), list->first()->_final_index); 1447228060Sbapt 1448228060Sbapt int count = 0; 1449228060Sbapt for (KeywordExt *links = list->first(); links; links = links->_duplicate_link) 1450228060Sbapt count++; 1451228060Sbapt 1452228060Sbapt printf ("%*swordendptr = wordptr + %d;\n" 1453228060Sbapt "%*sgoto multicompare;\n", 1454228060Sbapt indent, "", count, 1455228060Sbapt indent, ""); 1456228060Sbapt *jumps_away = 1; 1457228060Sbapt } 1458228060Sbapt else 1459228060Sbapt { 1460228060Sbapt if (option[LENTABLE]) 1461228060Sbapt { 1462228060Sbapt printf ("%*sif (len == %d)\n" 1463228060Sbapt "%*s {\n", 1464228060Sbapt indent, "", list->first()->_allchars_length, 1465228060Sbapt indent, ""); 1466228060Sbapt indent += 4; 1467228060Sbapt } 1468228060Sbapt printf ("%*sresword = ", 1469228060Sbapt indent, ""); 1470228060Sbapt if (option[TYPE]) 1471228060Sbapt printf ("&%s[%d]", option.get_wordlist_name (), list->first()->_final_index); 1472228060Sbapt else 1473228060Sbapt output_string (list->first()->_allchars, list->first()->_allchars_length); 1474228060Sbapt printf (";\n"); 1475228060Sbapt printf ("%*sgoto compare;\n", 1476228060Sbapt indent, ""); 1477228060Sbapt if (option[LENTABLE]) 1478228060Sbapt { 1479228060Sbapt indent -= 4; 1480228060Sbapt printf ("%*s }\n", 1481228060Sbapt indent, ""); 1482228060Sbapt } 1483228060Sbapt else 1484228060Sbapt *jumps_away = 1; 1485228060Sbapt } 1486228060Sbapt 1487228060Sbapt return list->rest(); 1488228060Sbapt} 1489228060Sbapt 1490228060Sbapt/* Output a total of size cases, grouped into num_switches switch statements, 1491228060Sbapt where 0 < num_switches <= size. */ 1492228060Sbapt 1493228060Sbaptstatic void 1494228060Sbaptoutput_switches (KeywordExt_List *list, int num_switches, int size, int min_hash_value, int max_hash_value, int indent) 1495228060Sbapt{ 1496228060Sbapt if (option[DEBUG]) 1497228060Sbapt printf ("%*s/* know %d <= key <= %d, contains %d cases */\n", 1498228060Sbapt indent, "", min_hash_value, max_hash_value, size); 1499228060Sbapt 1500228060Sbapt if (num_switches > 1) 1501228060Sbapt { 1502228060Sbapt int part1 = num_switches / 2; 1503228060Sbapt int part2 = num_switches - part1; 1504228060Sbapt int size1 = static_cast<int>(static_cast<double>(size) / static_cast<double>(num_switches) * static_cast<double>(part1) + 0.5); 1505228060Sbapt int size2 = size - size1; 1506228060Sbapt 1507228060Sbapt KeywordExt_List *temp = list; 1508228060Sbapt for (int count = size1; count > 0; count--) 1509228060Sbapt temp = temp->rest(); 1510228060Sbapt 1511228060Sbapt printf ("%*sif (key < %d)\n" 1512228060Sbapt "%*s {\n", 1513228060Sbapt indent, "", temp->first()->_hash_value, 1514228060Sbapt indent, ""); 1515228060Sbapt 1516228060Sbapt output_switches (list, part1, size1, min_hash_value, temp->first()->_hash_value-1, indent+4); 1517228060Sbapt 1518228060Sbapt printf ("%*s }\n" 1519228060Sbapt "%*selse\n" 1520228060Sbapt "%*s {\n", 1521228060Sbapt indent, "", indent, "", indent, ""); 1522228060Sbapt 1523228060Sbapt output_switches (temp, part2, size2, temp->first()->_hash_value, max_hash_value, indent+4); 1524228060Sbapt 1525228060Sbapt printf ("%*s }\n", 1526228060Sbapt indent, ""); 1527228060Sbapt } 1528228060Sbapt else 1529228060Sbapt { 1530228060Sbapt /* Output a single switch. */ 1531228060Sbapt int lowest_case_value = list->first()->_hash_value; 1532228060Sbapt if (size == 1) 1533228060Sbapt { 1534228060Sbapt int jumps_away = 0; 1535228060Sbapt assert (min_hash_value <= lowest_case_value); 1536228060Sbapt assert (lowest_case_value <= max_hash_value); 1537228060Sbapt if (min_hash_value == max_hash_value) 1538228060Sbapt output_switch_case (list, indent, &jumps_away); 1539228060Sbapt else 1540228060Sbapt { 1541228060Sbapt printf ("%*sif (key == %d)\n" 1542228060Sbapt "%*s {\n", 1543228060Sbapt indent, "", lowest_case_value, 1544228060Sbapt indent, ""); 1545228060Sbapt output_switch_case (list, indent+4, &jumps_away); 1546228060Sbapt printf ("%*s }\n", 1547228060Sbapt indent, ""); 1548228060Sbapt } 1549228060Sbapt } 1550228060Sbapt else 1551228060Sbapt { 1552228060Sbapt if (lowest_case_value == 0) 1553228060Sbapt printf ("%*sswitch (key)\n", indent, ""); 1554228060Sbapt else 1555228060Sbapt printf ("%*sswitch (key - %d)\n", indent, "", lowest_case_value); 1556228060Sbapt printf ("%*s {\n", 1557228060Sbapt indent, ""); 1558228060Sbapt for (; size > 0; size--) 1559228060Sbapt { 1560228060Sbapt int jumps_away = 0; 1561228060Sbapt printf ("%*s case %d:\n", 1562228060Sbapt indent, "", list->first()->_hash_value - lowest_case_value); 1563228060Sbapt list = output_switch_case (list, indent+6, &jumps_away); 1564228060Sbapt if (!jumps_away) 1565228060Sbapt printf ("%*s break;\n", 1566228060Sbapt indent, ""); 1567228060Sbapt } 1568228060Sbapt printf ("%*s }\n", 1569228060Sbapt indent, ""); 1570228060Sbapt } 1571228060Sbapt } 1572228060Sbapt} 1573228060Sbapt 1574228060Sbapt/* Generates C code to perform the keyword lookup. */ 1575228060Sbapt 1576228060Sbaptvoid 1577228060SbaptOutput::output_lookup_function_body (const Output_Compare& comparison) const 1578228060Sbapt{ 1579228060Sbapt printf (" if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)\n" 1580228060Sbapt " {\n" 1581228060Sbapt " register int key = %s (str, len);\n\n", 1582228060Sbapt option.get_hash_name ()); 1583228060Sbapt 1584228060Sbapt if (option[SWITCH]) 1585228060Sbapt { 1586228060Sbapt int switch_size = num_hash_values (); 1587228060Sbapt int num_switches = option.get_total_switches (); 1588228060Sbapt if (num_switches > switch_size) 1589228060Sbapt num_switches = switch_size; 1590228060Sbapt 1591228060Sbapt printf (" if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE)\n" 1592228060Sbapt " {\n"); 1593228060Sbapt if (option[DUP] && _total_duplicates > 0) 1594228060Sbapt { 1595228060Sbapt if (option[LENTABLE]) 1596228060Sbapt printf (" register %s%s *lengthptr;\n", 1597228060Sbapt const_always, smallest_integral_type (_max_key_len)); 1598228060Sbapt printf (" register "); 1599228060Sbapt output_const_type (const_readonly_array, _wordlist_eltype); 1600228060Sbapt printf ("*wordptr;\n"); 1601228060Sbapt printf (" register "); 1602228060Sbapt output_const_type (const_readonly_array, _wordlist_eltype); 1603228060Sbapt printf ("*wordendptr;\n"); 1604228060Sbapt } 1605228060Sbapt if (option[TYPE]) 1606228060Sbapt { 1607228060Sbapt printf (" register "); 1608228060Sbapt output_const_type (const_readonly_array, _struct_tag); 1609228060Sbapt printf ("*resword;\n\n"); 1610228060Sbapt } 1611228060Sbapt else 1612228060Sbapt printf (" register %sresword;\n\n", 1613228060Sbapt _struct_tag); 1614228060Sbapt 1615228060Sbapt output_switches (_head, num_switches, switch_size, _min_hash_value, _max_hash_value, 10); 1616228060Sbapt 1617228060Sbapt printf (" return 0;\n"); 1618228060Sbapt if (option[DUP] && _total_duplicates > 0) 1619228060Sbapt { 1620228060Sbapt int indent = 8; 1621228060Sbapt printf ("%*smulticompare:\n" 1622228060Sbapt "%*s while (wordptr < wordendptr)\n" 1623228060Sbapt "%*s {\n", 1624228060Sbapt indent, "", indent, "", indent, ""); 1625228060Sbapt if (option[LENTABLE]) 1626228060Sbapt { 1627228060Sbapt printf ("%*s if (len == *lengthptr)\n" 1628228060Sbapt "%*s {\n", 1629228060Sbapt indent, "", indent, ""); 1630228060Sbapt indent += 4; 1631228060Sbapt } 1632228060Sbapt printf ("%*s register %schar *s = ", 1633228060Sbapt indent, "", const_always); 1634228060Sbapt if (option[TYPE]) 1635228060Sbapt printf ("wordptr->%s", option.get_slot_name ()); 1636228060Sbapt else 1637228060Sbapt printf ("*wordptr"); 1638228060Sbapt if (option[SHAREDLIB]) 1639228060Sbapt printf (" + %s", 1640228060Sbapt option.get_stringpool_name ()); 1641228060Sbapt printf (";\n\n" 1642228060Sbapt "%*s if (", 1643228060Sbapt indent, ""); 1644228060Sbapt comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s")); 1645228060Sbapt printf (")\n" 1646228060Sbapt "%*s return %s;\n", 1647228060Sbapt indent, "", 1648228060Sbapt option[TYPE] ? "wordptr" : "s"); 1649228060Sbapt if (option[LENTABLE]) 1650228060Sbapt { 1651228060Sbapt indent -= 4; 1652228060Sbapt printf ("%*s }\n", 1653228060Sbapt indent, ""); 1654228060Sbapt } 1655228060Sbapt if (option[LENTABLE]) 1656228060Sbapt printf ("%*s lengthptr++;\n", 1657228060Sbapt indent, ""); 1658228060Sbapt printf ("%*s wordptr++;\n" 1659228060Sbapt "%*s }\n" 1660228060Sbapt "%*s return 0;\n", 1661228060Sbapt indent, "", indent, "", indent, ""); 1662228060Sbapt } 1663228060Sbapt printf (" compare:\n"); 1664228060Sbapt if (option[TYPE]) 1665228060Sbapt { 1666228060Sbapt printf (" {\n" 1667228060Sbapt " register %schar *s = resword->%s", 1668228060Sbapt const_always, option.get_slot_name ()); 1669228060Sbapt if (option[SHAREDLIB]) 1670228060Sbapt printf (" + %s", 1671228060Sbapt option.get_stringpool_name ()); 1672228060Sbapt printf (";\n\n" 1673228060Sbapt " if ("); 1674228060Sbapt comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s")); 1675228060Sbapt printf (")\n" 1676228060Sbapt " return resword;\n" 1677228060Sbapt " }\n"); 1678228060Sbapt } 1679228060Sbapt else 1680228060Sbapt { 1681228060Sbapt printf (" if ("); 1682228060Sbapt comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("resword")); 1683228060Sbapt printf (")\n" 1684228060Sbapt " return resword;\n"); 1685228060Sbapt } 1686228060Sbapt printf (" }\n"); 1687228060Sbapt } 1688228060Sbapt else 1689228060Sbapt { 1690228060Sbapt printf (" if (key <= MAX_HASH_VALUE && key >= 0)\n"); 1691228060Sbapt 1692228060Sbapt if (option[DUP]) 1693228060Sbapt { 1694228060Sbapt int indent = 8; 1695228060Sbapt printf ("%*s{\n" 1696228060Sbapt "%*s register int index = lookup[key];\n\n" 1697228060Sbapt "%*s if (index >= 0)\n", 1698228060Sbapt indent, "", indent, "", indent, ""); 1699228060Sbapt if (option[LENTABLE]) 1700228060Sbapt { 1701228060Sbapt printf ("%*s {\n" 1702228060Sbapt "%*s if (len == %s[index])\n", 1703228060Sbapt indent, "", indent, "", option.get_lengthtable_name ()); 1704228060Sbapt indent += 4; 1705228060Sbapt } 1706228060Sbapt printf ("%*s {\n" 1707228060Sbapt "%*s register %schar *s = %s[index]", 1708228060Sbapt indent, "", 1709228060Sbapt indent, "", const_always, option.get_wordlist_name ()); 1710228060Sbapt if (option[TYPE]) 1711228060Sbapt printf (".%s", option.get_slot_name ()); 1712228060Sbapt if (option[SHAREDLIB]) 1713228060Sbapt printf (" + %s", 1714228060Sbapt option.get_stringpool_name ()); 1715228060Sbapt printf (";\n\n" 1716228060Sbapt "%*s if (", 1717228060Sbapt indent, ""); 1718228060Sbapt comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s")); 1719228060Sbapt printf (")\n" 1720228060Sbapt "%*s return ", 1721228060Sbapt indent, ""); 1722228060Sbapt if (option[TYPE]) 1723228060Sbapt printf ("&%s[index]", option.get_wordlist_name ()); 1724228060Sbapt else 1725228060Sbapt printf ("s"); 1726228060Sbapt printf (";\n" 1727228060Sbapt "%*s }\n", 1728228060Sbapt indent, ""); 1729228060Sbapt if (option[LENTABLE]) 1730228060Sbapt { 1731228060Sbapt indent -= 4; 1732228060Sbapt printf ("%*s }\n", indent, ""); 1733228060Sbapt } 1734228060Sbapt if (_total_duplicates > 0) 1735228060Sbapt { 1736228060Sbapt printf ("%*s else if (index < -TOTAL_KEYWORDS)\n" 1737228060Sbapt "%*s {\n" 1738228060Sbapt "%*s register int offset = - 1 - TOTAL_KEYWORDS - index;\n", 1739228060Sbapt indent, "", indent, "", indent, ""); 1740228060Sbapt if (option[LENTABLE]) 1741228060Sbapt printf ("%*s register %s%s *lengthptr = &%s[TOTAL_KEYWORDS + lookup[offset]];\n", 1742228060Sbapt indent, "", const_always, smallest_integral_type (_max_key_len), 1743228060Sbapt option.get_lengthtable_name ()); 1744228060Sbapt printf ("%*s register ", 1745228060Sbapt indent, ""); 1746228060Sbapt output_const_type (const_readonly_array, _wordlist_eltype); 1747228060Sbapt printf ("*wordptr = &%s[TOTAL_KEYWORDS + lookup[offset]];\n", 1748228060Sbapt option.get_wordlist_name ()); 1749228060Sbapt printf ("%*s register ", 1750228060Sbapt indent, ""); 1751228060Sbapt output_const_type (const_readonly_array, _wordlist_eltype); 1752228060Sbapt printf ("*wordendptr = wordptr + -lookup[offset + 1];\n\n"); 1753228060Sbapt printf ("%*s while (wordptr < wordendptr)\n" 1754228060Sbapt "%*s {\n", 1755228060Sbapt indent, "", indent, ""); 1756228060Sbapt if (option[LENTABLE]) 1757228060Sbapt { 1758228060Sbapt printf ("%*s if (len == *lengthptr)\n" 1759228060Sbapt "%*s {\n", 1760228060Sbapt indent, "", indent, ""); 1761228060Sbapt indent += 4; 1762228060Sbapt } 1763228060Sbapt printf ("%*s register %schar *s = ", 1764228060Sbapt indent, "", const_always); 1765228060Sbapt if (option[TYPE]) 1766228060Sbapt printf ("wordptr->%s", option.get_slot_name ()); 1767228060Sbapt else 1768228060Sbapt printf ("*wordptr"); 1769228060Sbapt if (option[SHAREDLIB]) 1770228060Sbapt printf (" + %s", 1771228060Sbapt option.get_stringpool_name ()); 1772228060Sbapt printf (";\n\n" 1773228060Sbapt "%*s if (", 1774228060Sbapt indent, ""); 1775228060Sbapt comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s")); 1776228060Sbapt printf (")\n" 1777228060Sbapt "%*s return %s;\n", 1778228060Sbapt indent, "", 1779228060Sbapt option[TYPE] ? "wordptr" : "s"); 1780228060Sbapt if (option[LENTABLE]) 1781228060Sbapt { 1782228060Sbapt indent -= 4; 1783228060Sbapt printf ("%*s }\n", 1784228060Sbapt indent, ""); 1785228060Sbapt } 1786228060Sbapt if (option[LENTABLE]) 1787228060Sbapt printf ("%*s lengthptr++;\n", 1788228060Sbapt indent, ""); 1789228060Sbapt printf ("%*s wordptr++;\n" 1790228060Sbapt "%*s }\n" 1791228060Sbapt "%*s }\n", 1792228060Sbapt indent, "", indent, "", indent, ""); 1793228060Sbapt } 1794228060Sbapt printf ("%*s}\n", 1795228060Sbapt indent, ""); 1796228060Sbapt } 1797228060Sbapt else 1798228060Sbapt { 1799228060Sbapt int indent = 8; 1800228060Sbapt if (option[LENTABLE]) 1801228060Sbapt { 1802228060Sbapt printf ("%*sif (len == %s[key])\n", 1803228060Sbapt indent, "", option.get_lengthtable_name ()); 1804228060Sbapt indent += 2; 1805228060Sbapt } 1806228060Sbapt 1807228060Sbapt if (option[SHAREDLIB]) 1808228060Sbapt { 1809228060Sbapt if (!option[LENTABLE]) 1810228060Sbapt { 1811228060Sbapt printf ("%*s{\n" 1812228060Sbapt "%*s register int o = %s[key]", 1813228060Sbapt indent, "", 1814228060Sbapt indent, "", option.get_wordlist_name ()); 1815228060Sbapt if (option[TYPE]) 1816228060Sbapt printf (".%s", option.get_slot_name ()); 1817228060Sbapt printf (";\n" 1818228060Sbapt "%*s if (o >= 0)\n" 1819228060Sbapt "%*s {\n", 1820228060Sbapt indent, "", 1821228060Sbapt indent, ""); 1822228060Sbapt indent += 4; 1823228060Sbapt printf ("%*s register %schar *s = o", 1824228060Sbapt indent, "", const_always); 1825228060Sbapt } 1826228060Sbapt else 1827228060Sbapt { 1828228060Sbapt /* No need for the (o >= 0) test, because the 1829228060Sbapt (len == lengthtable[key]) test already guarantees that 1830228060Sbapt key points to nonempty table entry. */ 1831228060Sbapt printf ("%*s{\n" 1832228060Sbapt "%*s register %schar *s = %s[key]", 1833228060Sbapt indent, "", 1834228060Sbapt indent, "", const_always, 1835228060Sbapt option.get_wordlist_name ()); 1836228060Sbapt if (option[TYPE]) 1837228060Sbapt printf (".%s", option.get_slot_name ()); 1838228060Sbapt } 1839228060Sbapt printf (" + %s", 1840228060Sbapt option.get_stringpool_name ()); 1841228060Sbapt } 1842228060Sbapt else 1843228060Sbapt { 1844228060Sbapt printf ("%*s{\n" 1845228060Sbapt "%*s register %schar *s = %s[key]", 1846228060Sbapt indent, "", 1847228060Sbapt indent, "", const_always, option.get_wordlist_name ()); 1848228060Sbapt if (option[TYPE]) 1849228060Sbapt printf (".%s", option.get_slot_name ()); 1850228060Sbapt } 1851228060Sbapt 1852228060Sbapt printf (";\n\n" 1853228060Sbapt "%*s if (", 1854228060Sbapt indent, ""); 1855228060Sbapt if (!option[SHAREDLIB] && option[NULLSTRINGS]) 1856228060Sbapt printf ("s && "); 1857228060Sbapt comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s")); 1858228060Sbapt printf (")\n" 1859228060Sbapt "%*s return ", 1860228060Sbapt indent, ""); 1861228060Sbapt if (option[TYPE]) 1862228060Sbapt printf ("&%s[key]", option.get_wordlist_name ()); 1863228060Sbapt else 1864228060Sbapt printf ("s"); 1865228060Sbapt printf (";\n"); 1866228060Sbapt if (option[SHAREDLIB] && !option[LENTABLE]) 1867228060Sbapt { 1868228060Sbapt indent -= 4; 1869228060Sbapt printf ("%*s }\n", 1870228060Sbapt indent, ""); 1871228060Sbapt } 1872228060Sbapt printf ("%*s}\n", 1873228060Sbapt indent, ""); 1874228060Sbapt } 1875228060Sbapt } 1876228060Sbapt printf (" }\n" 1877228060Sbapt " return 0;\n"); 1878228060Sbapt} 1879228060Sbapt 1880228060Sbapt/* Generates C code for the lookup function. */ 1881228060Sbapt 1882228060Sbaptvoid 1883228060SbaptOutput::output_lookup_function () const 1884228060Sbapt{ 1885228060Sbapt /* Output the function's head. */ 1886228060Sbapt if (option[KRC] | option[C] | option[ANSIC]) 1887228060Sbapt /* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 1888228060Sbapt inline semantics, unless -fgnu89-inline is used. It defines a macro 1889228060Sbapt __GNUC_STDC_INLINE__ to indicate this situation. */ 1890228060Sbapt printf ("#ifdef __GNUC__\n" 1891228060Sbapt "__inline\n" 1892228060Sbapt "#ifdef __GNUC_STDC_INLINE__\n" 1893228060Sbapt "__attribute__ ((__gnu_inline__))\n" 1894228060Sbapt "#endif\n" 1895228060Sbapt "#endif\n"); 1896228060Sbapt 1897228060Sbapt printf ("%s%s\n", 1898228060Sbapt const_for_struct, _return_type); 1899228060Sbapt if (option[CPLUSPLUS]) 1900228060Sbapt printf ("%s::", option.get_class_name ()); 1901228060Sbapt printf ("%s ", option.get_function_name ()); 1902228060Sbapt printf (option[KRC] ? 1903228060Sbapt "(str, len)\n" 1904228060Sbapt " register char *str;\n" 1905228060Sbapt " register unsigned int len;\n" : 1906228060Sbapt option[C] ? 1907228060Sbapt "(str, len)\n" 1908228060Sbapt " register const char *str;\n" 1909228060Sbapt " register unsigned int len;\n" : 1910228060Sbapt option[ANSIC] | option[CPLUSPLUS] ? 1911228060Sbapt "(register const char *str, register unsigned int len)\n" : 1912228060Sbapt ""); 1913228060Sbapt 1914228060Sbapt /* Output the function's body. */ 1915228060Sbapt printf ("{\n"); 1916228060Sbapt 1917228060Sbapt if (option[ENUM] && !option[GLOBAL]) 1918228060Sbapt { 1919228060Sbapt Output_Enum style (" "); 1920228060Sbapt output_constants (style); 1921228060Sbapt } 1922228060Sbapt 1923228060Sbapt if (option[SHAREDLIB] && !(option[GLOBAL] || option[TYPE])) 1924228060Sbapt output_lookup_pools (); 1925228060Sbapt if (!option[GLOBAL]) 1926228060Sbapt output_lookup_tables (); 1927228060Sbapt 1928228060Sbapt if (option[LENTABLE]) 1929228060Sbapt output_lookup_function_body (Output_Compare_Memcmp ()); 1930228060Sbapt else 1931228060Sbapt { 1932228060Sbapt if (option[COMP]) 1933228060Sbapt output_lookup_function_body (Output_Compare_Strncmp ()); 1934228060Sbapt else 1935228060Sbapt output_lookup_function_body (Output_Compare_Strcmp ()); 1936228060Sbapt } 1937228060Sbapt 1938228060Sbapt printf ("}\n"); 1939228060Sbapt} 1940228060Sbapt 1941228060Sbapt/* ------------------------------------------------------------------------- */ 1942228060Sbapt 1943228060Sbapt/* Generates the hash function and the key word recognizer function 1944228060Sbapt based upon the user's Options. */ 1945228060Sbapt 1946228060Sbaptvoid 1947228060SbaptOutput::output () 1948228060Sbapt{ 1949228060Sbapt compute_min_max (); 1950228060Sbapt 1951228060Sbapt if (option[C] | option[ANSIC] | option[CPLUSPLUS]) 1952228060Sbapt { 1953228060Sbapt const_always = "const "; 1954228060Sbapt const_readonly_array = (option[CONST] ? "const " : ""); 1955228060Sbapt const_for_struct = ((option[CONST] && option[TYPE]) ? "const " : ""); 1956228060Sbapt } 1957228060Sbapt else 1958228060Sbapt { 1959228060Sbapt const_always = ""; 1960228060Sbapt const_readonly_array = ""; 1961228060Sbapt const_for_struct = ""; 1962228060Sbapt } 1963228060Sbapt 1964228060Sbapt if (!option[TYPE]) 1965228060Sbapt { 1966228060Sbapt _return_type = (const_always[0] ? "const char *" : "char *"); 1967228060Sbapt _struct_tag = (const_always[0] ? "const char *" : "char *"); 1968228060Sbapt } 1969228060Sbapt 1970228060Sbapt _wordlist_eltype = (option[SHAREDLIB] && !option[TYPE] ? "int" : _struct_tag); 1971228060Sbapt 1972228060Sbapt printf ("/* "); 1973228060Sbapt if (option[KRC]) 1974228060Sbapt printf ("KR-C"); 1975228060Sbapt else if (option[C]) 1976228060Sbapt printf ("C"); 1977228060Sbapt else if (option[ANSIC]) 1978228060Sbapt printf ("ANSI-C"); 1979228060Sbapt else if (option[CPLUSPLUS]) 1980228060Sbapt printf ("C++"); 1981228060Sbapt printf (" code produced by gperf version %s */\n", version_string); 1982228060Sbapt option.print_options (); 1983228060Sbapt printf ("\n"); 1984228060Sbapt if (!option[POSITIONS]) 1985228060Sbapt { 1986228060Sbapt printf ("/* Computed positions: -k'"); 1987228060Sbapt _key_positions.print(); 1988228060Sbapt printf ("' */\n"); 1989228060Sbapt } 1990228060Sbapt printf ("\n"); 1991228060Sbapt 1992228060Sbapt if (_charset_dependent 1993228060Sbapt && (_key_positions.get_size() > 0 || option[UPPERLOWER])) 1994228060Sbapt { 1995228060Sbapt /* The generated tables assume that the execution character set is 1996228060Sbapt based on ISO-646, not EBCDIC. */ 1997228060Sbapt printf ("#if !((' ' == 32) && ('!' == 33) && ('\"' == 34) && ('#' == 35) \\\n" 1998228060Sbapt " && ('%%' == 37) && ('&' == 38) && ('\\'' == 39) && ('(' == 40) \\\n" 1999228060Sbapt " && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \\\n" 2000228060Sbapt " && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \\\n" 2001228060Sbapt " && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \\\n" 2002228060Sbapt " && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \\\n" 2003228060Sbapt " && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \\\n" 2004228060Sbapt " && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \\\n" 2005228060Sbapt " && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \\\n" 2006228060Sbapt " && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \\\n" 2007228060Sbapt " && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \\\n" 2008228060Sbapt " && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \\\n" 2009228060Sbapt " && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \\\n" 2010228060Sbapt " && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \\\n" 2011228060Sbapt " && ('Z' == 90) && ('[' == 91) && ('\\\\' == 92) && (']' == 93) \\\n" 2012228060Sbapt " && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \\\n" 2013228060Sbapt " && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \\\n" 2014228060Sbapt " && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \\\n" 2015228060Sbapt " && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \\\n" 2016228060Sbapt " && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \\\n" 2017228060Sbapt " && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \\\n" 2018228060Sbapt " && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \\\n" 2019228060Sbapt " && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))\n" 2020228060Sbapt "/* The character set is not based on ISO-646. */\n"); 2021228060Sbapt 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"); 2022228060Sbapt printf ("#endif\n\n"); 2023228060Sbapt } 2024228060Sbapt 2025228060Sbapt if (_verbatim_declarations < _verbatim_declarations_end) 2026228060Sbapt { 2027228060Sbapt output_line_directive (_verbatim_declarations_lineno); 2028228060Sbapt fwrite (_verbatim_declarations, 1, 2029228060Sbapt _verbatim_declarations_end - _verbatim_declarations, stdout); 2030228060Sbapt } 2031228060Sbapt 2032228060Sbapt if (option[TYPE] && !option[NOTYPE]) /* Output type declaration now, reference it later on.... */ 2033228060Sbapt { 2034228060Sbapt output_line_directive (_struct_decl_lineno); 2035228060Sbapt printf ("%s\n", _struct_decl); 2036228060Sbapt } 2037228060Sbapt 2038228060Sbapt if (option[INCLUDE]) 2039228060Sbapt printf ("#include <string.h>\n"); /* Declare strlen(), strcmp(), strncmp(). */ 2040228060Sbapt 2041228060Sbapt if (!option[ENUM]) 2042228060Sbapt { 2043228060Sbapt Output_Defines style; 2044228060Sbapt output_constants (style); 2045228060Sbapt } 2046228060Sbapt else if (option[GLOBAL]) 2047228060Sbapt { 2048228060Sbapt Output_Enum style (""); 2049228060Sbapt output_constants (style); 2050228060Sbapt } 2051228060Sbapt 2052228060Sbapt printf ("/* maximum key range = %d, duplicates = %d */\n\n", 2053228060Sbapt _max_hash_value - _min_hash_value + 1, _total_duplicates); 2054228060Sbapt 2055228060Sbapt if (option[UPPERLOWER]) 2056228060Sbapt { 2057228060Sbapt #if USE_DOWNCASE_TABLE 2058228060Sbapt output_upperlower_table (); 2059228060Sbapt #endif 2060228060Sbapt 2061228060Sbapt if (option[LENTABLE]) 2062228060Sbapt output_upperlower_memcmp (); 2063228060Sbapt else 2064228060Sbapt { 2065228060Sbapt if (option[COMP]) 2066228060Sbapt output_upperlower_strncmp (); 2067228060Sbapt else 2068228060Sbapt output_upperlower_strcmp (); 2069228060Sbapt } 2070228060Sbapt } 2071228060Sbapt 2072228060Sbapt if (option[CPLUSPLUS]) 2073228060Sbapt printf ("class %s\n" 2074228060Sbapt "{\n" 2075228060Sbapt "private:\n" 2076228060Sbapt " static inline unsigned int %s (const char *str, unsigned int len);\n" 2077228060Sbapt "public:\n" 2078228060Sbapt " static %s%s%s (const char *str, unsigned int len);\n" 2079228060Sbapt "};\n" 2080228060Sbapt "\n", 2081228060Sbapt option.get_class_name (), option.get_hash_name (), 2082228060Sbapt const_for_struct, _return_type, option.get_function_name ()); 2083228060Sbapt 2084228060Sbapt output_hash_function (); 2085228060Sbapt 2086228060Sbapt if (option[SHAREDLIB] && (option[GLOBAL] || option[TYPE])) 2087228060Sbapt output_lookup_pools (); 2088228060Sbapt if (option[GLOBAL]) 2089228060Sbapt output_lookup_tables (); 2090228060Sbapt 2091228060Sbapt output_lookup_function (); 2092228060Sbapt 2093228060Sbapt if (_verbatim_code < _verbatim_code_end) 2094228060Sbapt { 2095228060Sbapt output_line_directive (_verbatim_code_lineno); 2096228060Sbapt fwrite (_verbatim_code, 1, _verbatim_code_end - _verbatim_code, stdout); 2097228060Sbapt } 2098228060Sbapt 2099228060Sbapt fflush (stdout); 2100228060Sbapt} 2101