DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400 Tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Rational R1000/400 Tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: B T

⟦5f266aa55⟧ TextFile

    Length: 52687 (0xcdcf)
    Types: TextFile
    Names: »B«

Derivation

└─⟦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⟧ 

TextFile

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