1/* Driver program for the hash function generator
2   Copyright (C) 1989-1998, 2000, 2002-2003 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#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include "options.h"
27#include "input.h"
28#include "search.h"
29#include "output.h"
30
31
32/* ------------------------------------------------------------------------- */
33
34/* This Keyword factory produces KeywordExt instances.  */
35
36class KeywordExt_Factory : public Keyword_Factory
37{
38virtual Keyword *       create_keyword (const char *allchars, int allchars_length,
39                                        const char *rest);
40};
41
42Keyword *
43KeywordExt_Factory::create_keyword (const char *allchars, int allchars_length, const char *rest)
44{
45  return new KeywordExt (allchars, allchars_length, rest);
46}
47
48/* ------------------------------------------------------------------------- */
49
50int
51main (int argc, char *argv[])
52{
53  int exitcode;
54
55  /* Set the Options.  Open the input file and assign stdin to it.  */
56  option.parse_options (argc, argv);
57
58  /* Open the input file.  */
59  if (option.get_input_file_name ())
60    if (!freopen (option.get_input_file_name (), "r", stdin))
61      {
62        fprintf (stderr, "Cannot open input file '%s'\n",
63                 option.get_input_file_name ());
64        exit (1);
65      }
66
67  {
68    /* Initialize the keyword list.  */
69    KeywordExt_Factory factory;
70    Input inputter (stdin, &factory);
71    inputter.read_input ();
72    /* We can cast the keyword list to KeywordExt_List* because its list
73       elements were created by KeywordExt_Factory.  */
74    KeywordExt_List* list = static_cast<KeywordExt_List*>(inputter._head);
75
76    {
77      /* Search for a good hash function.  */
78      Search searcher (list);
79      searcher.optimize ();
80      list = searcher._head;
81
82      /* Open the output file.  */
83      if (option.get_output_file_name ())
84        if (strcmp (option.get_output_file_name (), "-") != 0)
85          if (!freopen (option.get_output_file_name (), "w", stdout))
86            {
87              fprintf (stderr, "Cannot open output file '%s'\n",
88                       option.get_output_file_name ());
89              exit (1);
90            }
91
92      {
93        /* Output the hash function code.  */
94        Output outputter (searcher._head,
95                          inputter._struct_decl,
96                          inputter._struct_decl_lineno,
97                          inputter._return_type,
98                          inputter._struct_tag,
99                          inputter._verbatim_declarations,
100                          inputter._verbatim_declarations_end,
101                          inputter._verbatim_declarations_lineno,
102                          inputter._verbatim_code,
103                          inputter._verbatim_code_end,
104                          inputter._verbatim_code_lineno,
105                          inputter._charset_dependent,
106                          searcher._total_keys,
107                          searcher._max_key_len,
108                          searcher._min_key_len,
109                          searcher._key_positions,
110                          searcher._alpha_inc,
111                          searcher._total_duplicates,
112                          searcher._alpha_size,
113                          searcher._asso_values);
114        outputter.output ();
115
116        /* Check for write error on stdout.  */
117        exitcode = 0;
118        if (fflush (stdout) || ferror (stdout))
119          {
120            fprintf (stderr, "error while writing output file\n");
121            exitcode = 1;
122          }
123
124        /* Here we run the Output destructor.  */
125      }
126      /* Here we run the Search destructor.  */
127    }
128
129    /* Also delete the list that was allocated inside Input and reordered
130       inside Search.  */
131    for (KeywordExt_List *ptr = list; ptr; ptr = ptr->rest())
132      {
133        KeywordExt *keyword = ptr->first();
134        do
135          {
136            KeywordExt *next_keyword = keyword->_duplicate_link;
137            delete[] const_cast<unsigned int *>(keyword->_selchars);
138            if (keyword->_rest != empty_string)
139              delete[] const_cast<char*>(keyword->_rest);
140            if (!(keyword->_allchars >= inputter._input
141                  && keyword->_allchars < inputter._input_end))
142              delete[] const_cast<char*>(keyword->_allchars);
143            delete keyword;
144            keyword = next_keyword;
145          }
146        while (keyword != NULL);
147      }
148    delete_list (list);
149
150    /* Here we run the Input destructor.  */
151  }
152
153  /* Don't use exit() here, it skips the destructors.  */
154  return exitcode;
155}
156