1230237Sbapt/* Driver program for the hash function generator
2230237Sbapt   Copyright (C) 1989-1998, 2000, 2002-2003 Free Software Foundation, Inc.
3230237Sbapt   Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
4230237Sbapt   and Bruno Haible <bruno@clisp.org>.
558551Skris
6230237Sbapt   This file is part of GNU GPERF.
758551Skris
8230237Sbapt   GNU GPERF is free software; you can redistribute it and/or modify
9230237Sbapt   it under the terms of the GNU General Public License as published by
10230237Sbapt   the Free Software Foundation; either version 2, or (at your option)
11230237Sbapt   any later version.
1258551Skris
13230237Sbapt   GNU GPERF is distributed in the hope that it will be useful,
14230237Sbapt   but WITHOUT ANY WARRANTY; without even the implied warranty of
15230237Sbapt   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16230237Sbapt   GNU General Public License for more details.
1758551Skris
18230237Sbapt   You should have received a copy of the GNU General Public License
19230237Sbapt   along with this program; see the file COPYING.
20230237Sbapt   If not, write to the Free Software Foundation, Inc.,
21230237Sbapt   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
2258551Skris
2358551Skris#include <stdio.h>
24230237Sbapt#include <stdlib.h>
25230237Sbapt#include <string.h>
2658551Skris#include "options.h"
27230237Sbapt#include "input.h"
28230237Sbapt#include "search.h"
29230237Sbapt#include "output.h"
3058551Skris
31230237Sbapt
32230237Sbapt/* ------------------------------------------------------------------------- */
33230237Sbapt
34230237Sbapt/* This Keyword factory produces KeywordExt instances.  */
35230237Sbapt
36230237Sbaptclass KeywordExt_Factory : public Keyword_Factory
37230237Sbapt{
38230237Sbaptvirtual Keyword *       create_keyword (const char *allchars, int allchars_length,
39230237Sbapt                                        const char *rest);
40230237Sbapt};
41230237Sbapt
42230237SbaptKeyword *
43230237SbaptKeywordExt_Factory::create_keyword (const char *allchars, int allchars_length, const char *rest)
44230237Sbapt{
45230237Sbapt  return new KeywordExt (allchars, allchars_length, rest);
46230237Sbapt}
47230237Sbapt
48230237Sbapt/* ------------------------------------------------------------------------- */
49230237Sbapt
5058551Skrisint
5158551Skrismain (int argc, char *argv[])
5258551Skris{
53230237Sbapt  int exitcode;
5458551Skris
55230237Sbapt  /* Set the Options.  Open the input file and assign stdin to it.  */
56230237Sbapt  option.parse_options (argc, argv);
57230237Sbapt
58230237Sbapt  /* Open the input file.  */
59230237Sbapt  if (option.get_input_file_name ())
60230237Sbapt    if (!freopen (option.get_input_file_name (), "r", stdin))
61230237Sbapt      {
62230237Sbapt        fprintf (stderr, "Cannot open input file '%s'\n",
63230237Sbapt                 option.get_input_file_name ());
64230237Sbapt        exit (1);
65230237Sbapt      }
66230237Sbapt
6758551Skris  {
68230237Sbapt    /* Initialize the keyword list.  */
69230237Sbapt    KeywordExt_Factory factory;
70230237Sbapt    Input inputter (stdin, &factory);
71230237Sbapt    inputter.read_input ();
72230237Sbapt    /* We can cast the keyword list to KeywordExt_List* because its list
73230237Sbapt       elements were created by KeywordExt_Factory.  */
74230237Sbapt    KeywordExt_List* list = static_cast<KeywordExt_List*>(inputter._head);
7558551Skris
76230237Sbapt    {
77230237Sbapt      /* Search for a good hash function.  */
78230237Sbapt      Search searcher (list);
79230237Sbapt      searcher.optimize ();
80230237Sbapt      list = searcher._head;
8158551Skris
82230237Sbapt      /* Open the output file.  */
83230237Sbapt      if (option.get_output_file_name ())
84230237Sbapt        if (strcmp (option.get_output_file_name (), "-") != 0)
85230237Sbapt          if (!freopen (option.get_output_file_name (), "w", stdout))
86230237Sbapt            {
87230237Sbapt              fprintf (stderr, "Cannot open output file '%s'\n",
88230237Sbapt                       option.get_output_file_name ());
89230237Sbapt              exit (1);
90230237Sbapt            }
9158551Skris
92230237Sbapt      {
93230237Sbapt        /* Output the hash function code.  */
94230237Sbapt        Output outputter (searcher._head,
95230237Sbapt                          inputter._struct_decl,
96230237Sbapt                          inputter._struct_decl_lineno,
97230237Sbapt                          inputter._return_type,
98230237Sbapt                          inputter._struct_tag,
99230237Sbapt                          inputter._verbatim_declarations,
100230237Sbapt                          inputter._verbatim_declarations_end,
101230237Sbapt                          inputter._verbatim_declarations_lineno,
102230237Sbapt                          inputter._verbatim_code,
103230237Sbapt                          inputter._verbatim_code_end,
104230237Sbapt                          inputter._verbatim_code_lineno,
105230237Sbapt                          inputter._charset_dependent,
106230237Sbapt                          searcher._total_keys,
107230237Sbapt                          searcher._max_key_len,
108230237Sbapt                          searcher._min_key_len,
109230237Sbapt                          searcher._key_positions,
110230237Sbapt                          searcher._alpha_inc,
111230237Sbapt                          searcher._total_duplicates,
112230237Sbapt                          searcher._alpha_size,
113230237Sbapt                          searcher._asso_values);
114230237Sbapt        outputter.output ();
11558551Skris
116230237Sbapt        /* Check for write error on stdout.  */
117230237Sbapt        exitcode = 0;
118230237Sbapt        if (fflush (stdout) || ferror (stdout))
119230237Sbapt          {
120230237Sbapt            fprintf (stderr, "error while writing output file\n");
121230237Sbapt            exitcode = 1;
122230237Sbapt          }
12367064Sobrien
124230237Sbapt        /* Here we run the Output destructor.  */
125230237Sbapt      }
126230237Sbapt      /* Here we run the Search destructor.  */
127230237Sbapt    }
128230237Sbapt
129230237Sbapt    /* Also delete the list that was allocated inside Input and reordered
130230237Sbapt       inside Search.  */
131230237Sbapt    for (KeywordExt_List *ptr = list; ptr; ptr = ptr->rest())
132230237Sbapt      {
133230237Sbapt        KeywordExt *keyword = ptr->first();
134230237Sbapt        do
135230237Sbapt          {
136230237Sbapt            KeywordExt *next_keyword = keyword->_duplicate_link;
137230237Sbapt            delete[] const_cast<unsigned int *>(keyword->_selchars);
138230237Sbapt            if (keyword->_rest != empty_string)
139230237Sbapt              delete[] const_cast<char*>(keyword->_rest);
140230237Sbapt            if (!(keyword->_allchars >= inputter._input
141230237Sbapt                  && keyword->_allchars < inputter._input_end))
142230237Sbapt              delete[] const_cast<char*>(keyword->_allchars);
143230237Sbapt            delete keyword;
144230237Sbapt            keyword = next_keyword;
145230237Sbapt          }
146230237Sbapt        while (keyword != NULL);
147230237Sbapt      }
148230237Sbapt    delete_list (list);
149230237Sbapt
150230237Sbapt    /* Here we run the Input destructor.  */
151230237Sbapt  }
152230237Sbapt
153230237Sbapt  /* Don't use exit() here, it skips the destructors.  */
154230237Sbapt  return exitcode;
15558551Skris}
156