1
0
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:
Bruno Haible
2002-11-05 12:28:40 +00:00
parent 8797dd362b
commit 5de859e402
14 changed files with 387 additions and 190 deletions

View File

@@ -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.

View File

@@ -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)

View File

@@ -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,16 +189,20 @@ 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)
fewest_collisions = collisions; break;
if (option[DEBUG]) if (keyword == curr)
fprintf (stderr, "- resolved after %d iterations", total_iterations - i); {
return 0; fewest_collisions = collisions;
} if (option[DEBUG])
fprintf (stderr, "- resolved after %d iterations", total_iterations - i);
return 0;
}
}
} }
/* Restore original values, no more tries. */ /* Restore original values, no more tries. */
@@ -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); {
break; KeywordExt *ptrkw = ptr->first();
}
if (ptrkw->hash_value == currkw->hash_value)
{
change (ptrkw, currkw);
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))) {
if (option[DUP]) /* Keep track of this number... */ unsigned int hashcode = hash (curr->first());
total_duplicates++; if (collision_detector->set_bit (hashcode))
else /* Yow, big problems. we're outta here! */
{ {
fprintf (stderr, "\nInternal error, duplicate value %d:\n" if (option[DUP]) /* Keep track of this number... */
"try options -D or -r, or use new key positions.\n\n", hash (curr)); total_duplicates++;
return 1; else /* Yow, big problems. we're outta here! */
{
fprintf (stderr,
"\nInternal error, duplicate value %d:\n"
"try options -D or -r, or use new key positions.\n\n",
hashcode);
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

View File

@@ -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);

View File

@@ -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;
} }

View File

@@ -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

View File

@@ -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);
for (ptr = head; ptr->rest(); ptr = ptr->rest())
{ {
set_determined (ptr); set_determined (ptr->first());
if (already_determined (ptr->next)) if (!already_determined (ptr->rest()->first()))
continue;
else
{ {
List_Node *trail_ptr = ptr->next; KeywordExt_List *trail_ptr = ptr->rest();
List_Node *run_ptr = trail_ptr->next; KeywordExt_List *run_ptr = trail_ptr->rest();
for (; run_ptr; run_ptr = trail_ptr->next) 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... */

View File

@@ -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
View 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
View 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

View File

@@ -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. */

View File

@@ -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. */

View File

@@ -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)

View File

@@ -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';