summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2002-11-15 13:01:01 +0000
committerBruno Haible <bruno@clisp.org>2002-11-15 13:01:01 +0000
commitef7645289da8eea8a1e54383761fb5dc0cf043c8 (patch)
tree8481caa7dff23ca0dd2e7b5f691d1aff3816ca89
parent276e2fd9491c3b7b1793fd3d9f7147036824ae4c (diff)
downloadgperf-ef7645289da8eea8a1e54383761fb5dc0cf043c8.tar.gz
Move the input routines to class Input.
-rw-r--r--ChangeLog18
-rw-r--r--src/Makefile.in4
-rw-r--r--src/gen-perf.cc2
-rw-r--r--src/input.cc347
-rw-r--r--src/input.h52
-rw-r--r--src/key-list.cc463
-rw-r--r--src/key-list.h9
7 files changed, 499 insertions, 396 deletions
diff --git a/ChangeLog b/ChangeLog
index 138c94a..ceb59d9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2002-10-15 Bruno Haible <bruno@clisp.org>
+
+ * src/input.h: New file.
+ * src/input.cc: New file, extracted from key-list.cc.
+ * src/key-list.h (Key_List): Don't inherit from Read_Line.
+ (Key_List::get_special_input,
+ Key_List::save_include_src, Key_List::get_array_type,
+ Key_List::strcspn, Key_List::set_output_types): Remove methods.
+ * src/key-list.cc (Key_List::get_special_input,
+ Key_List::save_include_src, Key_List::get_array_type,
+ Key_List::strcspn, Key_List::set_output_types, parse_line): Move to
+ src/input.cc.
+ (Key_List::read_keys): Use Input::read_keys.
+ (Key_List::Key_List): Update.
+ * src/gen-perf.cc: Update.
+ * src/Makefile.in (OBJECTS): Add input.o.
+ (input.o): New rule.
+
2002-10-14 Bruno Haible <bruno@clisp.org>
* src/options.cc: Don't include "vector.h".
diff --git a/src/Makefile.in b/src/Makefile.in
index 7096761..36c4dac 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -61,7 +61,7 @@ VPATH = $(srcdir)
OBJECTS = options.o main.o gen-perf.o key-list.o \
hash-table.o bool-array.o read-line.o vectors.o version.o \
- keyword.o keyword-list.o output.o
+ keyword.o keyword-list.o output.o input.o
LIBS = ../lib/libgp.a @GPERF_LIBM@
CPPFLAGS = -I. -I$(srcdir)/../lib
@@ -116,6 +116,8 @@ keyword-list.o : keyword-list.cc keyword-list.h
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/keyword-list.cc
output.o : output.cc output.h
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/output.cc
+input.o : input.cc input.h
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/input.cc
install : all force
$(MKINSTALLDIRS) $(DESTDIR)$(bindir)
diff --git a/src/gen-perf.cc b/src/gen-perf.cc
index c054f1d..a90994d 100644
--- a/src/gen-perf.cc
+++ b/src/gen-perf.cc
@@ -41,7 +41,7 @@ Gen_Perf::Gen_Perf ()
int non_linked_length;
Vectors::ALPHA_SIZE = (option[SEVENBIT] ? 128 : 256);
- Key_List::read_keys ();
+ read_keys ();
if (option[ORDER])
reorder ();
_num_done = 1;
diff --git a/src/input.cc b/src/input.cc
new file mode 100644
index 0000000..1d18210
--- /dev/null
+++ b/src/input.cc
@@ -0,0 +1,347 @@
+/* Input routines.
+ Copyright (C) 1989-1998, 2002 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include <stdio.h>
+#include <stdlib.h> /* declares exit() */
+#include <string.h> /* declares strncpy(), strchr() */
+#include <limits.h> /* defines UCHAR_MAX etc. */
+#include "options.h"
+#include "input.h"
+
+/* Gathers the input stream into a buffer until one of two things occur:
+
+ 1. We read a '%' followed by a '%'
+ 2. We read a '%' followed by a '}'
+
+ The first symbolizes the beginning of the keyword list proper,
+ The second symbolizes the end of the C source code to be generated
+ verbatim in the output file.
+
+ I assume that the keys are separated from the optional preceding struct
+ declaration by a consecutive % followed by either % or } starting in
+ the first column. The code below uses an expandible buffer to scan off
+ and return a pointer to all the code (if any) appearing before the delimiter. */
+
+const char *
+Input::get_special_input (char delimiter)
+{
+ int size = 80;
+ char *buf = new char[size];
+ int c, i;
+
+ for (i = 0; (c = getchar ()) != EOF; i++)
+ {
+ if (c == '%')
+ {
+ if ((c = getchar ()) == delimiter)
+ {
+
+ while ((c = getchar ()) != '\n')
+ ; /* discard newline */
+
+ if (i == 0)
+ return "";
+ else
+ {
+ buf[delimiter == '%' && buf[i - 2] == ';' ? i - 2 : i - 1] = '\0';
+ return buf;
+ }
+ }
+ else
+ buf[i++] = '%';
+ }
+ else if (i >= size) /* Yikes, time to grow the buffer! */
+ {
+ char *temp = new char[size *= 2];
+ int j;
+
+ for (j = 0; j < i; j++)
+ temp[j] = buf[j];
+
+ buf = temp;
+ }
+ buf[i] = c;
+ }
+
+ return 0; /* Problem here. */
+}
+
+/* Stores any C text that must be included verbatim into the
+ generated code output. */
+
+const char *
+Input::save_include_src ()
+{
+ int c;
+
+ if ((c = getchar ()) != '%')
+ ungetc (c, stdin);
+ else if ((c = getchar ()) != '{')
+ {
+ fprintf (stderr, "internal error, %c != '{' on line %d in file %s", c, __LINE__, __FILE__);
+ exit (1);
+ }
+ else
+ return get_special_input ('}');
+ return "";
+}
+
+/* Determines from the input file whether the user wants to build a table
+ from a user-defined struct, or whether the user is content to simply
+ use the default array of keys. */
+
+const char *
+Input::get_array_type ()
+{
+ return get_special_input ('%');
+}
+
+/* strcspn - find length of initial segment of S consisting entirely
+ of characters not from REJECT (borrowed from Henry Spencer's
+ ANSI string package, when GNU libc comes out I'll replace this...). */
+
+#ifndef strcspn
+inline int
+Input::strcspn (const char *s, const char *reject)
+{
+ const char *scan;
+ const char *rej_scan;
+ int count = 0;
+
+ for (scan = s; *scan; scan++)
+ {
+
+ for (rej_scan = reject; *rej_scan; rej_scan++)
+ if (*scan == *rej_scan)
+ return count;
+
+ count++;
+ }
+
+ return count;
+}
+#endif
+
+/* Sets up the Return_Type, the Struct_Tag type and the Array_Type
+ based upon various user Options. */
+
+void
+Input::set_output_types ()
+{
+ if (option[TYPE])
+ {
+ _array_type = get_array_type ();
+ if (!_array_type)
+ /* Something's wrong, but we'll catch it later on, in read_keys()... */
+ return;
+ /* Yow, we've got a user-defined type... */
+ int i = strcspn (_array_type, "{\n\0");
+ /* Remove trailing whitespace. */
+ while (i > 0 && strchr (" \t", _array_type[i-1]))
+ i--;
+ int struct_tag_length = i;
+
+ /* Set `struct_tag' to a naked "struct something". */
+ char *structtag = new char[struct_tag_length + 1];
+ strncpy (structtag, _array_type, struct_tag_length);
+ structtag[struct_tag_length] = '\0';
+ _struct_tag = structtag;
+
+ /* The return type of the lookup function is "struct something *".
+ No "const" here, because if !option[CONST], some user code might want
+ to modify the structure. */
+ char *rettype = new char[struct_tag_length + 3];
+ strncpy (rettype, _array_type, struct_tag_length);
+ rettype[struct_tag_length] = ' ';
+ rettype[struct_tag_length + 1] = '*';
+ rettype[struct_tag_length + 2] = '\0';
+ _return_type = rettype;
+ }
+}
+
+/* Extracts a key from an input line and creates a new KeywordExt_List for
+ it. */
+
+static KeywordExt_List *
+parse_line (const char *line, const char *delimiters)
+{
+ if (*line == '"')
+ {
+ /* Parse a string in ANSI C syntax. */
+ char *key = new char[strlen(line)];
+ char *kp = key;
+ const char *lp = line + 1;
+
+ for (; *lp;)
+ {
+ char c = *lp;
+
+ if (c == '\0')
+ {
+ fprintf (stderr, "unterminated string: %s\n", line);
+ exit (1);
+ }
+ else if (c == '\\')
+ {
+ c = *++lp;
+ switch (c)
+ {
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ {
+ int code = 0;
+ int count = 0;
+ while (count < 3 && *lp >= '0' && *lp <= '7')
+ {
+ code = (code << 3) + (*lp - '0');
+ lp++;
+ count++;
+ }
+ if (code > UCHAR_MAX)
+ fprintf (stderr, "octal escape out of range: %s\n", line);
+ *kp = (char) code;
+ break;
+ }
+ case 'x':
+ {
+ int code = 0;
+ int count = 0;
+ lp++;
+ while ((*lp >= '0' && *lp <= '9')
+ || (*lp >= 'A' && *lp <= 'F')
+ || (*lp >= 'a' && *lp <= 'f'))
+ {
+ code = (code << 4)
+ + (*lp >= 'A' && *lp <= 'F' ? *lp - 'A' + 10 :
+ *lp >= 'a' && *lp <= 'f' ? *lp - 'a' + 10 :
+ *lp - '0');
+ lp++;
+ count++;
+ }
+ if (count == 0)
+ fprintf (stderr, "hexadecimal escape without any hex digits: %s\n", line);
+ if (code > UCHAR_MAX)
+ fprintf (stderr, "hexadecimal escape out of range: %s\n", line);
+ *kp = (char) code;
+ break;
+ }
+ case '\\': case '\'': case '"':
+ *kp = c;
+ lp++;
+ break;
+ case 'n':
+ *kp = '\n';
+ lp++;
+ break;
+ case 't':
+ *kp = '\t';
+ lp++;
+ break;
+ case 'r':
+ *kp = '\r';
+ lp++;
+ break;
+ case 'f':
+ *kp = '\f';
+ lp++;
+ break;
+ case 'b':
+ *kp = '\b';
+ lp++;
+ break;
+ case 'a':
+ *kp = '\a';
+ lp++;
+ break;
+ case 'v':
+ *kp = '\v';
+ lp++;
+ break;
+ default:
+ fprintf (stderr, "invalid escape sequence in string: %s\n", line);
+ exit (1);
+ }
+ }
+ else if (c == '"')
+ break;
+ else
+ {
+ *kp = c;
+ lp++;
+ }
+ kp++;
+ }
+ lp++;
+ if (*lp != '\0')
+ {
+ if (strchr (delimiters, *lp) == NULL)
+ {
+ fprintf (stderr, "string not followed by delimiter: %s\n", line);
+ exit (1);
+ }
+ lp++;
+ }
+ return new KeywordExt_List (key, kp - key, option[TYPE] ? lp : "");
+ }
+ else
+ {
+ /* Not a string. Look for the delimiter. */
+ int len = strcspn (line, delimiters);
+ const char *rest;
+
+ if (line[len] == '\0')
+ rest = "";
+ else
+ /* Skip the first delimiter. */
+ rest = &line[len + 1];
+ return new KeywordExt_List (line, len, option[TYPE] ? rest : "");
+ }
+}
+
+void
+Input::read_keys ()
+{
+ char *ptr;
+
+ _include_src = save_include_src ();
+ set_output_types ();
+
+ /* Oops, problem with the input file. */
+ if (! (ptr = Read_Line::read_next_line ()))
+ {
+ fprintf (stderr, "No words in input file, did you forget to prepend %s or use -t accidentally?\n", "%%");
+ exit (1);
+ }
+
+ /* Read in all the keywords from the input file. */
+ const char *delimiter = option.get_delimiter ();
+
+ _head = parse_line (ptr, delimiter);
+
+ for (KeywordExt_List *temp = _head;
+ (ptr = Read_Line::read_next_line ()) && strcmp (ptr, "%%");
+ temp = temp->rest())
+ temp->rest() = parse_line (ptr, delimiter);
+
+ /* See if any additional C code is included at end of this file. */
+ if (ptr)
+ _additional_code = 1;
+}
diff --git a/src/input.h b/src/input.h
new file mode 100644
index 0000000..d602891
--- /dev/null
+++ b/src/input.h
@@ -0,0 +1,52 @@
+/* This may look like C code, but it is really -*- C++ -*- */
+
+/* Input routines.
+
+ Copyright (C) 1989-1998, 2002 Free Software Foundation, Inc.
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
+ and Bruno Haible <bruno@clisp.org>.
+
+This file is part of GNU GPERF.
+
+GNU GPERF is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU GPERF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU GPERF; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#ifndef input_h
+#define input_h 1
+
+#include "read-line.h"
+#include "keyword-list.h"
+
+class Input : private Read_Line
+{
+public:
+ void read_keys ();
+private:
+#ifndef strcspn
+ static int strcspn (const char *s, const char *reject);
+#endif
+ void set_output_types ();
+ const char *get_array_type ();
+ const char *save_include_src ();
+ const char *get_special_input (char delimiter);
+public:
+ const char *_array_type; /* Pointer to the type for word list. */
+ const char *_return_type; /* Pointer to return type for lookup function. */
+ const char *_struct_tag; /* Shorthand for user-defined struct tag type. */
+ const char *_include_src; /* C source code to be included verbatim. */
+ int _additional_code; /* True if any additional C code is included. */
+ KeywordExt_List *_head; /* Points to the head of the linked list. */
+};
+
+#endif
diff --git a/src/key-list.cc b/src/key-list.cc
index abcd4cd..81db2ac 100644
--- a/src/key-list.cc
+++ b/src/key-list.cc
@@ -19,13 +19,12 @@ along with GNU GPERF; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
#include <stdio.h>
-#include <string.h> /* declares strncpy(), strchr() */
-#include <stdlib.h> /* declares malloc(), free(), abs(), exit(), abort() */
-#include <limits.h> /* defines UCHAR_MAX etc. */
+#include <stdlib.h> /* declares exit() */
+#include <limits.h> /* defines INT_MIN, INT_MAX */
#include "options.h"
-#include "read-line.h"
-#include "hash-table.h"
#include "key-list.h"
+#include "input.h"
+#include "hash-table.h"
/* Make the hash table 8 times larger than the number of keyword entries. */
static const int TABLE_MULTIPLE = 10;
@@ -49,407 +48,99 @@ Key_List::~Key_List ()
}
}
-/* Gathers the input stream into a buffer until one of two things occur:
-
- 1. We read a '%' followed by a '%'
- 2. We read a '%' followed by a '}'
-
- The first symbolizes the beginning of the keyword list proper,
- The second symbolizes the end of the C source code to be generated
- verbatim in the output file.
-
- I assume that the keys are separated from the optional preceding struct
- declaration by a consecutive % followed by either % or } starting in
- the first column. The code below uses an expandible buffer to scan off
- and return a pointer to all the code (if any) appearing before the delimiter. */
-
-const char *
-Key_List::get_special_input (char delimiter)
-{
- int size = 80;
- char *buf = new char[size];
- int c, i;
-
- for (i = 0; (c = getchar ()) != EOF; i++)
- {
- if (c == '%')
- {
- if ((c = getchar ()) == delimiter)
- {
-
- while ((c = getchar ()) != '\n')
- ; /* discard newline */
-
- if (i == 0)
- return "";
- else
- {
- buf[delimiter == '%' && buf[i - 2] == ';' ? i - 2 : i - 1] = '\0';
- return buf;
- }
- }
- else
- buf[i++] = '%';
- }
- else if (i >= size) /* Yikes, time to grow the buffer! */
- {
- char *temp = new char[size *= 2];
- int j;
-
- for (j = 0; j < i; j++)
- temp[j] = buf[j];
-
- buf = temp;
- }
- buf[i] = c;
- }
-
- return 0; /* Problem here. */
-}
-
-/* Stores any C text that must be included verbatim into the
- generated code output. */
-
-const char *
-Key_List::save_include_src ()
-{
- int c;
-
- if ((c = getchar ()) != '%')
- ungetc (c, stdin);
- else if ((c = getchar ()) != '{')
- {
- fprintf (stderr, "internal error, %c != '{' on line %d in file %s", c, __LINE__, __FILE__);
- exit (1);
- }
- else
- return get_special_input ('}');
- return "";
-}
-
-/* Determines from the input file whether the user wants to build a table
- from a user-defined struct, or whether the user is content to simply
- use the default array of keys. */
-
-const char *
-Key_List::get_array_type ()
-{
- return get_special_input ('%');
-}
-
-/* strcspn - find length of initial segment of S consisting entirely
- of characters not from REJECT (borrowed from Henry Spencer's
- ANSI string package, when GNU libc comes out I'll replace this...). */
-
-#ifndef strcspn
-inline int
-Key_List::strcspn (const char *s, const char *reject)
-{
- const char *scan;
- const char *rej_scan;
- int count = 0;
-
- for (scan = s; *scan; scan++)
- {
-
- for (rej_scan = reject; *rej_scan; rej_scan++)
- if (*scan == *rej_scan)
- return count;
-
- count++;
- }
-
- return count;
-}
-#endif
-
-/* Sets up the Return_Type, the Struct_Tag type and the Array_Type
- based upon various user Options. */
-
-void
-Key_List::set_output_types ()
-{
- if (option[TYPE])
- {
- _array_type = get_array_type ();
- if (!_array_type)
- /* Something's wrong, but we'll catch it later on, in read_keys()... */
- return;
- /* Yow, we've got a user-defined type... */
- int i = strcspn (_array_type, "{\n\0");
- /* Remove trailing whitespace. */
- while (i > 0 && strchr (" \t", _array_type[i-1]))
- i--;
- int struct_tag_length = i;
-
- /* Set `struct_tag' to a naked "struct something". */
- char *structtag = new char[struct_tag_length + 1];
- strncpy (structtag, _array_type, struct_tag_length);
- structtag[struct_tag_length] = '\0';
- _struct_tag = structtag;
-
- /* The return type of the lookup function is "struct something *".
- No "const" here, because if !option[CONST], some user code might want
- to modify the structure. */
- char *rettype = new char[struct_tag_length + 3];
- strncpy (rettype, _array_type, struct_tag_length);
- rettype[struct_tag_length] = ' ';
- rettype[struct_tag_length + 1] = '*';
- rettype[struct_tag_length + 2] = '\0';
- _return_type = rettype;
- }
-}
-
-/* Extracts a key from an input line and creates a new KeywordExt_List for
- it. */
-
-static KeywordExt_List *
-parse_line (const char *line, const char *delimiters)
-{
- if (*line == '"')
- {
- /* Parse a string in ANSI C syntax. */
- char *key = new char[strlen(line)];
- char *kp = key;
- const char *lp = line + 1;
-
- for (; *lp;)
- {
- char c = *lp;
-
- if (c == '\0')
- {
- fprintf (stderr, "unterminated string: %s\n", line);
- exit (1);
- }
- else if (c == '\\')
- {
- c = *++lp;
- switch (c)
- {
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- {
- int code = 0;
- int count = 0;
- while (count < 3 && *lp >= '0' && *lp <= '7')
- {
- code = (code << 3) + (*lp - '0');
- lp++;
- count++;
- }
- if (code > UCHAR_MAX)
- fprintf (stderr, "octal escape out of range: %s\n", line);
- *kp = (char) code;
- break;
- }
- case 'x':
- {
- int code = 0;
- int count = 0;
- lp++;
- while ((*lp >= '0' && *lp <= '9')
- || (*lp >= 'A' && *lp <= 'F')
- || (*lp >= 'a' && *lp <= 'f'))
- {
- code = (code << 4)
- + (*lp >= 'A' && *lp <= 'F' ? *lp - 'A' + 10 :
- *lp >= 'a' && *lp <= 'f' ? *lp - 'a' + 10 :
- *lp - '0');
- lp++;
- count++;
- }
- if (count == 0)
- fprintf (stderr, "hexadecimal escape without any hex digits: %s\n", line);
- if (code > UCHAR_MAX)
- fprintf (stderr, "hexadecimal escape out of range: %s\n", line);
- *kp = (char) code;
- break;
- }
- case '\\': case '\'': case '"':
- *kp = c;
- lp++;
- break;
- case 'n':
- *kp = '\n';
- lp++;
- break;
- case 't':
- *kp = '\t';
- lp++;
- break;
- case 'r':
- *kp = '\r';
- lp++;
- break;
- case 'f':
- *kp = '\f';
- lp++;
- break;
- case 'b':
- *kp = '\b';
- lp++;
- break;
- case 'a':
- *kp = '\a';
- lp++;
- break;
- case 'v':
- *kp = '\v';
- lp++;
- break;
- default:
- fprintf (stderr, "invalid escape sequence in string: %s\n", line);
- exit (1);
- }
- }
- else if (c == '"')
- break;
- else
- {
- *kp = c;
- lp++;
- }
- kp++;
- }
- lp++;
- if (*lp != '\0')
- {
- if (strchr (delimiters, *lp) == NULL)
- {
- fprintf (stderr, "string not followed by delimiter: %s\n", line);
- exit (1);
- }
- lp++;
- }
- return new KeywordExt_List (key, kp - key, option[TYPE] ? lp : "");
- }
- else
- {
- /* Not a string. Look for the delimiter. */
- int len = strcspn (line, delimiters);
- const char *rest;
-
- if (line[len] == '\0')
- rest = "";
- else
- /* Skip the first delimiter. */
- rest = &line[len + 1];
- return new KeywordExt_List (line, len, option[TYPE] ? rest : "");
- }
-}
-
/* Reads in all keys from standard input and creates a linked list pointed
- to by Head. This list is then quickly checked for ``links,'' i.e.,
+ to by _head. This list is then quickly checked for "links", i.e.,
unhashable elements possessing identical key sets and lengths. */
void
Key_List::read_keys ()
{
- char *ptr;
-
- _include_src = save_include_src ();
- set_output_types ();
-
- /* Oops, problem with the input file. */
- if (! (ptr = Read_Line::read_next_line ()))
+ Input inputter;
+ inputter.read_keys ();
+ _array_type = inputter._array_type;
+ _return_type = inputter._return_type;
+ _struct_tag = inputter._struct_tag;
+ _include_src = inputter._include_src;
+ _additional_code = inputter._additional_code;
+ _head = inputter._head;
+
+ KeywordExt_List *temp;
+ KeywordExt_List *trail = NULL;
+
+ for (temp = _head; temp; temp = temp->rest())
{
- fprintf (stderr, "No words in input file, did you forget to prepend %s or use -t accidentally?\n", "%%");
- exit (1);
+ temp->first()->init_selchars(this);
+ _total_keys++;
}
+
+ /* Hash table this number of times larger than keyword number. */
+ int table_size = (_list_len = _total_keys) * TABLE_MULTIPLE;
+ /* Table must be a power of 2 for the hash function scheme to work. */
+ KeywordExt **table = new KeywordExt*[POW (table_size)];
- /* Read in all the keywords from the input file. */
- else
- {
- const char *delimiter = option.get_delimiter ();
- KeywordExt_List *temp;
- KeywordExt_List *trail = NULL;
-
- _head = parse_line (ptr, delimiter);
- _head->first()->init_selchars(this);
-
- for (temp = _head;
- (ptr = Read_Line::read_next_line ()) && strcmp (ptr, "%%");
- temp = temp->rest())
- {
- temp->rest() = parse_line (ptr, delimiter);
- temp->rest()->first()->init_selchars(this);
- _total_keys++;
- }
+ /* Make large hash table for efficiency. */
+ Hash_Table found_link (table, table_size, option[NOLENGTH]);
- /* See if any additional C code is included at end of this file. */
- if (ptr)
- _additional_code = 1;
+ /* Test whether there are any links and also set the maximum length of
+ an identifier in the keyword list. */
- /* Hash table this number of times larger than keyword number. */
- int table_size = (_list_len = _total_keys) * TABLE_MULTIPLE;
- /* Table must be a power of 2 for the hash function scheme to work. */
- KeywordExt **table = new KeywordExt*[POW (table_size)];
-
- /* Make large hash table for efficiency. */
- Hash_Table found_link (table, table_size, option[NOLENGTH]);
+ for (temp = _head; temp; temp = temp->rest())
+ {
+ KeywordExt *keyword = temp->first();
+ KeywordExt *other_keyword = found_link.insert (keyword);
- /* Test whether there are any links and also set the maximum length of
- an identifier in the keyword list. */
+ /* Check for links. We deal with these by building an equivalence class
+ of all duplicate values (i.e., links) so that only 1 keyword is
+ representative of the entire collection. This *greatly* simplifies
+ processing during later stages of the program. */
- for (temp = _head; temp; temp = temp->rest())
+ if (other_keyword)
{
- KeywordExt *keyword = temp->first();
- KeywordExt *other_keyword = found_link.insert (keyword);
-
- /* Check for links. We deal with these by building an equivalence class
- of all duplicate values (i.e., links) so that only 1 keyword is
- representative of the entire collection. This *greatly* simplifies
- processing during later stages of the program. */
-
- if (other_keyword)
- {
- _total_duplicates++;
- _list_len--;
- trail->rest() = temp->rest();
- temp->first()->_duplicate_link = other_keyword->_duplicate_link;
- other_keyword->_duplicate_link = temp->first();
-
- /* Complain if user hasn't enabled the duplicate option. */
- if (!option[DUP] || option[DEBUG])
- fprintf (stderr, "Key link: \"%.*s\" = \"%.*s\", with key set \"%.*s\".\n",
- keyword->_allchars_length, keyword->_allchars,
- other_keyword->_allchars_length, other_keyword->_allchars,
- keyword->_selchars_length, keyword->_selchars);
- }
- else
- trail = temp;
-
- /* Update minimum and maximum keyword length, if needed. */
- if (_max_key_len < keyword->_allchars_length)
- _max_key_len = keyword->_allchars_length;
- if (_min_key_len > keyword->_allchars_length)
- _min_key_len = keyword->_allchars_length;
+ _total_duplicates++;
+ _list_len--;
+ trail->rest() = temp->rest();
+ temp->first()->_duplicate_link = other_keyword->_duplicate_link;
+ other_keyword->_duplicate_link = temp->first();
+
+ /* Complain if user hasn't enabled the duplicate option. */
+ if (!option[DUP] || option[DEBUG])
+ fprintf (stderr, "Key link: \"%.*s\" = \"%.*s\", with key set \"%.*s\".\n",
+ keyword->_allchars_length, keyword->_allchars,
+ other_keyword->_allchars_length, other_keyword->_allchars,
+ keyword->_selchars_length, keyword->_selchars);
}
+ else
+ trail = temp;
- delete[] table;
+ /* Update minimum and maximum keyword length, if needed. */
+ if (_max_key_len < keyword->_allchars_length)
+ _max_key_len = keyword->_allchars_length;
+ if (_min_key_len > keyword->_allchars_length)
+ _min_key_len = keyword->_allchars_length;
+ }
- /* Exit program if links exists and option[DUP] not set, since we can't continue */
- if (_total_duplicates)
- {
- if (option[DUP])
- fprintf (stderr, "%d input keys have identical hash values, examine output carefully...\n",
- _total_duplicates);
- else
- {
- fprintf (stderr, "%d input keys have identical hash values,\ntry different key positions or use option -D.\n",
- _total_duplicates);
- exit (1);
- }
- }
- /* Exit program if an empty string is used as key, since the comparison
- expressions don't work correctly for looking up an empty string. */
- if (_min_key_len == 0)
+ delete[] table;
+
+ /* Exit program if links exists and option[DUP] not set, since we can't continue */
+ if (_total_duplicates)
+ {
+ if (option[DUP])
+ fprintf (stderr, "%d input keys have identical hash values, examine output carefully...\n",
+ _total_duplicates);
+ else
{
- fprintf (stderr, "Empty input key is not allowed.\nTo recognize an empty input key, your code should check for\nlen == 0 before calling the gperf generated lookup function.\n");
+ fprintf (stderr, "%d input keys have identical hash values,\ntry different key positions or use option -D.\n",
+ _total_duplicates);
exit (1);
}
}
+ /* Exit program if an empty string is used as key, since the comparison
+ expressions don't work correctly for looking up an empty string. */
+ if (_min_key_len == 0)
+ {
+ fprintf (stderr, "Empty input key is not allowed.\nTo recognize an empty input key, your code should check for\nlen == 0 before calling the gperf generated lookup function.\n");
+ exit (1);
+ }
}
/* Recursively merges two sorted lists together to form one sorted list. The
@@ -638,7 +329,7 @@ Key_List::dump ()
Key_List::Key_List ()
{
- _total_keys = 1;
+ _total_keys = 0;
_max_key_len = INT_MIN;
_min_key_len = INT_MAX;
_array_type = 0;
diff --git a/src/key-list.h b/src/key-list.h
index dbcd8b1..83da4e9 100644
--- a/src/key-list.h
+++ b/src/key-list.h
@@ -33,7 +33,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
#include "vectors.h"
#include "read-line.h"
-class Key_List : private Read_Line, public Vectors
+class Key_List : public Vectors
{
protected:
const char *_array_type; /* Pointer to the type for word list. */
@@ -55,16 +55,9 @@ protected:
private:
static int _determined[MAX_ALPHA_SIZE]; /* Used in function reorder, below. */
static int get_occurrence (KeywordExt *ptr);
-#ifndef strcspn
- static int strcspn (const char *s, const char *reject);
-#endif
static int already_determined (KeywordExt *ptr);
static void set_determined (KeywordExt *ptr);
- void set_output_types ();
void dump ();
- const char *get_array_type ();
- const char *save_include_src ();
- const char *get_special_input (char delimiter);
KeywordExt_List *merge (KeywordExt_List *list1, KeywordExt_List *list2);
KeywordExt_List *merge_sort (KeywordExt_List *head);