|
|
DataMuseum.dkPresents historical artifacts from the history of: Rational R1000/400 Tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Rational R1000/400 Tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: B T
Length: 52687 (0xcdcf)
Types: TextFile
Names: »B«
└─⟦180fe333a⟧ Bits:30000405 8mm tape, Rational 1000, SW CATALOG, 10_20_0
└─⟦180fe333a⟧ Bits:30000537 8mm tape, Rational 1000, SW Catalog 10_20_0
└─⟦5cb1d1d7f⟧ »DATA«
└─⟦3b1ee7bd8⟧
└─⟦this⟧
----------------------------------------------------------------
--
-- Abstract : This unit contains the actual code for the
-- : various procedures and functions contained
-- : within package DICTIONARY_MANAGER. Each
-- : section is documented separately.
-- :
-- : The purpose of the package is to provide the
-- : necessary management of the data structures
-- : used in the Spelling Corrector tool.
-- :
----------------------------------------------------------------
with Machine_Dependencies, Character_Set, Token_Definition,
-- UNCHECKED_DEALLOCATION,
Terminal_Interface;
package body Dictionary_Manager is
--A pointer to the head of the dictionary list
Dictionary_Search_List : Dictionary_Ptr;
--A pointer to an incomplete dictionary left by a storage error
--during creation. To be used for deallocation when available.
Deallocation : Dictionary_Ptr;
--Generic instaniations to be used when UNCHECKED_DEALLOCATION is available
--procedure FREE is new UNCHECKED_DEALLOCATION(WORD_RECORD,WORD_RECORD_PTR);
--procedure FREE_DICT is new UNCHECKED_DEALLOCATION
-- (DICTIONARY_RECORD,DICTIONARY_PTR);
--Establishes the length of a word(token)
Token_Length_Range : constant Positive := Token_Definition.Token_Length;
--Establishes the minimum length of a word in the dictionary. This length
--is also necessary for the hashing function and the correction algorithm.
Necessary_Length : constant Natural := 2;
--A subtype to allow passing of the length of a token as a parameter
subtype Token_Length_Type is Positive range 1 .. Token_Length_Range;
--Declarations necessary to create the global variables needed in the
--INITIATOR, NEXT_WORD and MORE subprograms.
Count : Natural;
Index : Hash_Bucket_Type;
Word_Ptr : Word_Record_Ptr;
Init_Word : Token_Definition.Token_Type;
Temp_Ptr : Dictionary_Ptr;
----------------------------------------------------------------
--
-- Abstract : This function provides a boolean value of true
-- : if a particular dictionary structure has been
-- : altered since it was loaded from a file.
--
----------------------------------------------------------------
--
-- Parameters : DICTIONARY - An in parameter consisting of an
-- : access value to the structure in
-- : question.
--
----------------------------------------------------------------
function Alter (Dictionary : in Dictionary_Ptr) return Boolean is
begin
if Dictionary = null then
raise Dictionary_Error;
else
return Dictionary.Alter_Flag;
end if;
end Alter;
----------------------------------------------------------------
--
-- Abstract : This function provides access to the Acronym
-- : dictionary if that dictionary exists. If the
-- : dictionary does not exist a null access type
-- : is returned.
--
----------------------------------------------------------------
--
-- Parameters : An access type to a Dictionary Record is
-- : returned by this function.
--
----------------------------------------------------------------
function Get_Acronym_Dictionary return Dictionary_Ptr is
begin
if Dictionary_Search_List = null then
return null;
elsif Dictionary_Search_List.Dictionary_Name = Acronym then
return Dictionary_Search_List;
elsif ((Dictionary_Search_List.Dictionary_Name = Master) and
(Dictionary_Search_List.Next_Dictionary /= null)) and then
(Dictionary_Search_List.Next_Dictionary.Dictionary_Name =
Acronym) then
return Dictionary_Search_List.Next_Dictionary;
else
return null;
end if;
end Get_Acronym_Dictionary;
----------------------------------------------------------------
--
-- Abstract : This function provides and access type to the
-- : Master dictionary if the dictionary exists. If
-- : the unit does not exist a null access type is
-- : returned.
--
----------------------------------------------------------------
--
-- Parameters : An access type to a Dictionary record is re-
-- : turned by this function.
--
----------------------------------------------------------------
function Get_Master_Dictionary return Dictionary_Ptr is
begin
if Dictionary_Search_List = null then
return Dictionary_Search_List;
elsif Dictionary_Search_List.Dictionary_Name = Master then
return Dictionary_Search_List;
else
return null;
end if;
end Get_Master_Dictionary;
----------------------------------------------------------------
--
-- Abstract : This function provides the numeric value
-- : to provide access to one cell of an array of
-- : access types. The algorithm used was obtained
-- : from "Communications of the ACM", Volume 23,
-- : Number 12, pp. 681. This information is contained
-- : in an article by James L. Peteson, "Computer
-- : Programs for Detecting and Correcting Spelling
-- : Errors".
--
----------------------------------------------------------------
--
-- Parameters : FIRST_CHARACTER - The first character of the
-- : word to be hashed.
-- : SECOND_CHARACTER - The second character of the
-- : word to be hashed.
-- : TOKEN_LENGTH - The length of the word.
-- : - A subtype of positive numbers
-- : returned by the hashing function.
-- :
----------------------------------------------------------------
function Hash_Value (First_Character : in Character;
Second_Character : in Character;
Token_Length : in Token_Length_Type)
return Hash_Bucket_Type is
First : Natural := Character'Pos (First_Character);
Second : Natural := Character'Pos (Second_Character);
Hold : Token_Length_Type;
Holder : Hash_Bucket_Type;
begin
if not (Character_Set.Is_Alpha_Numeric (First_Character) and
(Character_Set.Is_Alpha_Numeric (Second_Character) or
Token_Definition.Is_Special_Char (Second_Character))) then
raise Bad_Word;
else
--Convert to lower case
if (First_Character >= 'A') and (First_Character <= 'Z') then
First := Character'Pos
(Character_Set.To_Lower (First_Character));
end if;
if (Second_Character >= 'A') and (Second_Character <= 'Z') then
Second := Character'Pos
(Character_Set.To_Lower (Second_Character));
end if;
--The hashing function starts here
if (Token_Length - 2) >= 9 then
Hold := 9;
else
Hold := Token_Length;
end if;
return Hash_Bucket_Type
(((10 * ((First * 26) + Second) + Hold) rem 101) + 1);
end if;
end Hash_Value;
----------------------------------------------------------------
--
-- Abstract : This procedure disables a dictionary. This
-- : disablement is accomplished by changing a
-- : boolean value contained in the Dictionary
-- : record to false.
--
----------------------------------------------------------------
--
-- Parameters : DICTIONARY - An access type to a Dictionary
-- : record passed from the calling
-- : routine to facilitate access to
-- : the structure.
--
----------------------------------------------------------------
procedure Disable (Dictionary : in Dictionary_Ptr) is
begin
if Dictionary = null then
raise Dictionary_Error;
else
Dictionary.Enabled := False;
end if;
end Disable;
----------------------------------------------------------------
--
-- Abstract : This procedure enables a dictionary. This is
-- : accomplished by setting a boolean value contained
-- : in the dictionary record to true.
-- :
--
----------------------------------------------------------------
--
-- Parameters : DICTIONARY - An access type to a Dictionary
-- : record passed from the calling
-- : routine to facilitate access of
-- : the structure.
--
----------------------------------------------------------------
procedure Enable_Dictionary (Dictionary : in Dictionary_Ptr) is
begin
if Dictionary = null then
raise Dictionary_Error;
else
Dictionary.Enabled := True;
end if;
end Enable_Dictionary;
----------------------------------------------------------------
--
-- Abstract : This procedure creates a dictionary. The
-- : dictionary is initialized and data from a
-- : file is entered into the structure.
-- :
--
----------------------------------------------------------------
--
-- Parameters : DICTIONARY_KIND - A designation of the type of
-- : dictionary to be created.
-- :
-- : DICTIONARY_IN - An access type used as an out
-- : parameter for later access to the
-- : structure.
-- :
-- : FILENAME - A STRING variable passed as an
-- : in parameter which contains the
-- : name of the file which stores the
-- : data to be loaded in to the in-
-- : ternal dictionary structure.
--
----------------------------------------------------------------
procedure Create_Dictionary (Dictionary_Kind : in Dictionary_Type;
Dictionary_In : out Dictionary_Ptr;
Filename : in String) is
Temp_Dict : Dictionary_Ptr := null;
Dictionary : Dictionary_Ptr;
--Declarations used in UNCHECKED_DEALLOCATION(commented out)
-- HOLD_PTR : WORD_RECORD_PTR;
-- REC_PTR : WORD_RECORD_PTR;
----------------------------------------------------------------
--
-- Abstract : This procedure initializes the new dictionary
-- : structure. The actual creation of a dictionary
-- : node takes place in this procedure.
-- :
-- : This procedure is internal to CREATE_DICTIONARY
-- : and uses variables declared in that procedure.
--
----------------------------------------------------------------
procedure Init_Dict is
begin
Dictionary := new Dictionary_Record;
Dictionary.Dictionary_Name := Dictionary_Kind;
end Init_Dict;
----------------------------------------------------------------
--
-- Abstract : This procedure loads the contents of a file into
-- : a dictionary data structure.
-- :
--
----------------------------------------------------------------
--
-- Parameters : This procedure is internal to CREATE_DICTIONARY
-- : and uses variables declared in that procedure.
--
----------------------------------------------------------------
--
-- Algorithm : The algorithm is to read from a file while there
-- : is data in the file and to create an array of linked lists
-- : of the data which is indexed by the value returned
-- : by the HASH_VALUE function.
--
----------------------------------------------------------------
procedure Load_Dict is
Input : String (1 .. 80);
This_Word : Token_Definition.Token_String;
Word_Length : Token_Length_Type;
Temp_Ptr : Word_Record_Ptr := null;
Number : Natural;
From_Dictionary : Text_Io.File_Type;
--There is the possibility of running out of storage and thus raising
--a STORAGE_ERROR in this procedure. There is no way of knowing how
--much space will be required for the dictionaries used. The dictionary
--being created will be left intact at the point of the STORAGE_ERROR.
--The dictionary may be accessed by the access variable DEALLOCATION.
--When UNCHECKED_DEALLOCATION is included the code for deallocating the
--dictionary is included in the exception handler of this routine.
begin
--A test variable to be used to count the number of words loaded into the
--data structure.
Word_Counter := 0;
Text_Io.Open (File => From_Dictionary,
Mode => Text_Io.In_File,
Name => Filename,
Form => "");
--beginning of the actual loading algorithm
while not (Text_Io.End_Of_File (From_Dictionary)) loop
loop
--This loop passes over words of less than necessary length
Text_Io.Get_Line (From_Dictionary, Input, Number);
if (Number <= Token_Length_Range) and
(Number >= Necessary_Length) then
This_Word := Input (1 .. Token_Length_Range);
exit;
end if;
end loop;
Word_Length := Token_Length_Type (Number);
--The words are counted at this point.
Word_Counter := Word_Counter + 1;
if Dictionary.Hash_Table
(Hash_Value (This_Word (1), This_Word (2), Word_Length)) =
null then
Dictionary.Hash_Table
(Hash_Value (This_Word (1), This_Word (2),
Word_Length)) :=
new Word_Record'((This_Word, Word_Length), null);
else
Temp_Ptr := Dictionary.Hash_Table
(Hash_Value (This_Word (1), This_Word (2),
Word_Length));
while Temp_Ptr.Next /= null loop
Temp_Ptr := Temp_Ptr.Next;
end loop;
Temp_Ptr.Next :=
new Word_Record'((This_Word, Word_Length), null);
end if;
end loop;
Text_Io.Close (From_Dictionary);
exception
when Storage_Error =>
Text_Io.Close (From_Dictionary);
Deallocation := Dictionary;
--Code to deallocate storage, to be used when UNCHECKED_DEALLOCATION is
--included.
-- for INDEX in 1..MAX_HASH_BUCKETS loop
-- REC_PTR := DICTIONARY.HASH_TABLE(INDEX);
-- while REC_PTR /= null loop
-- HOLD_PTR := REC_PTR.NEXT;
-- FREE(REC_PTR);
-- REC_PTR := HOLD_PTR;
-- end loop;
-- end loop;
-- FREE_DICT(DICTIONARY);
raise Storage_Error;
end Load_Dict;
----------------------------------------------------------------
--
-- Abstract : This procedure places a dictionary in its
-- : proper place in the Dictionary Search List.
-- : The ordering is on the basis of Master, Acronym,
-- : and the various User dictonaries.
--
----------------------------------------------------------------
--
-- Parameters : This routine is internal to CREATE_DICTIONARY
-- : and uses the variables associated with that
-- : routine.
--
----------------------------------------------------------------
procedure Insert_Dict is
begin
if Dictionary_Search_List = null then
Dictionary_Search_List := Dictionary;
elsif Dictionary.Dictionary_Name = Master then
Dictionary.Next_Dictionary := Dictionary_Search_List;
Dictionary_Search_List := Dictionary;
elsif Dictionary.Dictionary_Name = Acronym and then
Dictionary_Search_List.Dictionary_Name = Master then
Dictionary.Next_Dictionary :=
Dictionary_Search_List.Next_Dictionary;
Dictionary_Search_List.Next_Dictionary := Dictionary;
else
Temp_Dict := Dictionary_Search_List;
while Temp_Dict.Next_Dictionary /= null loop
Temp_Dict := Temp_Dict.Next_Dictionary;
end loop;
Temp_Dict.Next_Dictionary := Dictionary;
end if;
end Insert_Dict;
--This is the main routine of CREATE_DICTIONARY
begin
--The check for the existence of a Master or Acronym dictionary when
--the same type of dictionary exists.
if Dictionary_Search_List /= null then
if ((Dictionary_Kind = Master) and
(Dictionary_Search_List.Dictionary_Name = Master)) or
((Dictionary_Kind = Acronym) and
(Dictionary_Search_List.Dictionary_Name = Acronym)) or
(((Dictionary_Kind = Acronym) and
(Dictionary_Search_List.Next_Dictionary /= null)) and then
(Dictionary_Search_List.Next_Dictionary.Dictionary_Name =
Acronym)) then
raise Dictionary_Error;
end if;
end if;
--Start of the actual routine
Init_Dict;
Terminal_Interface.New_Line;
Terminal_Interface.Put ("*** Creating a ");
Terminal_Interface.Put
(Dictionary_Manager.Dictionary_Type'Image (Dictionary_Kind));
Terminal_Interface.Put (" dictionary from ");
Terminal_Interface.Put (Filename);
Terminal_Interface.Put_Line (" ***");
Terminal_Interface.New_Line;
Load_Dict;
Insert_Dict;
Enable_Dictionary (Dictionary);
Dictionary_In := Dictionary;
exception
when Text_Io.Device_Error =>
raise Hardware_Failure;
end Create_Dictionary;
----------------------------------------------------------------
--
-- Abstract : This procedure provides a listing of the
-- : data contained in the internal dictionary
-- : structure. This data is listed to a file.
-- :
--
----------------------------------------------------------------
--
-- Parameters : DICTIONARY - An access variable to a dictionary
-- : record. This variable provides
-- : the address of the dictionary to be
-- : listed.
-- : FILENAME - A STRING variable used to access the
-- : file to which the dictionary is listed.
--
----------------------------------------------------------------
--
-- Algorithm : The algorithm used is to output from each dictionary
-- : cell the information contained within the linked
-- : list headed by that cell.
--
----------------------------------------------------------------
procedure List_Dictionary
(Dictionary : in Dictionary_Ptr; Filename : in String) is
Token : Word_Record_Ptr;
List_Name : Text_Io.File_Type;
Fail : Boolean;
begin
Fail := False;
begin
Text_Io.Create (File => List_Name,
Mode => Text_Io.Out_File,
Name => Filename,
Form => "");
exception
when others =>
Fail := True;
end;
if Fail then
Text_Io.Open (File => List_Name,
Mode => Text_Io.Out_File,
Name => Filename,
Form => "");
end if;
--Start of the actual list dictionary
if (Dictionary = null) or else (not (Dictionary.Enabled)) then
raise Dictionary_Error;
else
--The start of the outer loop
for Index in 1 .. Max_Hash_Buckets loop
Token := Dictionary.Hash_Table (Index);
--The start of the inner loop
while Token /= null loop
Text_Io.Put_Line (List_Name,
Token.Token.Word (1 ..
Token.Token.Length));
Token := Token.Next;
end loop;
end loop;
Text_Io.Close (List_Name);
end if;
exception
when Text_Io.Device_Error =>
raise Hardware_Failure;
end List_Dictionary;
----------------------------------------------------------------
--
-- Abstract : This procedure provides a listing of the data
-- : contained in the internal dictionary to the
-- : terminal.
-- :
--
----------------------------------------------------------------
--
-- Parameters : DICTIONARY - An in parameter used to access the
-- : dictionary structure to be listed.
--
----------------------------------------------------------------
--
-- Algorithm : This procedure is an overload of the previous
-- : LIST_DICTIONARY procedure. The algorithm is
-- : the same with output to the terminal.
--
----------------------------------------------------------------
procedure List_Dictionary (Dictionary : in Dictionary_Ptr) is
Token : Word_Record_Ptr;
begin
if (Dictionary = null) or else (not (Dictionary.Enabled)) then
raise Dictionary_Error;
else
for Index in 1 .. Max_Hash_Buckets loop
Token := Dictionary.Hash_Table (Index);
while Token /= null loop
Terminal_Interface.Put_Line
(Token.Token.Word (1 .. Token.Token.Length));
Token := Token.Next;
end loop;
end loop;
end if;
exception
when Terminal_Interface.Device_Error =>
raise Hardware_Failure;
end List_Dictionary;
----------------------------------------------------------------
--
-- Abstract : This procedure provides the ability to delete
-- : a word from an existing dictionary. The
-- : dictionary must exist and be enabled.
-- :
--
----------------------------------------------------------------
--
-- Parameters : TOKEN - A record containing the word to be
-- : deleted and the length of the word.
-- : FROM_DICTIONARY - An access variable disignating
-- : the dictionary structure from which
-- : the word is to be deleted.
--
----------------------------------------------------------------
--
-- Algorithm : Function HASH_VALUE is used to determine the proper
-- : cell of the dictionary. A linear search, comparing
-- : on the length of the words, is used. When the length
-- : is matched a compare of the words is performed. If
-- : the word is found it is deleted. If the word is not
-- : found the list is searched from this point until a
-- : new length match is found or until the end of the list
-- : is found. An exception is returned if the word can-
-- : not be matched in the dictionary.
--
----------------------------------------------------------------
procedure Delete_Word (Token : in Token_Definition.Token_Type;
From_Dictionary : in Dictionary_Ptr) is
Temp_Word_Record_Ptr : Word_Record_Ptr;
Save_Word_Record_Ptr : Word_Record_Ptr;
Word : Token_Definition.Token_String := Token.Word;
Length : Natural := Token.Length;
begin
--A check for improper word length
if Token.Length < Necessary_Length then
raise Bad_Word;
end if;
--A check for a valid dictionary structure
if (From_Dictionary = null) or else (not (From_Dictionary.Enabled)) then
raise Dictionary_Error;
else
--The actual search and delete algorithm begins here
Temp_Word_Record_Ptr :=
From_Dictionary.Hash_Table
(Hash_Value (Word (1), Word (2), Length));
Save_Word_Record_Ptr := Temp_Word_Record_Ptr;
if Temp_Word_Record_Ptr /= null then
loop
--The length check
while (Temp_Word_Record_Ptr.Token.Length /= Length) and
(Temp_Word_Record_Ptr.Next /= null) loop
Save_Word_Record_Ptr := Temp_Word_Record_Ptr;
Temp_Word_Record_Ptr := Temp_Word_Record_Ptr.Next;
end loop;
--The word match
if Temp_Word_Record_Ptr.Token.Word
(1 .. Temp_Word_Record_Ptr.Token.Length) =
Word (1 .. Length) then
--The deletion
if Save_Word_Record_Ptr = Temp_Word_Record_Ptr then
From_Dictionary.Hash_Table
(Hash_Value (Word (1), Word (2), Length)) :=
Save_Word_Record_Ptr.Next;
--Code to free storage not used upon deletion.
-- FREE(SAVE_WORD_RECORD_PTR);
From_Dictionary.Alter_Flag := True;
exit;
else
Save_Word_Record_Ptr.Next :=
Temp_Word_Record_Ptr.Next;
--Code to free storage not used upon deletion.
-- FREE(TEMP_WORD_RECORD_PTR);
From_Dictionary.Alter_Flag := True;
exit;
end if;
elsif Temp_Word_Record_Ptr.Next = null then
raise Word_Not_Valid;
else
Save_Word_Record_Ptr := Temp_Word_Record_Ptr;
Temp_Word_Record_Ptr := Temp_Word_Record_Ptr.Next;
end if;
end loop;
else
--The unfound word exception raised
raise Word_Not_Valid;
end if;
end if;
end Delete_Word;
----------------------------------------------------------------
--
-- Abstract : This procedure provides the ability to insert
-- : a word into an existing dictionary. The
-- : dictionary must be enabled and must exist.
-- :
--
----------------------------------------------------------------
--
-- Parameters : TOKEN - An in parameter containing the word
-- : to be inserted into the dictionary
-- : structure.
-- : INTO_DICTIONARY - The access variable containing
-- : the address of the dictionary structure.
--
----------------------------------------------------------------
--
-- Algorithm : The algorithm used in this procedure is similar to
-- : the algorithm used in the DELETE_WORD procedure.
-- : The search is the same. Upon location of the word
-- : an exit is performed in order not to duplicate the
-- : word. If the word is not located in the particular
-- : cell's list it is appended to the end of the list.
--
----------------------------------------------------------------
procedure Insert_Word (Token : in Token_Definition.Token_Type;
Into_Dictionary : in Dictionary_Ptr) is
Temp_Word_Record_Ptr : Word_Record_Ptr;
Save_Word_Record_Ptr : Word_Record_Ptr;
Word : Token_Definition.Token_String := Token.Word;
Length : Natural := Token.Length;
begin
--A check for improper word length
if Token.Length < Necessary_Length then
raise Bad_Word;
end if;
--A check for an invalid dictionary structure
if (Into_Dictionary = null) or else (not (Into_Dictionary.Enabled)) then
raise Dictionary_Error;
else
--The actual insertion routine begins here
Temp_Word_Record_Ptr :=
Into_Dictionary.Hash_Table
(Hash_Value (Word (1), Word (2), Length));
if Temp_Word_Record_Ptr = null then
Into_Dictionary.Hash_Table (Hash_Value
(Word (1), Word (2), Length)) :=
new Word_Record'((Word, Length), null);
Into_Dictionary.Alter_Flag := True;
else
loop
--The check for the length match
while (Temp_Word_Record_Ptr.Token.Length /= Length) and
(Temp_Word_Record_Ptr.Next /= null) loop
Temp_Word_Record_Ptr := Temp_Word_Record_Ptr.Next;
end loop;
--The check for the word match
if Temp_Word_Record_Ptr.Token.Word
(1 .. Temp_Word_Record_Ptr.Token.Length) =
Word (1 .. Length) then
--The exit if the word is found
exit;
elsif
--The insertion of the word
Temp_Word_Record_Ptr.Next = null then
Temp_Word_Record_Ptr.Next :=
new Word_Record'((Word, Length), null);
Into_Dictionary.Alter_Flag := True;
exit;
else
Temp_Word_Record_Ptr := Temp_Word_Record_Ptr.Next;
end if;
end loop;
end if;
end if;
end Insert_Word;
----------------------------------------------------------------
--
-- Abstract : This procedure verifies that the in parameters
-- : are valid dictionary structures. This procedure
-- : is called by both the MERGE_DICTIONARY and the
-- : DELETE_DICTIONARY procedures.
--
----------------------------------------------------------------
--
-- Parameters : DICTIONARY - The access variable containing
-- : the address of the dictionary structure to
-- : be checked.
--
----------------------------------------------------------------
procedure Check_Dictionary (Dictionary : in Dictionary_Ptr) is
Hold_Dictionary_Ptr : Dictionary_Ptr;
Temp_Dictionary_Ptr : Dictionary_Ptr;
begin
Hold_Dictionary_Ptr := null;
Temp_Dictionary_Ptr := Dictionary_Search_List;
while (Dictionary /= Temp_Dictionary_Ptr) and
(Temp_Dictionary_Ptr /= null) loop
Hold_Dictionary_Ptr := Temp_Dictionary_Ptr;
Temp_Dictionary_Ptr := Temp_Dictionary_Ptr.Next_Dictionary;
end loop;
if Temp_Dictionary_Ptr = null then
raise Dictionary_Error;
end if;
end Check_Dictionary;
----------------------------------------------------------------
--
-- Abstract : A procedure to remove a dictionary from the
-- : DICTIONARY_SEARCH_LIST. This procedure is called
-- : by both the MERGE_DICTIONARY and the DELETE_DICTIONARY
-- : procedures.
--
----------------------------------------------------------------
--
-- Parameters : DICTIONARY - The access variable which addresses
-- : the dictionary structure to be removed.
--
----------------------------------------------------------------
procedure Change_List (Dictionary : in Dictionary_Ptr) is
Temp_Dictionary_Ptr : Dictionary_Ptr;
Hold_Dictionary_Ptr : Dictionary_Ptr;
begin
Hold_Dictionary_Ptr := null;
Temp_Dictionary_Ptr := Dictionary_Search_List;
while (Dictionary /= Temp_Dictionary_Ptr) and
(Temp_Dictionary_Ptr /= null) loop
Hold_Dictionary_Ptr := Temp_Dictionary_Ptr;
Temp_Dictionary_Ptr := Temp_Dictionary_Ptr.Next_Dictionary;
end loop;
if Hold_Dictionary_Ptr = null then
Dictionary_Search_List := Dictionary_Search_List.Next_Dictionary;
elsif Temp_Dictionary_Ptr = null then
null;
else
Hold_Dictionary_Ptr.Next_Dictionary :=
Temp_Dictionary_Ptr.Next_Dictionary;
end if;
end Change_List;
----------------------------------------------------------------
--
-- Abstract : This procedure allows for the deletion of a
-- : dictionary pointer from the search list. This
-- : has the effect of deleting a dictionary structure.
-- : This procedure is called from outside of the package.
--
----------------------------------------------------------------
--
-- Parameters : DICTIONARY - An in parameter of an access type
-- : which is the address of the structure
-- : to be removed from the search list.
--
----------------------------------------------------------------
procedure Delete_Dictionary (Dictionary : in out Dictionary_Ptr) is
begin
if (Dictionary = null) or (Dictionary_Search_List = null) then
raise Dictionary_Error;
else
Check_Dictionary (Dictionary);
Change_List (Dictionary);
--Code to reclaim storage when UNCHECKED_DEALLOCATION is implemented.
-- for INDEX in 1..MAX_HASH_BUCKETS loop
-- REC_PTR := DICTIONARY.HASH_TABLE(INDEX);
-- while REC_PTR /= null loop
-- HOLD_PTR := REC_PTR.NEXT;
-- FREE(REC_PTR);
-- REC_PTR := HOLD_PTR;
-- end loop;
-- end loop;
-- FREE_DICT(DICTIONARY);
Dictionary := null;
end if;
end Delete_Dictionary;
----------------------------------------------------------------
--
-- Abstract : This procedure provides the function of finding
-- : a token if it exists in the enabled dictionaries.
-- :
-- :
--
----------------------------------------------------------------
--
-- Parameters : IN_DICTIONARY - An out parameter, access type
-- : to the dictionary structure containing the
-- : word, if it is located.
-- : WORD _ The word to be searched for and its length.
-- : FOUND - A BOOLEAN value returned to
-- : indicate the status of the search.
--
----------------------------------------------------------------
--
-- Algorithm : The algorithm used searches for a length match
-- : of the words. If the length is matched the word
-- : is compared and the appropriate actions taken. If
-- : the word is not found the rest of the list is searched
-- : and each enabled dictionary is searched in its turn.
-- : If no match is obtained the BOOLEAN is returned false
-- : and the IN_DICTIONARY variable is returned null.
--
----------------------------------------------------------------
procedure Token_Is_Found (In_Dictionary : out Dictionary_Ptr;
Word : in Token_Definition.Token_Type;
Found : out Boolean) is
Structure_Ptr : Dictionary_Ptr := Dictionary_Search_List;
Element_Ptr : Word_Record_Ptr;
Token : Token_Definition.Token_String := Word.Word;
Token_Length : Natural := Word.Length;
begin
--A check for improper word length
if Word.Length < Necessary_Length then
raise Bad_Word;
end if;
--The dictionary list loop
Search:
while Structure_Ptr /= null loop
if Structure_Ptr.Enabled then
Element_Ptr := Structure_Ptr.Hash_Table
(Hash_Value (Token (1), Token (2),
Token_Length));
if Element_Ptr /= null then
--The cell list search loop
loop
--The length compare
while (Element_Ptr.Next /= null) and
(Element_Ptr.Token.Length /=
Token_Length) loop
Element_Ptr := Element_Ptr.Next;
end loop;
--The word compare
if Element_Ptr.Token.Word
(1 .. Element_Ptr.Token.Length) =
(Token (1 .. Token_Length)) then
Found := True;
In_Dictionary := Structure_Ptr;
exit Search;
elsif Element_Ptr.Next = null then
exit;
else
Element_Ptr := Element_Ptr.Next;
end if;
end loop;
end if;
end if;
--To the next dictionary structure
Structure_Ptr := Structure_Ptr.Next_Dictionary;
end loop Search;
if Structure_Ptr = null then
--The not found actions
Found := False;
In_Dictionary := null;
end if;
end Token_Is_Found;
----------------------------------------------------------------
--
-- Abstract : This procedure provides for the merging of
-- : two dictionaries that are resident in memory.
-- : A third dictionary is created and its address
-- : returned to the calling procedure.
--
----------------------------------------------------------------
--
-- Parameters : DICTIONARY_A - An in out parameter with the address
-- : of the dictionary structure to be
-- : merged.
-- : DICTIONARY_B - A second in out parameter with a
-- : structure address.
-- : INTO_DICTIONARY - An out parameter which will contain
-- : the address of the output of the merge.
--
----------------------------------------------------------------
--
-- Algorithm : The A and B dictionaries are merged into a third
-- : Structure. All words contained in every cell of
-- : B are in turn matched against every word in the
-- : corresponding cell of A. If the word is matched
-- : it is not added to the new structure. If the word is not
-- : matched it is placed in the new structure. At the
-- : end of each cell's list comparison the cell list
-- : from the A dictionary is appended to the end of the
-- : new structure's corresponding cell list. At the time
-- : of this appending only the words not found in the A
-- : list are contained in the new structure. The addition
-- : of the A list completes the merge of a particular cell.
-- : This process is repeated until all cells are merged.
--
----------------------------------------------------------------
procedure Merge_Dictionary (Dictionary_A : in out Dictionary_Ptr;
Dictionary_B : in out Dictionary_Ptr;
Into_Dictionary : out Dictionary_Ptr) is
New_List_Ptr : Word_Record_Ptr;
A_Temp_Ptr : Word_Record_Ptr;
B_Temp_Ptr : Word_Record_Ptr;
New_Dictionary : Dictionary_Ptr;
Hold_Dictionary_Ptr : Dictionary_Ptr;
begin
--The check for a valid dictionary
if ((Dictionary_A = null) or (Dictionary_B = null)) or else
((Dictionary_A.Dictionary_Name = Master) or
(Dictionary_B.Dictionary_Name = Acronym) or
(Dictionary_Search_List = null) or
(Dictionary_A.Enabled = False) or (Dictionary_B.Enabled = False) or
(Dictionary_A.Dictionary_Name = Acronym) or
(Dictionary_B.Dictionary_Name = Master)) then
raise Dictionary_Error;
end if;
--The allocation of the new dictionary structure, STORAGE_ERROR
--could be raised at this point.
New_Dictionary := new Dictionary_Record;
New_Dictionary.Dictionary_Name := User;
New_Dictionary.Enabled := True;
Check_Dictionary (Dictionary_A);
Check_Dictionary (Dictionary_B);
--The array cell loop
for Index in 1 .. Max_Hash_Buckets loop
B_Temp_Ptr := Dictionary_B.Hash_Table (Index);
New_List_Ptr := New_Dictionary.Hash_Table (Index);
--The B dictionary cell loop
while B_Temp_Ptr /= null loop
A_Temp_Ptr := Dictionary_A.Hash_Table (Index);
--The A dictionary cell loop
while A_Temp_Ptr /= null loop
--The word compare
if (B_Temp_Ptr.Token.Length =
A_Temp_Ptr.Token.Length) and then
(B_Temp_Ptr.Token.Word (1 .. B_Temp_Ptr.Token.Length) =
A_Temp_Ptr.Token.Word (1 ..
A_Temp_Ptr.Token.Length)) then
--The exit if found
exit;
else
A_Temp_Ptr := A_Temp_Ptr.Next;
end if;
end loop;
--The insertion into the new list
if A_Temp_Ptr = null then
if New_Dictionary.Hash_Table (Index) = null then
New_Dictionary.Hash_Table (Index) := B_Temp_Ptr;
New_List_Ptr := B_Temp_Ptr;
else
New_List_Ptr.Next := B_Temp_Ptr;
New_List_Ptr := New_List_Ptr.Next;
end if;
end if;
B_Temp_Ptr := B_Temp_Ptr.Next;
end loop;
--The appending of A to the end of the list
if New_Dictionary.Hash_Table (Index) = null then
New_Dictionary.Hash_Table (Index) :=
Dictionary_A.Hash_Table (Index);
else
New_List_Ptr.Next := Dictionary_A.Hash_Table (Index);
end if;
end loop;
--Deletion of the merged dictionary structures from the search list
Change_List (Dictionary_A);
Change_List (Dictionary_B);
--The addition of the output structure to the search list
if Dictionary_Search_List /= null then
Hold_Dictionary_Ptr := Dictionary_Search_List;
while Hold_Dictionary_Ptr.Next_Dictionary /= null loop
Hold_Dictionary_Ptr := Hold_Dictionary_Ptr.Next_Dictionary;
end loop;
Hold_Dictionary_Ptr.Next_Dictionary := New_Dictionary;
else
Dictionary_Search_List := New_Dictionary;
end if;
Dictionary_A := null;
Dictionary_B := null;
Into_Dictionary := New_Dictionary;
end Merge_Dictionary;
----------------------------------------------------------------
--
-- Abstract : This function returns a positive BOOLEAN value
-- : if a counter initiated in the procedure INITIATOR
-- : is greater than zero. This value is used to control
-- : the number of possible corrections output.
--
----------------------------------------------------------------
function More return Boolean is
begin
return Count > 0;
end More;
----------------------------------------------------------------
--
-- Abstract : This procedure is used to return a word to the
-- : calling routine. These words are obtained from
-- : the enabled dictionary structures and resemble
-- : a word that is to be corrected.
--
----------------------------------------------------------------
--
-- Parameters : WORD - An out parameter containing the possible
-- : correctly spelled word and its length.
--
----------------------------------------------------------------
--
-- Algorithm : The dictionary structure cells are searched for
-- : closely matching words of the same length
-- : until there are no more words available or the
-- : function MORE returns a negative value.
-- : The index of the cells containing the possible
-- : correct words is a global variable and is
-- : initialized in procedure INITIATOR with a value
-- : obtained from the hashing function HASH_VALUE.
--
----------------------------------------------------------------
procedure Next_Word (Word : out Token_Definition.Token_Type) is
begin
loop
--The search for the possible word
if (Word_Ptr /= null) and (Count > 0) and (Temp_Ptr.Enabled) then
if (Word_Ptr.Token.Length = Init_Word.Length) and then
((Word_Ptr.Token.Word (1) = Init_Word.Word (1)) and then
(Word_Ptr.Token.Word (2) = Init_Word.Word (2))) then
--The return of the possible correct word
Word := Word_Ptr.Token;
Count := Count - 1;
Word_Ptr := Word_Ptr.Next;
exit;
else
Word_Ptr := Word_Ptr.Next;
end if;
elsif
--The move to the next dictionary structure
((Temp_Ptr.Next_Dictionary /= null) and
(Count > 0)) and then
(Temp_Ptr.Next_Dictionary.Enabled) then
Temp_Ptr := Temp_Ptr.Next_Dictionary;
Word_Ptr := Temp_Ptr.Hash_Table (Index);
elsif ((Temp_Ptr.Next_Dictionary /= null) and (Count > 0)) then
while (Temp_Ptr.Next_Dictionary /= null) and then
(not (Temp_Ptr.Next_Dictionary.Enabled)) loop
Temp_Ptr := Temp_Ptr.Next_Dictionary;
end loop;
if Temp_Ptr.Next_Dictionary = null then
Count := 0;
raise No_More_Words;
else
Temp_Ptr := Temp_Ptr.Next_Dictionary;
Word_Ptr := Temp_Ptr.Hash_Table (Index);
end if;
else
--The exception raised when there are no more words available
Count := 0;
raise No_More_Words;
end if;
end loop;
end Next_Word;
----------------------------------------------------------------
--
-- Abstract : This procedure initializes the search for like
-- : words to be returned to the spelling corrector.
-- : The variables are global to package DICTIONARY_
-- : MANAGER and are thus available for the routines
-- : MORE and NEXT_WORD to use.
--
----------------------------------------------------------------
--
-- Parameters : TOKEN - An in parameter containing the word
-- : and its length to be used as a possible match.
-- : NUMBER - The number of possible correct words
-- : to be returned.
--
----------------------------------------------------------------
--
-- Algorithm : Within this procedure certain global variables
-- : are set to values that are passed from a calling
-- : routine. These values are then used to locate
-- : and return words that may be possible corrections
-- : for a misspelling. These values are used by the
-- : routines NEXT_WORD and MORE.
--
----------------------------------------------------------------
procedure Initiator (Token : in Token_Definition.Token_Type;
Number : in Positive) is
begin
--The check for the proper word length
if Token.Length < Necessary_Length then
raise Bad_Word;
end if;
--The check for a valid dictionary
if Dictionary_Search_List = null then
raise Dictionary_Error;
else
--The initialization process starts here
Count := Number;
Index := (Hash_Value
(Token.Word (1), Token.Word (2), Token.Length));
Word_Ptr := Dictionary_Search_List.Hash_Table (Index);
Init_Word := Token;
Temp_Ptr := Dictionary_Search_List;
end if;
end Initiator;
end Dictionary_Manager;