mirror of
https://git.savannah.gnu.org/git/gperf.git
synced 2025-12-02 21:19:24 +00:00
Replace class List_Node with class KeywordExt.
This commit is contained in:
17
ChangeLog
17
ChangeLog
@@ -1,5 +1,22 @@
|
|||||||
2002-10-03 Bruno Haible <bruno@clisp.org>
|
2002-10-03 Bruno Haible <bruno@clisp.org>
|
||||||
|
|
||||||
|
* src/keyword-list.h: New file.
|
||||||
|
* src/keyword-list.cc: New file.
|
||||||
|
* src/list-node.h: Remove file.
|
||||||
|
* src/list-node.cc: Remove file.
|
||||||
|
* src/keyword.h (KeywordExt::init_selchars): New declaration.
|
||||||
|
* src/keyword.cc (sort_char_set, KeywordExt::init_selchars): New, from
|
||||||
|
old list-node.cc.
|
||||||
|
* src/gen-perf.cc: Replace List_Node by KeywordExt or KeywordExt_List,
|
||||||
|
as appropriate.
|
||||||
|
* src/hash-table.h: Likewise.
|
||||||
|
* src/key-list.h: Likewise.
|
||||||
|
* src/key-list.cc: Likewise.
|
||||||
|
* src/Makefile.in (OBJECTS): Remove list-node.o, add keyword-list.o.
|
||||||
|
(LIST_NODE_H): Remove macro.
|
||||||
|
(list-node.o): Remove rule.
|
||||||
|
(keyword-list.o): New rule.
|
||||||
|
|
||||||
* src/keyword.h (KeywordExt): New class.
|
* src/keyword.h (KeywordExt): New class.
|
||||||
* src/keyword.cc (KeywordExt): New constructor.
|
* src/keyword.cc (KeywordExt): New constructor.
|
||||||
* src/list-node.h (List_Node): Inherit from KeywordExt.
|
* src/list-node.h (List_Node): Inherit from KeywordExt.
|
||||||
|
|||||||
@@ -59,9 +59,9 @@ SHELL = /bin/sh
|
|||||||
|
|
||||||
VPATH = $(srcdir)
|
VPATH = $(srcdir)
|
||||||
|
|
||||||
OBJECTS = options.o iterator.o main.o gen-perf.o key-list.o list-node.o \
|
OBJECTS = options.o iterator.o main.o gen-perf.o key-list.o \
|
||||||
hash-table.o bool-array.o read-line.o vectors.o version.o \
|
hash-table.o bool-array.o read-line.o vectors.o version.o \
|
||||||
keyword.o
|
keyword.o keyword-list.o
|
||||||
LIBS = ../lib/libgp.a @GPERF_LIBM@
|
LIBS = ../lib/libgp.a @GPERF_LIBM@
|
||||||
CPPFLAGS = -I. -I$(srcdir)/../lib
|
CPPFLAGS = -I. -I$(srcdir)/../lib
|
||||||
|
|
||||||
@@ -87,10 +87,9 @@ VERSION_H = version.h
|
|||||||
VECTORS_H = vectors.h
|
VECTORS_H = vectors.h
|
||||||
READ_LINE_H = read-line.h read-line.icc
|
READ_LINE_H = read-line.h read-line.icc
|
||||||
OPTIONS_H = options.h options.icc
|
OPTIONS_H = options.h options.icc
|
||||||
LIST_NODE_H = list-node.h $(VECTORS_H)
|
KEY_LIST_H = key-list.h $(VECTORS_H) $(READ_LINE_H)
|
||||||
KEY_LIST_H = key-list.h $(LIST_NODE_H) $(VECTORS_H) $(READ_LINE_H)
|
|
||||||
ITERATOR_H = iterator.h
|
ITERATOR_H = iterator.h
|
||||||
HASH_TABLE_H = hash-table.h $(LIST_NODE_H)
|
HASH_TABLE_H = hash-table.h
|
||||||
BOOL_ARRAY_H = bool-array.h bool-array.icc $(OPTIONS_H)
|
BOOL_ARRAY_H = bool-array.h bool-array.icc $(OPTIONS_H)
|
||||||
GEN_PERF_H = gen-perf.h $(KEY_LIST_H) $(BOOL_ARRAY_H)
|
GEN_PERF_H = gen-perf.h $(KEY_LIST_H) $(BOOL_ARRAY_H)
|
||||||
|
|
||||||
@@ -104,8 +103,6 @@ iterator.o : iterator.cc $(ITERATOR_H)
|
|||||||
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/iterator.cc
|
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/iterator.cc
|
||||||
key-list.o : key-list.cc $(KEY_LIST_H) $(OPTIONS_H) $(READ_LINE_H) $(HASH_TABLE_H) $(VERSION_H)
|
key-list.o : key-list.cc $(KEY_LIST_H) $(OPTIONS_H) $(READ_LINE_H) $(HASH_TABLE_H) $(VERSION_H)
|
||||||
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/key-list.cc
|
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/key-list.cc
|
||||||
list-node.o : list-node.cc $(LIST_NODE_H) $(OPTIONS_H)
|
|
||||||
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/list-node.cc
|
|
||||||
main.o : main.cc $(OPTIONS_H) $(GEN_PERF_H) $(CONFIG_H)
|
main.o : main.cc $(OPTIONS_H) $(GEN_PERF_H) $(CONFIG_H)
|
||||||
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/main.cc
|
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/main.cc
|
||||||
options.o : options.cc $(OPTIONS_H) $(ITERATOR_H) $(VECTORS_H) $(VERSION_H)
|
options.o : options.cc $(OPTIONS_H) $(ITERATOR_H) $(VECTORS_H) $(VERSION_H)
|
||||||
@@ -118,6 +115,8 @@ version.o : version.cc $(VERSION_H)
|
|||||||
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/version.cc
|
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/version.cc
|
||||||
keyword.o : keyword.cc keyword.h
|
keyword.o : keyword.cc keyword.h
|
||||||
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/keyword.cc
|
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/keyword.cc
|
||||||
|
keyword-list.o : keyword-list.cc keyword-list.h
|
||||||
|
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(srcdir)/keyword-list.cc
|
||||||
|
|
||||||
install : all force
|
install : all force
|
||||||
$(MKINSTALLDIRS) $(DESTDIR)$(bindir)
|
$(MKINSTALLDIRS) $(DESTDIR)$(bindir)
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ Gen_Perf::sort_set (char *union_set, int len)
|
|||||||
/* Generate a key set's hash value. */
|
/* Generate a key set's hash value. */
|
||||||
|
|
||||||
inline int
|
inline int
|
||||||
Gen_Perf::hash (List_Node *key_node)
|
Gen_Perf::hash (KeywordExt *key_node)
|
||||||
{
|
{
|
||||||
int sum = option[NOLENGTH] ? 0 : key_node->allchars_length;
|
int sum = option[NOLENGTH] ? 0 : key_node->allchars_length;
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ Gen_Perf::hash (List_Node *key_node)
|
|||||||
Option.Get_Jump was forced to be an odd value! */
|
Option.Get_Jump was forced to be an odd value! */
|
||||||
|
|
||||||
inline int
|
inline int
|
||||||
Gen_Perf::affects_prev (char c, List_Node *curr)
|
Gen_Perf::affects_prev (char c, KeywordExt *curr)
|
||||||
{
|
{
|
||||||
int original_char = asso_values[(unsigned char)c];
|
int original_char = asso_values[(unsigned char)c];
|
||||||
int total_iterations = !option[FAST]
|
int total_iterations = !option[FAST]
|
||||||
@@ -189,10 +189,13 @@ Gen_Perf::affects_prev (char c, List_Node *curr)
|
|||||||
/* See how this asso_value change affects previous keywords. If
|
/* See how this asso_value change affects previous keywords. If
|
||||||
it does better than before we'll take it! */
|
it does better than before we'll take it! */
|
||||||
|
|
||||||
for (List_Node *ptr = head;
|
for (KeywordExt_List *ptr = head; ; ptr = ptr->rest())
|
||||||
!collision_detector->set_bit (hash (ptr)) || ++collisions < fewest_collisions;
|
{
|
||||||
ptr = ptr->next)
|
KeywordExt *keyword = ptr->first();
|
||||||
if (ptr == curr)
|
if (collision_detector->set_bit (hash (keyword))
|
||||||
|
&& ++collisions >= fewest_collisions)
|
||||||
|
break;
|
||||||
|
if (keyword == curr)
|
||||||
{
|
{
|
||||||
fewest_collisions = collisions;
|
fewest_collisions = collisions;
|
||||||
if (option[DEBUG])
|
if (option[DEBUG])
|
||||||
@@ -200,6 +203,7 @@ Gen_Perf::affects_prev (char c, List_Node *curr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Restore original values, no more tries. */
|
/* Restore original values, no more tries. */
|
||||||
asso_values[(unsigned char)c] = original_char;
|
asso_values[(unsigned char)c] = original_char;
|
||||||
@@ -210,7 +214,7 @@ Gen_Perf::affects_prev (char c, List_Node *curr)
|
|||||||
/* Change a character value, try least-used characters first. */
|
/* Change a character value, try least-used characters first. */
|
||||||
|
|
||||||
void
|
void
|
||||||
Gen_Perf::change (List_Node *prior, List_Node *curr)
|
Gen_Perf::change (KeywordExt *prior, KeywordExt *curr)
|
||||||
{
|
{
|
||||||
static char *union_set;
|
static char *union_set;
|
||||||
int union_set_length;
|
int union_set_length;
|
||||||
@@ -247,8 +251,13 @@ Gen_Perf::change (List_Node *prior, List_Node *curr)
|
|||||||
return; /* Good, doesn't affect previous hash values, we'll take it. */
|
return; /* Good, doesn't affect previous hash values, we'll take it. */
|
||||||
}
|
}
|
||||||
|
|
||||||
for (List_Node *ptr = head; ptr != curr; ptr = ptr->next)
|
for (KeywordExt_List *ptr = head; ; ptr = ptr->rest())
|
||||||
hash (ptr);
|
{
|
||||||
|
KeywordExt* keyword = ptr->first();
|
||||||
|
if (keyword == curr)
|
||||||
|
break;
|
||||||
|
hash (keyword);
|
||||||
|
}
|
||||||
|
|
||||||
hash (curr);
|
hash (curr);
|
||||||
|
|
||||||
@@ -275,17 +284,23 @@ Gen_Perf::change (List_Node *prior, List_Node *curr)
|
|||||||
int
|
int
|
||||||
Gen_Perf::doit_all (void)
|
Gen_Perf::doit_all (void)
|
||||||
{
|
{
|
||||||
List_Node *curr;
|
KeywordExt_List *curr;
|
||||||
for (curr = head; curr; curr = curr->next)
|
for (curr = head; curr != NULL; curr = curr->rest())
|
||||||
{
|
{
|
||||||
hash (curr);
|
KeywordExt *currkw = curr->first();
|
||||||
|
|
||||||
for (List_Node *ptr = head; ptr != curr; ptr = ptr->next)
|
hash (currkw);
|
||||||
if (ptr->hash_value == curr->hash_value)
|
|
||||||
|
for (KeywordExt_List *ptr = head; ptr != curr; ptr = ptr->rest())
|
||||||
{
|
{
|
||||||
change (ptr, curr);
|
KeywordExt *ptrkw = ptr->first();
|
||||||
|
|
||||||
|
if (ptrkw->hash_value == currkw->hash_value)
|
||||||
|
{
|
||||||
|
change (ptrkw, currkw);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
num_done++;
|
num_done++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,16 +308,23 @@ Gen_Perf::doit_all (void)
|
|||||||
|
|
||||||
collision_detector->clear ();
|
collision_detector->clear ();
|
||||||
|
|
||||||
for (curr = head; curr; curr = curr->next)
|
for (curr = head; curr; curr = curr->rest())
|
||||||
if (collision_detector->set_bit (hash (curr)))
|
{
|
||||||
|
unsigned int hashcode = hash (curr->first());
|
||||||
|
if (collision_detector->set_bit (hashcode))
|
||||||
|
{
|
||||||
if (option[DUP]) /* Keep track of this number... */
|
if (option[DUP]) /* Keep track of this number... */
|
||||||
total_duplicates++;
|
total_duplicates++;
|
||||||
else /* Yow, big problems. we're outta here! */
|
else /* Yow, big problems. we're outta here! */
|
||||||
{
|
{
|
||||||
fprintf (stderr, "\nInternal error, duplicate value %d:\n"
|
fprintf (stderr,
|
||||||
"try options -D or -r, or use new key positions.\n\n", hash (curr));
|
"\nInternal error, duplicate value %d:\n"
|
||||||
|
"try options -D or -r, or use new key positions.\n\n",
|
||||||
|
hashcode);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Sorts the key word list by hash value, and then outputs the list.
|
/* Sorts the key word list by hash value, and then outputs the list.
|
||||||
The generated hash table code is only output if the early stage of
|
The generated hash table code is only output if the early stage of
|
||||||
|
|||||||
@@ -36,9 +36,9 @@ private:
|
|||||||
int num_done; /* Number of keywords processed without a collision. */
|
int num_done; /* Number of keywords processed without a collision. */
|
||||||
Bool_Array *collision_detector;
|
Bool_Array *collision_detector;
|
||||||
|
|
||||||
void change (List_Node *prior, List_Node *curr);
|
void change (KeywordExt *prior, KeywordExt *curr);
|
||||||
int affects_prev (char c, List_Node *curr);
|
int affects_prev (char c, KeywordExt *curr);
|
||||||
static int hash (List_Node *key_node);
|
static int hash (KeywordExt *key_node);
|
||||||
static int compute_disjoint_union (const char *set_1, int size_1, const char *set_2, int size_2, char *set_3);
|
static int compute_disjoint_union (const char *set_1, int size_1, const char *set_2, int size_2, char *set_3);
|
||||||
static void sort_set (char *union_set, int len);
|
static void sort_set (char *union_set, int len);
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
|
|||||||
This compromises information hiding somewhat, but greatly reduces
|
This compromises information hiding somewhat, but greatly reduces
|
||||||
memory fragmentation, since we can now use alloca! */
|
memory fragmentation, since we can now use alloca! */
|
||||||
|
|
||||||
Hash_Table::Hash_Table (List_Node **table_ptr, int s, int ignore_len):
|
Hash_Table::Hash_Table (KeywordExt **table_ptr, int s, int ignore_len):
|
||||||
table (table_ptr), size (s), collisions (0), ignore_length (ignore_len)
|
table (table_ptr), size (s), collisions (0), ignore_length (ignore_len)
|
||||||
{
|
{
|
||||||
memset ((char *) table, 0, size * sizeof (*table));
|
memset ((char *) table, 0, size * sizeof (*table));
|
||||||
@@ -68,8 +68,8 @@ Hash_Table::~Hash_Table (void)
|
|||||||
in the table. Otherwise inserts the ITEM, and returns FALSE.
|
in the table. Otherwise inserts the ITEM, and returns FALSE.
|
||||||
Uses double hashing. */
|
Uses double hashing. */
|
||||||
|
|
||||||
List_Node *
|
KeywordExt *
|
||||||
Hash_Table::insert (List_Node *item)
|
Hash_Table::insert (KeywordExt *item)
|
||||||
{
|
{
|
||||||
unsigned hash_val = hashpjw (item->selchars, item->selchars_length);
|
unsigned hash_val = hashpjw (item->selchars, item->selchars_length);
|
||||||
int probe = hash_val & (size - 1);
|
int probe = hash_val & (size - 1);
|
||||||
@@ -87,5 +87,5 @@ Hash_Table::insert (List_Node *item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
table[probe] = item;
|
table[probe] = item;
|
||||||
return (List_Node *) 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/* Hash table used to check for duplicate keyword entries.
|
/* Hash table used to check for duplicate keyword entries.
|
||||||
|
|
||||||
Copyright (C) 1989-1998, 2000 Free Software Foundation, Inc.
|
Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc.
|
||||||
written by Douglas C. Schmidt (schmidt@ics.uci.edu)
|
written by Douglas C. Schmidt (schmidt@ics.uci.edu)
|
||||||
|
|
||||||
This file is part of GNU GPERF.
|
This file is part of GNU GPERF.
|
||||||
@@ -24,20 +24,20 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
|
|||||||
#ifndef hash_table_h
|
#ifndef hash_table_h
|
||||||
#define hash_table_h 1
|
#define hash_table_h 1
|
||||||
|
|
||||||
#include "list-node.h"
|
#include "keyword.h"
|
||||||
|
|
||||||
class Hash_Table
|
class Hash_Table
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
List_Node **table; /* Vector of pointers to linked lists of List_Node's. */
|
KeywordExt **table; /* Vector of pointers to linked lists of keywords. */
|
||||||
int size; /* Size of the vector. */
|
int size; /* Size of the vector. */
|
||||||
int collisions; /* Find out how well our double hashing is working! */
|
int collisions; /* Find out how well our double hashing is working! */
|
||||||
int ignore_length;
|
int ignore_length;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Hash_Table (List_Node **t, int s, int ignore_len);
|
Hash_Table (KeywordExt **t, int s, int ignore_len);
|
||||||
~Hash_Table (void);
|
~Hash_Table (void);
|
||||||
List_Node *insert (List_Node *item);
|
KeywordExt *insert (KeywordExt *item);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
264
src/key-list.cc
264
src/key-list.cc
@@ -203,9 +203,10 @@ Key_List::set_output_types (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extracts a key from an input line and creates a new List_Node for it. */
|
/* Extracts a key from an input line and creates a new KeywordExt_List for
|
||||||
|
it. */
|
||||||
|
|
||||||
static List_Node *
|
static KeywordExt_List *
|
||||||
parse_line (const char *line, const char *delimiters)
|
parse_line (const char *line, const char *delimiters)
|
||||||
{
|
{
|
||||||
if (*line == '"')
|
if (*line == '"')
|
||||||
@@ -324,7 +325,7 @@ parse_line (const char *line, const char *delimiters)
|
|||||||
}
|
}
|
||||||
lp++;
|
lp++;
|
||||||
}
|
}
|
||||||
return new List_Node (key, kp - key, option[TYPE] ? lp : "");
|
return new KeywordExt_List (key, kp - key, option[TYPE] ? lp : "");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -337,7 +338,7 @@ parse_line (const char *line, const char *delimiters)
|
|||||||
else
|
else
|
||||||
/* Skip the first delimiter. */
|
/* Skip the first delimiter. */
|
||||||
rest = &line[len + 1];
|
rest = &line[len + 1];
|
||||||
return new List_Node (line, len, option[TYPE] ? rest : "");
|
return new KeywordExt_List (line, len, option[TYPE] ? rest : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,15 +365,18 @@ Key_List::read_keys (void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
const char *delimiter = option.get_delimiter ();
|
const char *delimiter = option.get_delimiter ();
|
||||||
List_Node *temp, *trail = 0;
|
KeywordExt_List *temp;
|
||||||
|
KeywordExt_List *trail = NULL;
|
||||||
|
|
||||||
head = parse_line (ptr, delimiter);
|
head = parse_line (ptr, delimiter);
|
||||||
|
head->first()->init_selchars(this);
|
||||||
|
|
||||||
for (temp = head;
|
for (temp = head;
|
||||||
(ptr = Read_Line::read_next_line ()) && strcmp (ptr, "%%");
|
(ptr = Read_Line::read_next_line ()) && strcmp (ptr, "%%");
|
||||||
temp = temp->next)
|
temp = temp->rest())
|
||||||
{
|
{
|
||||||
temp->next = parse_line (ptr, delimiter);
|
temp->rest() = parse_line (ptr, delimiter);
|
||||||
|
temp->rest()->first()->init_selchars(this);
|
||||||
total_keys++;
|
total_keys++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,7 +387,7 @@ Key_List::read_keys (void)
|
|||||||
/* Hash table this number of times larger than keyword number. */
|
/* Hash table this number of times larger than keyword number. */
|
||||||
int table_size = (list_len = total_keys) * TABLE_MULTIPLE;
|
int table_size = (list_len = total_keys) * TABLE_MULTIPLE;
|
||||||
/* Table must be a power of 2 for the hash function scheme to work. */
|
/* Table must be a power of 2 for the hash function scheme to work. */
|
||||||
List_Node **table = new List_Node*[POW (table_size)];
|
KeywordExt **table = new KeywordExt*[POW (table_size)];
|
||||||
|
|
||||||
/* Make large hash table for efficiency. */
|
/* Make large hash table for efficiency. */
|
||||||
Hash_Table found_link (table, table_size, option[NOLENGTH]);
|
Hash_Table found_link (table, table_size, option[NOLENGTH]);
|
||||||
@@ -391,38 +395,39 @@ Key_List::read_keys (void)
|
|||||||
/* Test whether there are any links and also set the maximum length of
|
/* Test whether there are any links and also set the maximum length of
|
||||||
an identifier in the keyword list. */
|
an identifier in the keyword list. */
|
||||||
|
|
||||||
for (temp = head; temp; temp = temp->next)
|
for (temp = head; temp; temp = temp->rest())
|
||||||
{
|
{
|
||||||
List_Node *ptr = found_link.insert (temp);
|
KeywordExt *keyword = temp->first();
|
||||||
|
KeywordExt *other_keyword = found_link.insert (keyword);
|
||||||
|
|
||||||
/* Check for links. We deal with these by building an equivalence class
|
/* 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
|
of all duplicate values (i.e., links) so that only 1 keyword is
|
||||||
representative of the entire collection. This *greatly* simplifies
|
representative of the entire collection. This *greatly* simplifies
|
||||||
processing during later stages of the program. */
|
processing during later stages of the program. */
|
||||||
|
|
||||||
if (ptr)
|
if (other_keyword)
|
||||||
{
|
{
|
||||||
total_duplicates++;
|
total_duplicates++;
|
||||||
list_len--;
|
list_len--;
|
||||||
trail->next = temp->next;
|
trail->rest() = temp->rest();
|
||||||
temp->duplicate_link = ptr->duplicate_link;
|
temp->first()->duplicate_link = other_keyword->duplicate_link;
|
||||||
ptr->duplicate_link = temp;
|
other_keyword->duplicate_link = temp->first();
|
||||||
|
|
||||||
/* Complain if user hasn't enabled the duplicate option. */
|
/* Complain if user hasn't enabled the duplicate option. */
|
||||||
if (!option[DUP] || option[DEBUG])
|
if (!option[DUP] || option[DEBUG])
|
||||||
fprintf (stderr, "Key link: \"%.*s\" = \"%.*s\", with key set \"%.*s\".\n",
|
fprintf (stderr, "Key link: \"%.*s\" = \"%.*s\", with key set \"%.*s\".\n",
|
||||||
temp->allchars_length, temp->allchars,
|
keyword->allchars_length, keyword->allchars,
|
||||||
ptr->allchars_length, ptr->allchars,
|
other_keyword->allchars_length, other_keyword->allchars,
|
||||||
temp->selchars_length, temp->selchars);
|
keyword->selchars_length, keyword->selchars);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
trail = temp;
|
trail = temp;
|
||||||
|
|
||||||
/* Update minimum and maximum keyword length, if needed. */
|
/* Update minimum and maximum keyword length, if needed. */
|
||||||
if (max_key_len < temp->allchars_length)
|
if (max_key_len < keyword->allchars_length)
|
||||||
max_key_len = temp->allchars_length;
|
max_key_len = keyword->allchars_length;
|
||||||
if (min_key_len > temp->allchars_length)
|
if (min_key_len > keyword->allchars_length)
|
||||||
min_key_len = temp->allchars_length;
|
min_key_len = keyword->allchars_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] table;
|
delete[] table;
|
||||||
@@ -458,11 +463,11 @@ Key_List::read_keys (void)
|
|||||||
almost identical code without incurring the overhead of a function
|
almost identical code without incurring the overhead of a function
|
||||||
call comparison. */
|
call comparison. */
|
||||||
|
|
||||||
List_Node *
|
KeywordExt_List *
|
||||||
Key_List::merge (List_Node *list1, List_Node *list2)
|
Key_List::merge (KeywordExt_List *list1, KeywordExt_List *list2)
|
||||||
{
|
{
|
||||||
List_Node *result;
|
KeywordExt_List *result;
|
||||||
List_Node **resultp = &result;
|
KeywordExt_List **resultp = &result;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (!list1)
|
if (!list1)
|
||||||
@@ -475,16 +480,16 @@ Key_List::merge (List_Node *list1, List_Node *list2)
|
|||||||
*resultp = list1;
|
*resultp = list1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (occurrence_sort && list1->occurrence < list2->occurrence
|
if (occurrence_sort && list1->first()->occurrence < list2->first()->occurrence
|
||||||
|| hash_sort && list1->hash_value > list2->hash_value)
|
|| hash_sort && list1->first()->hash_value > list2->first()->hash_value)
|
||||||
{
|
{
|
||||||
*resultp = list2;
|
*resultp = list2;
|
||||||
resultp = &list2->next; list2 = list1; list1 = *resultp;
|
resultp = &list2->rest(); list2 = list1; list1 = *resultp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*resultp = list1;
|
*resultp = list1;
|
||||||
resultp = &list1->next; list1 = *resultp;
|
resultp = &list1->rest(); list1 = *resultp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -493,26 +498,26 @@ Key_List::merge (List_Node *list1, List_Node *list2)
|
|||||||
/* Applies the merge sort algorithm to recursively sort the key list by
|
/* Applies the merge sort algorithm to recursively sort the key list by
|
||||||
frequency of occurrence of elements in the key set. */
|
frequency of occurrence of elements in the key set. */
|
||||||
|
|
||||||
List_Node *
|
KeywordExt_List *
|
||||||
Key_List::merge_sort (List_Node *head)
|
Key_List::merge_sort (KeywordExt_List *head)
|
||||||
{
|
{
|
||||||
if (!head || !head->next)
|
if (!head || !head->rest())
|
||||||
return head;
|
return head;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
List_Node *middle = head;
|
KeywordExt_List *middle = head;
|
||||||
List_Node *temp = head->next->next;
|
KeywordExt_List *temp = head->rest()->rest();
|
||||||
|
|
||||||
while (temp)
|
while (temp)
|
||||||
{
|
{
|
||||||
temp = temp->next;
|
temp = temp->rest();
|
||||||
middle = middle->next;
|
middle = middle->rest();
|
||||||
if (temp)
|
if (temp)
|
||||||
temp = temp->next;
|
temp = temp->rest();
|
||||||
}
|
}
|
||||||
|
|
||||||
temp = middle->next;
|
temp = middle->rest();
|
||||||
middle->next = 0;
|
middle->rest() = 0;
|
||||||
return merge (merge_sort (head), merge_sort (temp));
|
return merge (merge_sort (head), merge_sort (temp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -520,7 +525,7 @@ Key_List::merge_sort (List_Node *head)
|
|||||||
/* Returns the frequency of occurrence of elements in the key set. */
|
/* Returns the frequency of occurrence of elements in the key set. */
|
||||||
|
|
||||||
inline int
|
inline int
|
||||||
Key_List::get_occurrence (List_Node *ptr)
|
Key_List::get_occurrence (KeywordExt *ptr)
|
||||||
{
|
{
|
||||||
int value = 0;
|
int value = 0;
|
||||||
|
|
||||||
@@ -536,7 +541,7 @@ Key_List::get_occurrence (List_Node *ptr)
|
|||||||
determined. */
|
determined. */
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
Key_List::set_determined (List_Node *ptr)
|
Key_List::set_determined (KeywordExt *ptr)
|
||||||
{
|
{
|
||||||
const char *p = ptr->selchars;
|
const char *p = ptr->selchars;
|
||||||
unsigned int i = ptr->selchars_length;
|
unsigned int i = ptr->selchars_length;
|
||||||
@@ -547,7 +552,7 @@ Key_List::set_determined (List_Node *ptr)
|
|||||||
/* Returns TRUE if PTR's key set is already completely determined. */
|
/* Returns TRUE if PTR's key set is already completely determined. */
|
||||||
|
|
||||||
inline int
|
inline int
|
||||||
Key_List::already_determined (List_Node *ptr)
|
Key_List::already_determined (KeywordExt *ptr)
|
||||||
{
|
{
|
||||||
int is_determined = 1;
|
int is_determined = 1;
|
||||||
|
|
||||||
@@ -568,32 +573,36 @@ Key_List::already_determined (List_Node *ptr)
|
|||||||
void
|
void
|
||||||
Key_List::reorder (void)
|
Key_List::reorder (void)
|
||||||
{
|
{
|
||||||
List_Node *ptr;
|
KeywordExt_List *ptr;
|
||||||
for (ptr = head; ptr; ptr = ptr->next)
|
for (ptr = head; ptr; ptr = ptr->rest())
|
||||||
ptr->occurrence = get_occurrence (ptr);
|
{
|
||||||
|
KeywordExt *keyword = ptr->first();
|
||||||
|
|
||||||
|
keyword->occurrence = get_occurrence (keyword);
|
||||||
|
}
|
||||||
|
|
||||||
hash_sort = 0;
|
hash_sort = 0;
|
||||||
occurrence_sort = 1;
|
occurrence_sort = 1;
|
||||||
|
|
||||||
for (ptr = head = merge_sort (head); ptr->next; ptr = ptr->next)
|
head = merge_sort (head);
|
||||||
{
|
|
||||||
set_determined (ptr);
|
|
||||||
|
|
||||||
if (already_determined (ptr->next))
|
for (ptr = head; ptr->rest(); ptr = ptr->rest())
|
||||||
continue;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
List_Node *trail_ptr = ptr->next;
|
set_determined (ptr->first());
|
||||||
List_Node *run_ptr = trail_ptr->next;
|
|
||||||
|
|
||||||
for (; run_ptr; run_ptr = trail_ptr->next)
|
if (!already_determined (ptr->rest()->first()))
|
||||||
|
{
|
||||||
|
KeywordExt_List *trail_ptr = ptr->rest();
|
||||||
|
KeywordExt_List *run_ptr = trail_ptr->rest();
|
||||||
|
|
||||||
|
for (; run_ptr; run_ptr = trail_ptr->rest())
|
||||||
{
|
{
|
||||||
|
|
||||||
if (already_determined (run_ptr))
|
if (already_determined (run_ptr->first()))
|
||||||
{
|
{
|
||||||
trail_ptr->next = run_ptr->next;
|
trail_ptr->rest() = run_ptr->rest();
|
||||||
run_ptr->next = ptr->next;
|
run_ptr->rest() = ptr->rest();
|
||||||
ptr = ptr->next = run_ptr;
|
ptr = ptr->rest() = run_ptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
trail_ptr = run_ptr;
|
trail_ptr = run_ptr;
|
||||||
@@ -647,12 +656,12 @@ static const char *char_to_index;
|
|||||||
void
|
void
|
||||||
Key_List::compute_min_max (void)
|
Key_List::compute_min_max (void)
|
||||||
{
|
{
|
||||||
List_Node *temp;
|
KeywordExt_List *temp;
|
||||||
for (temp = head; temp->next; temp = temp->next)
|
for (temp = head; temp->rest(); temp = temp->rest())
|
||||||
;
|
;
|
||||||
|
|
||||||
min_hash_value = head->hash_value;
|
min_hash_value = head->first()->hash_value;
|
||||||
max_hash_value = temp->hash_value;
|
max_hash_value = temp->first()->hash_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
@@ -663,15 +672,14 @@ int
|
|||||||
Key_List::num_hash_values (void)
|
Key_List::num_hash_values (void)
|
||||||
{
|
{
|
||||||
int count = 1;
|
int count = 1;
|
||||||
List_Node *temp;
|
KeywordExt_List *temp;
|
||||||
int value;
|
int value;
|
||||||
|
|
||||||
for (temp = head, value = temp->hash_value; temp->next; )
|
for (temp = head, value = temp->first()->hash_value; (temp = temp->rest()) != NULL; )
|
||||||
{
|
{
|
||||||
temp = temp->next;
|
if (value != temp->first()->hash_value)
|
||||||
if (value != temp->hash_value)
|
|
||||||
{
|
{
|
||||||
value = temp->hash_value;
|
value = temp->first()->hash_value;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1135,7 +1143,7 @@ Key_List::output_keylength_table (void)
|
|||||||
int index;
|
int index;
|
||||||
int column;
|
int column;
|
||||||
const char *indent = option[GLOBAL] ? "" : " ";
|
const char *indent = option[GLOBAL] ? "" : " ";
|
||||||
List_Node *temp;
|
KeywordExt_List *temp;
|
||||||
|
|
||||||
printf ("%sstatic %s%s lengthtable[] =\n%s {",
|
printf ("%sstatic %s%s lengthtable[] =\n%s {",
|
||||||
indent, const_readonly_array,
|
indent, const_readonly_array,
|
||||||
@@ -1145,17 +1153,17 @@ Key_List::output_keylength_table (void)
|
|||||||
/* Generate an array of lengths, similar to output_keyword_table. */
|
/* Generate an array of lengths, similar to output_keyword_table. */
|
||||||
|
|
||||||
column = 0;
|
column = 0;
|
||||||
for (temp = head, index = 0; temp; temp = temp->next)
|
for (temp = head, index = 0; temp; temp = temp->rest())
|
||||||
{
|
{
|
||||||
if (option[SWITCH] && !option[TYPE]
|
if (option[SWITCH] && !option[TYPE]
|
||||||
&& !(temp->duplicate_link
|
&& !(temp->first()->duplicate_link
|
||||||
|| (temp->next && temp->hash_value == temp->next->hash_value)))
|
|| (temp->rest() && temp->first()->hash_value == temp->rest()->first()->hash_value)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (index < temp->hash_value && !option[SWITCH] && !option[DUP])
|
if (index < temp->first()->hash_value && !option[SWITCH] && !option[DUP])
|
||||||
{
|
{
|
||||||
/* Some blank entries. */
|
/* Some blank entries. */
|
||||||
for ( ; index < temp->hash_value; index++)
|
for ( ; index < temp->first()->hash_value; index++)
|
||||||
{
|
{
|
||||||
if (index > 0)
|
if (index > 0)
|
||||||
printf (",");
|
printf (",");
|
||||||
@@ -1169,11 +1177,11 @@ Key_List::output_keylength_table (void)
|
|||||||
printf (",");
|
printf (",");
|
||||||
if ((column++ % columns) == 0)
|
if ((column++ % columns) == 0)
|
||||||
printf("\n%s ", indent);
|
printf("\n%s ", indent);
|
||||||
printf ("%3d", temp->allchars_length);
|
printf ("%3d", temp->first()->allchars_length);
|
||||||
|
|
||||||
/* Deal with links specially. */
|
/* Deal with links specially. */
|
||||||
if (temp->duplicate_link) // implies option[DUP]
|
if (temp->first()->duplicate_link) // implies option[DUP]
|
||||||
for (KeywordExt *links = temp->duplicate_link; links; links = links->duplicate_link)
|
for (KeywordExt *links = temp->first()->duplicate_link; links; links = links->duplicate_link)
|
||||||
{
|
{
|
||||||
++index;
|
++index;
|
||||||
printf (",");
|
printf (",");
|
||||||
@@ -1253,7 +1261,7 @@ Key_List::output_keyword_table (void)
|
|||||||
{
|
{
|
||||||
const char *indent = option[GLOBAL] ? "" : " ";
|
const char *indent = option[GLOBAL] ? "" : " ";
|
||||||
int index;
|
int index;
|
||||||
List_Node *temp;
|
KeywordExt_List *temp;
|
||||||
|
|
||||||
printf ("%sstatic ",
|
printf ("%sstatic ",
|
||||||
indent);
|
indent);
|
||||||
@@ -1265,31 +1273,31 @@ Key_List::output_keyword_table (void)
|
|||||||
|
|
||||||
/* Generate an array of reserved words at appropriate locations. */
|
/* Generate an array of reserved words at appropriate locations. */
|
||||||
|
|
||||||
for (temp = head, index = 0; temp; temp = temp->next)
|
for (temp = head, index = 0; temp; temp = temp->rest())
|
||||||
{
|
{
|
||||||
if (option[SWITCH] && !option[TYPE]
|
if (option[SWITCH] && !option[TYPE]
|
||||||
&& !(temp->duplicate_link
|
&& !(temp->first()->duplicate_link
|
||||||
|| (temp->next && temp->hash_value == temp->next->hash_value)))
|
|| (temp->rest() && temp->first()->hash_value == temp->rest()->first()->hash_value)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (index > 0)
|
if (index > 0)
|
||||||
printf (",\n");
|
printf (",\n");
|
||||||
|
|
||||||
if (index < temp->hash_value && !option[SWITCH] && !option[DUP])
|
if (index < temp->first()->hash_value && !option[SWITCH] && !option[DUP])
|
||||||
{
|
{
|
||||||
/* Some blank entries. */
|
/* Some blank entries. */
|
||||||
output_keyword_blank_entries (temp->hash_value - index, indent);
|
output_keyword_blank_entries (temp->first()->hash_value - index, indent);
|
||||||
printf (",\n");
|
printf (",\n");
|
||||||
index = temp->hash_value;
|
index = temp->first()->hash_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
temp->final_index = index;
|
temp->first()->final_index = index;
|
||||||
|
|
||||||
output_keyword_entry (temp, indent);
|
output_keyword_entry (temp->first(), indent);
|
||||||
|
|
||||||
/* Deal with links specially. */
|
/* Deal with links specially. */
|
||||||
if (temp->duplicate_link) // implies option[DUP]
|
if (temp->first()->duplicate_link) // implies option[DUP]
|
||||||
for (KeywordExt *links = temp->duplicate_link; links; links = links->duplicate_link)
|
for (KeywordExt *links = temp->first()->duplicate_link; links; links = links->duplicate_link)
|
||||||
{
|
{
|
||||||
links->final_index = ++index;
|
links->final_index = ++index;
|
||||||
printf (",\n");
|
printf (",\n");
|
||||||
@@ -1336,24 +1344,24 @@ Key_List::output_lookup_array (void)
|
|||||||
|
|
||||||
/* Now dup_ptr = &duplicates[0] and lookup_ptr = &lookup_array[0]. */
|
/* Now dup_ptr = &duplicates[0] and lookup_ptr = &lookup_array[0]. */
|
||||||
|
|
||||||
for (List_Node *temp = head; temp; temp = temp->next)
|
for (KeywordExt_List *temp = head; temp; temp = temp->rest())
|
||||||
{
|
{
|
||||||
int hash_value = temp->hash_value;
|
int hash_value = temp->first()->hash_value;
|
||||||
lookup_array[hash_value] = temp->final_index;
|
lookup_array[hash_value] = temp->first()->final_index;
|
||||||
if (option[DEBUG])
|
if (option[DEBUG])
|
||||||
fprintf (stderr, "keyword = %.*s, index = %d\n",
|
fprintf (stderr, "keyword = %.*s, index = %d\n",
|
||||||
temp->allchars_length, temp->allchars, temp->final_index);
|
temp->first()->allchars_length, temp->first()->allchars, temp->first()->final_index);
|
||||||
if (temp->duplicate_link
|
if (temp->first()->duplicate_link
|
||||||
|| (temp->next && hash_value == temp->next->hash_value))
|
|| (temp->rest() && hash_value == temp->rest()->first()->hash_value))
|
||||||
{
|
{
|
||||||
/* Start a duplicate entry. */
|
/* Start a duplicate entry. */
|
||||||
dup_ptr->hash_value = hash_value;
|
dup_ptr->hash_value = hash_value;
|
||||||
dup_ptr->index = temp->final_index;
|
dup_ptr->index = temp->first()->final_index;
|
||||||
dup_ptr->count = 1;
|
dup_ptr->count = 1;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
for (KeywordExt *ptr = temp->duplicate_link; ptr; ptr = ptr->duplicate_link)
|
for (KeywordExt *ptr = temp->first()->duplicate_link; ptr; ptr = ptr->duplicate_link)
|
||||||
{
|
{
|
||||||
dup_ptr->count++;
|
dup_ptr->count++;
|
||||||
if (option[DEBUG])
|
if (option[DEBUG])
|
||||||
@@ -1362,15 +1370,15 @@ Key_List::output_lookup_array (void)
|
|||||||
ptr->allchars_length, ptr->allchars, ptr->final_index);
|
ptr->allchars_length, ptr->allchars, ptr->final_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(temp->next && hash_value == temp->next->hash_value))
|
if (!(temp->rest() && hash_value == temp->rest()->first()->hash_value))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
temp = temp->next;
|
temp = temp->rest();
|
||||||
|
|
||||||
dup_ptr->count++;
|
dup_ptr->count++;
|
||||||
if (option[DEBUG])
|
if (option[DEBUG])
|
||||||
fprintf (stderr, "dynamic linked keyword = %.*s, index = %d\n",
|
fprintf (stderr, "dynamic linked keyword = %.*s, index = %d\n",
|
||||||
temp->allchars_length, temp->allchars, temp->final_index);
|
temp->first()->allchars_length, temp->first()->allchars, temp->first()->final_index);
|
||||||
}
|
}
|
||||||
assert (dup_ptr->count >= 2);
|
assert (dup_ptr->count >= 2);
|
||||||
dup_ptr++;
|
dup_ptr++;
|
||||||
@@ -1497,29 +1505,29 @@ Key_List::output_lookup_tables (void)
|
|||||||
|
|
||||||
/* Output a single switch case (including duplicates). Advance list. */
|
/* Output a single switch case (including duplicates). Advance list. */
|
||||||
|
|
||||||
static List_Node *
|
static KeywordExt_List *
|
||||||
output_switch_case (List_Node *list, int indent, int *jumps_away)
|
output_switch_case (KeywordExt_List *list, int indent, int *jumps_away)
|
||||||
{
|
{
|
||||||
if (option[DEBUG])
|
if (option[DEBUG])
|
||||||
printf ("%*s/* hash value = %4d, keyword = \"%.*s\" */\n",
|
printf ("%*s/* hash value = %4d, keyword = \"%.*s\" */\n",
|
||||||
indent, "", list->hash_value, list->allchars_length, list->allchars);
|
indent, "", list->first()->hash_value, list->first()->allchars_length, list->first()->allchars);
|
||||||
|
|
||||||
if (option[DUP]
|
if (option[DUP]
|
||||||
&& (list->duplicate_link
|
&& (list->first()->duplicate_link
|
||||||
|| (list->next && list->hash_value == list->next->hash_value)))
|
|| (list->rest() && list->first()->hash_value == list->rest()->first()->hash_value)))
|
||||||
{
|
{
|
||||||
if (option[LENTABLE])
|
if (option[LENTABLE])
|
||||||
printf ("%*slengthptr = &lengthtable[%d];\n",
|
printf ("%*slengthptr = &lengthtable[%d];\n",
|
||||||
indent, "", list->final_index);
|
indent, "", list->first()->final_index);
|
||||||
printf ("%*swordptr = &%s[%d];\n",
|
printf ("%*swordptr = &%s[%d];\n",
|
||||||
indent, "", option.get_wordlist_name (), list->final_index);
|
indent, "", option.get_wordlist_name (), list->first()->final_index);
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (List_Node *temp = list; ; temp = temp->next)
|
for (KeywordExt_List *temp = list; ; temp = temp->rest())
|
||||||
{
|
{
|
||||||
for (KeywordExt *links = temp; links; links = links->duplicate_link)
|
for (KeywordExt *links = temp->first(); links; links = links->duplicate_link)
|
||||||
count++;
|
count++;
|
||||||
if (!(temp->next && temp->hash_value == temp->next->hash_value))
|
if (!(temp->rest() && temp->first()->hash_value == temp->rest()->first()->hash_value))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1535,16 +1543,16 @@ output_switch_case (List_Node *list, int indent, int *jumps_away)
|
|||||||
{
|
{
|
||||||
printf ("%*sif (len == %d)\n"
|
printf ("%*sif (len == %d)\n"
|
||||||
"%*s {\n",
|
"%*s {\n",
|
||||||
indent, "", list->allchars_length,
|
indent, "", list->first()->allchars_length,
|
||||||
indent, "");
|
indent, "");
|
||||||
indent += 4;
|
indent += 4;
|
||||||
}
|
}
|
||||||
printf ("%*sresword = ",
|
printf ("%*sresword = ",
|
||||||
indent, "");
|
indent, "");
|
||||||
if (option[TYPE])
|
if (option[TYPE])
|
||||||
printf ("&%s[%d]", option.get_wordlist_name (), list->final_index);
|
printf ("&%s[%d]", option.get_wordlist_name (), list->first()->final_index);
|
||||||
else
|
else
|
||||||
output_string (list->allchars, list->allchars_length);
|
output_string (list->first()->allchars, list->first()->allchars_length);
|
||||||
printf (";\n");
|
printf (";\n");
|
||||||
printf ("%*sgoto compare;\n",
|
printf ("%*sgoto compare;\n",
|
||||||
indent, "");
|
indent, "");
|
||||||
@@ -1558,9 +1566,9 @@ output_switch_case (List_Node *list, int indent, int *jumps_away)
|
|||||||
*jumps_away = 1;
|
*jumps_away = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (list->next && list->hash_value == list->next->hash_value)
|
while (list->rest() && list->first()->hash_value == list->rest()->first()->hash_value)
|
||||||
list = list->next;
|
list = list->rest();
|
||||||
list = list->next;
|
list = list->rest();
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1568,7 +1576,7 @@ output_switch_case (List_Node *list, int indent, int *jumps_away)
|
|||||||
where 0 < num_switches <= size. */
|
where 0 < num_switches <= size. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
output_switches (List_Node *list, int num_switches, int size, int min_hash_value, int max_hash_value, int indent)
|
output_switches (KeywordExt_List *list, int num_switches, int size, int min_hash_value, int max_hash_value, int indent)
|
||||||
{
|
{
|
||||||
if (option[DEBUG])
|
if (option[DEBUG])
|
||||||
printf ("%*s/* know %d <= key <= %d, contains %d cases */\n",
|
printf ("%*s/* know %d <= key <= %d, contains %d cases */\n",
|
||||||
@@ -1581,27 +1589,27 @@ output_switches (List_Node *list, int num_switches, int size, int min_hash_value
|
|||||||
int size1 = (int)((double)size / (double)num_switches * (double)part1 + 0.5);
|
int size1 = (int)((double)size / (double)num_switches * (double)part1 + 0.5);
|
||||||
int size2 = size - size1;
|
int size2 = size - size1;
|
||||||
|
|
||||||
List_Node *temp = list;
|
KeywordExt_List *temp = list;
|
||||||
for (int count = size1; count > 0; count--)
|
for (int count = size1; count > 0; count--)
|
||||||
{
|
{
|
||||||
while (temp->hash_value == temp->next->hash_value)
|
while (temp->first()->hash_value == temp->rest()->first()->hash_value)
|
||||||
temp = temp->next;
|
temp = temp->rest();
|
||||||
temp = temp->next;
|
temp = temp->rest();
|
||||||
}
|
}
|
||||||
|
|
||||||
printf ("%*sif (key < %d)\n"
|
printf ("%*sif (key < %d)\n"
|
||||||
"%*s {\n",
|
"%*s {\n",
|
||||||
indent, "", temp->hash_value,
|
indent, "", temp->first()->hash_value,
|
||||||
indent, "");
|
indent, "");
|
||||||
|
|
||||||
output_switches (list, part1, size1, min_hash_value, temp->hash_value-1, indent+4);
|
output_switches (list, part1, size1, min_hash_value, temp->first()->hash_value-1, indent+4);
|
||||||
|
|
||||||
printf ("%*s }\n"
|
printf ("%*s }\n"
|
||||||
"%*selse\n"
|
"%*selse\n"
|
||||||
"%*s {\n",
|
"%*s {\n",
|
||||||
indent, "", indent, "", indent, "");
|
indent, "", indent, "", indent, "");
|
||||||
|
|
||||||
output_switches (temp, part2, size2, temp->hash_value, max_hash_value, indent+4);
|
output_switches (temp, part2, size2, temp->first()->hash_value, max_hash_value, indent+4);
|
||||||
|
|
||||||
printf ("%*s }\n",
|
printf ("%*s }\n",
|
||||||
indent, "");
|
indent, "");
|
||||||
@@ -1609,7 +1617,7 @@ output_switches (List_Node *list, int num_switches, int size, int min_hash_value
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Output a single switch. */
|
/* Output a single switch. */
|
||||||
int lowest_case_value = list->hash_value;
|
int lowest_case_value = list->first()->hash_value;
|
||||||
if (size == 1)
|
if (size == 1)
|
||||||
{
|
{
|
||||||
int jumps_away = 0;
|
int jumps_away = 0;
|
||||||
@@ -1640,7 +1648,7 @@ output_switches (List_Node *list, int num_switches, int size, int min_hash_value
|
|||||||
{
|
{
|
||||||
int jumps_away = 0;
|
int jumps_away = 0;
|
||||||
printf ("%*s case %d:\n",
|
printf ("%*s case %d:\n",
|
||||||
indent, "", list->hash_value - lowest_case_value);
|
indent, "", list->first()->hash_value - lowest_case_value);
|
||||||
list = output_switch_case (list, indent+6, &jumps_away);
|
list = output_switch_case (list, indent+6, &jumps_away);
|
||||||
if (!jumps_away)
|
if (!jumps_away)
|
||||||
printf ("%*s break;\n",
|
printf ("%*s break;\n",
|
||||||
@@ -2066,11 +2074,11 @@ Key_List::dump ()
|
|||||||
fprintf (stderr, "\nList contents are:\n(hash value, key length, index, %*s, keyword):\n",
|
fprintf (stderr, "\nList contents are:\n(hash value, key length, index, %*s, keyword):\n",
|
||||||
field_width, "selchars");
|
field_width, "selchars");
|
||||||
|
|
||||||
for (List_Node *ptr = head; ptr; ptr = ptr->next)
|
for (KeywordExt_List *ptr = head; ptr; ptr = ptr->rest())
|
||||||
fprintf (stderr, "%11d,%11d,%6d, %*.*s, %.*s\n",
|
fprintf (stderr, "%11d,%11d,%6d, %*.*s, %.*s\n",
|
||||||
ptr->hash_value, ptr->allchars_length, ptr->final_index,
|
ptr->first()->hash_value, ptr->first()->allchars_length, ptr->first()->final_index,
|
||||||
field_width, ptr->selchars_length, ptr->selchars,
|
field_width, ptr->first()->selchars_length, ptr->first()->selchars,
|
||||||
ptr->allchars_length, ptr->allchars);
|
ptr->first()->allchars_length, ptr->first()->allchars);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Simple-minded constructor action here... */
|
/* Simple-minded constructor action here... */
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
|
|||||||
#ifndef key_list_h
|
#ifndef key_list_h
|
||||||
#define key_list_h 1
|
#define key_list_h 1
|
||||||
|
|
||||||
#include "list-node.h"
|
#include "keyword-list.h"
|
||||||
#include "vectors.h"
|
#include "vectors.h"
|
||||||
#include "read-line.h"
|
#include "read-line.h"
|
||||||
|
|
||||||
@@ -54,12 +54,12 @@ private:
|
|||||||
int list_len; /* Length of head's Key_List, not counting duplicates. */
|
int list_len; /* Length of head's Key_List, not counting duplicates. */
|
||||||
int total_keys; /* Total number of keys, counting duplicates. */
|
int total_keys; /* Total number of keys, counting duplicates. */
|
||||||
static int determined[MAX_ALPHA_SIZE]; /* Used in function reorder, below. */
|
static int determined[MAX_ALPHA_SIZE]; /* Used in function reorder, below. */
|
||||||
static int get_occurrence (List_Node *ptr);
|
static int get_occurrence (KeywordExt *ptr);
|
||||||
#ifndef strcspn
|
#ifndef strcspn
|
||||||
static int strcspn (const char *s, const char *reject);
|
static int strcspn (const char *s, const char *reject);
|
||||||
#endif
|
#endif
|
||||||
static int already_determined (List_Node *ptr);
|
static int already_determined (KeywordExt *ptr);
|
||||||
static void set_determined (List_Node *ptr);
|
static void set_determined (KeywordExt *ptr);
|
||||||
void compute_min_max (void);
|
void compute_min_max (void);
|
||||||
int num_hash_values (void);
|
int num_hash_values (void);
|
||||||
void output_constants (struct Output_Constants&);
|
void output_constants (struct Output_Constants&);
|
||||||
@@ -75,11 +75,11 @@ private:
|
|||||||
const char *get_array_type (void);
|
const char *get_array_type (void);
|
||||||
const char *save_include_src (void);
|
const char *save_include_src (void);
|
||||||
const char *get_special_input (char delimiter);
|
const char *get_special_input (char delimiter);
|
||||||
List_Node *merge (List_Node *list1, List_Node *list2);
|
KeywordExt_List *merge (KeywordExt_List *list1, KeywordExt_List *list2);
|
||||||
List_Node *merge_sort (List_Node *head);
|
KeywordExt_List *merge_sort (KeywordExt_List *head);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
List_Node *head; /* Points to the head of the linked list. */
|
KeywordExt_List *head; /* Points to the head of the linked list. */
|
||||||
int total_duplicates; /* Total number of duplicate hash values. */
|
int total_duplicates; /* Total number of duplicate hash values. */
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
29
src/keyword-list.cc
Normal file
29
src/keyword-list.cc
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/* Keyword list.
|
||||||
|
|
||||||
|
Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc.
|
||||||
|
Written by 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 <stddef.h>
|
||||||
|
#include "keyword-list.h"
|
||||||
|
|
||||||
|
/* Constructor. */
|
||||||
|
KeywordExt_List::KeywordExt_List (const char *s, int s_len, const char *r)
|
||||||
|
: KeywordExt (s, s_len, r), cdr (NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
44
src/keyword-list.h
Normal file
44
src/keyword-list.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/* This may look like C code, but it is really -*- C++ -*- */
|
||||||
|
|
||||||
|
/* Keyword list.
|
||||||
|
|
||||||
|
Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc.
|
||||||
|
Written by 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 keyword_list_h
|
||||||
|
#define keyword_list_h 1
|
||||||
|
|
||||||
|
#include "keyword.h"
|
||||||
|
|
||||||
|
/* List node of a linear list. */
|
||||||
|
class KeywordExt_List : private KeywordExt {
|
||||||
|
public:
|
||||||
|
/* Constructor. */
|
||||||
|
KeywordExt_List (const char *allchars, int allchars_length, const char *rest);
|
||||||
|
|
||||||
|
/* Access to first element of list. */
|
||||||
|
KeywordExt* first () { return this; }
|
||||||
|
/* Access to next element of list. */
|
||||||
|
KeywordExt_List *& rest () { return cdr; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
KeywordExt_List * cdr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -19,11 +19,15 @@ 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. */
|
Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include "keyword.h"
|
#include "keyword.h"
|
||||||
|
#include "options.h"
|
||||||
|
|
||||||
|
|
||||||
/* Keyword class. */
|
/* Keyword class. */
|
||||||
|
|
||||||
|
/* Constructor. */
|
||||||
Keyword::Keyword (const char *s, int s_len, const char *r)
|
Keyword::Keyword (const char *s, int s_len, const char *r)
|
||||||
: allchars (s), allchars_length (s_len), rest (r)
|
: allchars (s), allchars_length (s_len), rest (r)
|
||||||
{
|
{
|
||||||
@@ -32,11 +36,79 @@ Keyword::Keyword (const char *s, int s_len, const char *r)
|
|||||||
|
|
||||||
/* KeywordExt class. */
|
/* KeywordExt class. */
|
||||||
|
|
||||||
|
/* Constructor. */
|
||||||
KeywordExt::KeywordExt (const char *s, int s_len, const char *r)
|
KeywordExt::KeywordExt (const char *s, int s_len, const char *r)
|
||||||
: Keyword (s, s_len, r), duplicate_link (NULL), final_index (0)
|
: Keyword (s, s_len, r), duplicate_link (NULL), final_index (0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sort a small set of 'char', base[0..len-1], in place. */
|
||||||
|
static inline void sort_char_set (char *base, int len)
|
||||||
|
{
|
||||||
|
/* Bubble sort is sufficient here. */
|
||||||
|
for (int i = 1; i < len; i++)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
char tmp;
|
||||||
|
|
||||||
|
for (j = i, tmp = base[j]; j > 0 && tmp < base[j - 1]; j--)
|
||||||
|
base[j] = base[j - 1];
|
||||||
|
|
||||||
|
base[j] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize selchars and selchars_length, and update v->occurrences. */
|
||||||
|
void KeywordExt::init_selchars (Vectors *v)
|
||||||
|
{
|
||||||
|
const char *k = allchars;
|
||||||
|
char *key_set =
|
||||||
|
new char[(option[ALLCHARS] ? allchars_length : option.get_max_keysig_size ())];
|
||||||
|
char *ptr = key_set;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (option[ALLCHARS])
|
||||||
|
/* Use all the character positions in the KEY. */
|
||||||
|
for (i = allchars_length; i > 0; k++, ptr++, i--)
|
||||||
|
v->occurrences[(unsigned char)(*ptr = *k)]++;
|
||||||
|
else
|
||||||
|
/* Only use those character positions specified by the user. */
|
||||||
|
{
|
||||||
|
/* Iterate through the list of key_positions, initializing occurrences
|
||||||
|
table and selchars (via char * pointer ptr). */
|
||||||
|
|
||||||
|
for (option.reset (); (i = option.get ()) != EOS; )
|
||||||
|
{
|
||||||
|
if (i == WORD_END)
|
||||||
|
/* Special notation for last KEY position, i.e. '$'. */
|
||||||
|
*ptr = allchars[allchars_length - 1];
|
||||||
|
else if (i <= allchars_length)
|
||||||
|
/* Within range of KEY length, so we'll keep it. */
|
||||||
|
*ptr = allchars[i - 1];
|
||||||
|
else
|
||||||
|
/* Out of range of KEY length, so we'll just skip it. */
|
||||||
|
continue;
|
||||||
|
v->occurrences[(unsigned char)*ptr]++;
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Didn't get any hits and user doesn't want to consider the
|
||||||
|
keylength, so there are essentially no usable hash positions! */
|
||||||
|
if (ptr == selchars && option[NOLENGTH])
|
||||||
|
{
|
||||||
|
fprintf (stderr, "Can't hash keyword %.*s with chosen key positions.\n",
|
||||||
|
allchars_length, allchars);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sort the KEY_SET items alphabetically. */
|
||||||
|
sort_char_set (key_set, ptr - key_set);
|
||||||
|
|
||||||
|
selchars = key_set;
|
||||||
|
selchars_length = ptr - key_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Keyword_Factory class. */
|
/* Keyword_Factory class. */
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
|
|||||||
#ifndef keyword_h
|
#ifndef keyword_h
|
||||||
#define keyword_h 1
|
#define keyword_h 1
|
||||||
|
|
||||||
|
#include "vectors.h"
|
||||||
|
|
||||||
/* An instance of this class is a keyword, as specified in the input file. */
|
/* An instance of this class is a keyword, as specified in the input file. */
|
||||||
struct Keyword
|
struct Keyword
|
||||||
{
|
{
|
||||||
@@ -52,6 +54,10 @@ struct KeywordExt : public Keyword
|
|||||||
/* Chained list of keywords having the same selchars. */
|
/* Chained list of keywords having the same selchars. */
|
||||||
KeywordExt * duplicate_link;
|
KeywordExt * duplicate_link;
|
||||||
|
|
||||||
|
/* Methods depending on the keyposition list. */
|
||||||
|
/* Initialize selchars and selchars_length, and update v->occurrences. */
|
||||||
|
void init_selchars (Vectors *v);
|
||||||
|
|
||||||
/* Data members used by the algorithm. */
|
/* Data members used by the algorithm. */
|
||||||
int occurrence; /* A metric for frequency of key set occurrences. */
|
int occurrence; /* A metric for frequency of key set occurrences. */
|
||||||
int hash_value; /* Hash value for the key. */
|
int hash_value; /* Hash value for the key. */
|
||||||
|
|||||||
@@ -450,7 +450,7 @@ Options::operator() (int argc, char *argv[])
|
|||||||
while ((option_char =
|
while ((option_char =
|
||||||
getopt_long (argument_count, argument_vector,
|
getopt_long (argument_count, argument_vector,
|
||||||
"adcCDe:Ef:F:gGhH:i:Ij:k:K:lL:nN:oprs:S:tTvW:Z:7",
|
"adcCDe:Ef:F:gGhH:i:Ij:k:K:lL:nN:oprs:S:tTvW:Z:7",
|
||||||
long_options, (int *)0))
|
long_options, NULL))
|
||||||
!= -1)
|
!= -1)
|
||||||
{
|
{
|
||||||
switch (option_char)
|
switch (option_char)
|
||||||
|
|||||||
@@ -38,21 +38,21 @@ Read_Line::read_next_line (void)
|
|||||||
;
|
;
|
||||||
|
|
||||||
if (c == EOF)
|
if (c == EOF)
|
||||||
return (char *)0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == EOF)
|
if (c == EOF)
|
||||||
return (char *)0;
|
return NULL;
|
||||||
|
|
||||||
ungetc (c, stdin);
|
ungetc (c, stdin);
|
||||||
|
|
||||||
char *line = (char *)0;
|
char *line = NULL;
|
||||||
size_t linesize = 0;
|
size_t linesize = 0;
|
||||||
int length = get_line (&line, &linesize, fp);
|
int length = get_line (&line, &linesize, fp);
|
||||||
if (length < 0)
|
if (length < 0)
|
||||||
{
|
{
|
||||||
delete[] line;
|
delete[] line;
|
||||||
return (char *)0;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (length > 0 && line[length - 1] == '\n')
|
if (length > 0 && line[length - 1] == '\n')
|
||||||
line[length - 1] = '\0';
|
line[length - 1] = '\0';
|
||||||
|
|||||||
Reference in New Issue
Block a user