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

⟦f72bd60ff⟧ TextFile

    Length: 26144 (0x6620)
    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

with Text_Io;
use Text_Io;
with Calendar;
use Calendar;
with String_Pkg;
use String_Pkg;
with Unchecked_Deallocation;


package body Simple_Paginated_Output is

    package Int_Io is new Integer_Io (Integer);

    Month_Name : constant Variable_String_Array (1 .. 12) :=
       (1 => Create ("January"),
        2 => Create ("February"),
        3 => Create ("March"),
        4 => Create ("April"),
        5 => Create ("May"),
        6 => Create ("June"),
        7 => Create ("July"),
        8 => Create ("August"),
        9 => Create ("September"),
        10 => Create ("October"),
        11 => Create ("November"),
        12 => Create ("December"));

    function Convert (Input_Number : in Integer; Digit : in Integer := 0)
                     return String is

        --|-Algorithm:
        --| If integer value is negative or greater than 99
        --|    then return null text
        --| If input value is less than 10 (ie. single decimal digit)
        --|    then concatenate 0 and character equivalent of the given value
        --|    else convert value to character equivalent
        --| Return converted text
        --|+

        Temp_Text : String (1 .. 16);
        Index : Integer;

    begin

        if Digit > Temp_Text'Last then
            return "";
        end if;
        Int_Io.Put (Temp_Text, Input_Number);
        if Digit <= 0 then
            Index := Temp_Text'Last;
            for I in Temp_Text'Range loop
                if Temp_Text (I) /= ' ' then
                    Index := I;
                    exit;
                end if;
            end loop;
        else
            Index := Temp_Text'Last - Digit + 1;
            for I in Index .. Temp_Text'Last loop
                if Temp_Text (I) = ' ' then
                    Temp_Text (I) := '0';
                end if;
            end loop;
        end if;
        return Temp_Text (Index .. Temp_Text'Last);

    end Convert;
    pragma Page;
    procedure Set_Date_Time (File_Handle : in Paginated_File_Handle) is

        --|-Algorithm:
        --| Get the current system date/time
        --| Separate date/time into appropriate components
        --| Calculate in terms of hours, minutes, and seconds
        --| Set current date/time in the file structure
        --| Set the current date in "English" (eg. January 1, 1985)
        --|    in the file structure
        --| Exit
        --|+

        Clock_Value : Calendar.Time;
        Year : Calendar.Year_Number;
        Month : Calendar.Month_Number;
        Day : Calendar.Day_Number;
        Duration : Calendar.Day_Duration;

    begin

        Clock_Value := Calendar.Clock;
        Calendar.Split (Clock_Value, Year, Month, Day, Duration);
        File_Handle.Current_Date := Convert (Integer (Month), 2) & "/" &
                                       Convert (Integer (Day), 2) & "/" &
                                       Convert (Integer (Year mod 100), 2);
        File_Handle.Current_Time :=
           Convert (Integer (Duration) / (60 * 60), 2) & ":" &
              Convert ((Integer (Duration) mod (60 * 60)) / 60, 2) &
              ":" & Convert (Integer (Duration) mod 60, 2);
        String_Pkg.Mark;
        File_Handle.Current_Calendar :=
           String_Pkg.Make_Persistent
              (Month_Name (Integer (Month)) &
               Integer'Image (Day) & "," & Integer'Image (Year));
        String_Pkg.Release;

    end Set_Date_Time;
    pragma Page;
    procedure Check_Valid (File_Handle : in Paginated_File_Handle) is

        --|-Algorithm:
        --| If handle is null or external file name is null
        --|    then raise an error
        --| Exit
        --|+

    begin

        if File_Handle = null then
            raise Invalid_File;
        end if;

    end Check_Valid;
    pragma Page;
    procedure Clear_Text (Text_Handle : in Variable_String_Array_Handle) is

        --|-Algorithm:
        --| If valid access to text array
        --|    then return text array storage to the heap (access set to null)
        --| Exit
        --|+

    begin

        if Text_Handle /= null then
            for I in Text_Handle'Range loop
                String_Pkg.Flush (Text_Handle (I));
            end loop;
        end if;

    end Clear_Text;
    pragma Page;
    procedure Set_Text (File_Handle : in Paginated_File_Handle;
                        Text_String : in Variable_String_Array) is

        --|-Algorithm:
        --| Validate paginated file structure (raise error if not valid)
        --| If requested text array is too large
        --|    then raise an error
        --| Clear old text array
        --| Set new text array with specified justification (top or bottom)
        --| in the area as specified
        --| Exit
        --|+

        Text_Index : Integer;

    begin
        Check_Valid (File_Handle);
        Text_Index := 1;
        if File_Handle.Header_Size < Text_String'Last then
            raise Text_Overflow;
        end if;
        Clear_Text (File_Handle.Page_Header);
        for I in Text_String'Range loop
            File_Handle.Page_Header (Text_Index) :=
               String_Pkg.Make_Persistent (Text_String (I));
            Text_Index := Text_Index + 1;
        end loop;
    end Set_Text;
    pragma Page;
    function Tilde_Substitute
                (File_Handle : in Paginated_File_Handle;
                 Input_Text : in String_Pkg.String_Type) return String is

        --|-Algorithm:
        --| Set the length of the text in question
        --| Clear the result string to null
        --| Loop until all input characters are processed
        --|    Fetch one character
        --|    If the character is a tilde (~)
        --|       then bump input index and if past the end exit the loop
        --|            Fetch the next character
        --|            Based on this character substitute appropriately
        --|        else add this to the output
        --|     Bump input index and loop
        --| Return the output (substituted) string
        --| Exit
        --|+

        Output_Text : String_Pkg.String_Type;
        S_Str : String_Pkg.String_Type;
        Letter : Character;
        Index : Natural;

    begin

        S_Str := Input_Text;
        loop
            Index := String_Pkg.Match_C (S_Str, '~');
            if Index = 0 then
                Output_Text := Output_Text & S_Str;
                exit;
            end if;
            if Index > 1 then
                Output_Text := Output_Text &
                                  String_Pkg.Substr (S_Str, 1, Index - 1);
            end if;
            if Index < String_Pkg.Length (S_Str) then
                Letter := String_Pkg.Fetch (S_Str, Index + 1);
            else
                exit;
            end if;
            case Letter is
                when 'f' | 'F' =>
                    Output_Text := Output_Text & File_Handle.File_Name;
                when 'c' | 'C' =>
                    Output_Text := Output_Text & File_Handle.Current_Calendar;
                when 'd' | 'D' =>
                    Output_Text := Output_Text & File_Handle.Current_Date;
                when 't' | 'T' =>
                    Output_Text := Output_Text & File_Handle.Current_Time;
                when 'p' | 'P' =>
                    Output_Text := Output_Text &
                                      Convert (File_Handle.Current_Page, 0);
                when others =>
                    Output_Text := Output_Text & ("" & Letter);
            end case;
            Index := Index + 2;
            if Index > String_Pkg.Length (S_Str) then
                exit;
            end if;
            S_Str := String_Pkg.Substr (S_Str, Index,
                                        String_Pkg.Length (S_Str) - Index + 1);
        end loop;

        return String_Pkg.Value (Output_Text);

    end Tilde_Substitute;
    pragma Page;
    procedure Put_Text (File_Handle : in Paginated_File_Handle) is

        --|-Algorithm:
        --| If access to text array is null
        --|    then write appropriate number of line terminators
        --|         exit
        --| Loop over the depth of the text array
        --|    If text is null
        --|       then write line terminator
        --|       else resolve tilde substitution
        --|            write a line of text followed by a line terminator
        --| Exit
        --|+

        Text_Size : Integer;

    begin
        if File_Handle.Header_Size = 0 then
            return;
        end if;
        Text_Size := File_Handle.Header_Size;
        if File_Handle.Page_Header = null then
            Text_Io.New_Line (File_Handle.File_Reference,
                              Text_Io.Positive_Count (Text_Size));
            return;
        end if;
        for I in 1 .. Text_Size loop
            String_Pkg.Mark;
            if String_Pkg.Is_Empty (File_Handle.Page_Header (I)) then
                Text_Io.New_Line (File_Handle.File_Reference, 1);
            else
                Text_Io.Put_Line
                   (File_Handle.File_Reference,
                    Tilde_Substitute
                       (File_Handle, File_Handle.Page_Header (I)));
            end if;
            String_Pkg.Release;
        end loop;

    end Put_Text;
    pragma Page;
    procedure Free_Structure is
       new Unchecked_Deallocation
              (Paginated_File_Structure, Paginated_File_Handle);

    procedure Abort_Paginated_Output
                 (File_Handle : in out Paginated_File_Handle) is

        --|-Algorithm:
        --| If given handle is null
        --|    return
        --| Return header/footer text array storage to the heap
        --| Close file
        --| Return file structure storage to the heap
        --| Exit
        --|+

    begin
        if File_Handle = null then
            return;
        end if;
        Clear_Text (File_Handle.Page_Header);
        String_Pkg.Flush (File_Handle.Current_Calendar);
        String_Pkg.Flush (File_Handle.File_Name);
        Text_Io.Close (File_Handle.File_Reference);
        Free_Structure (File_Handle);

    exception

        when Text_Io.Status_Error =>
            Free_Structure (File_Handle);

    end Abort_Paginated_Output;
    pragma Page;
    procedure Line_Feed (File_Handle : in Paginated_File_Handle;
                         Count : in Integer) is

        --|-Algorithm:
        --| If at top of the page
        --|    then write header
        --| If the request count is 0
        --|    then return
        --| If the request is greater than the remainder on the page
        --|    then write remainder number of new lines
        --|         decrement request by this amount
        --|         write footer
        --|         eject page and update page and line count
        --|         if more space needed
        --|            then recursively call self with count
        --|    else write requested number of new lines
        --|         update line count
        --| Exit
        --|+

        Skip_Count : Integer;

    begin

        if File_Handle.Current_Line = 0 and File_Handle.Page_Size /= 0 then
            File_Handle.Current_Line := 1;
            File_Handle.Current_Page := File_Handle.Current_Page + 1;
            Text_Io.New_Page (File_Handle.File_Reference);
            Put_Text (File_Handle);
        end if;
        if Count <= 0 then
            return;
        end if;
        Skip_Count := File_Handle.Maximum_Line - File_Handle.Current_Line + 1;
        if Count >= Skip_Count and File_Handle.Page_Size /= 0 then
            Text_Io.New_Line (File_Handle.File_Reference,
                              Text_Io.Positive_Count (Skip_Count));
            Skip_Count := Count - Skip_Count;
            File_Handle.Current_Line := 0;
            if Skip_Count /= 0 then
                Line_Feed (File_Handle, Skip_Count);
            end if;
        else
            Text_Io.New_Line (File_Handle.File_Reference,
                              Text_Io.Positive_Count (Count));
            if File_Handle.Page_Size /= 0 then
                File_Handle.Current_Line := File_Handle.Current_Line + Count;
            end if;
        end if;

    end Line_Feed;
    pragma Page;
    procedure Page_Eject (File_Handle : in Paginated_File_Handle;
                          Count : in Integer := 1) is

        --|-Algorithm:
        --| Validate paginated file structure (raise error if not valid)
        --| Raise Invalid_Count if page request is too large
        --| Convert the number of pages to skip into number of lines
        --| Write out this number of new line control characters
        --| while taking into account header, footer, and pagination.
        --| Exit
        --|+

    begin

        if File_Handle.Page_Size = 0 then
            Line_Feed (File_Handle, 1);
            return;
        end if;
        if Count > 99 then
            raise Invalid_Count;
        end if;
        if File_Handle.Current_Line = 0 then
            Line_Feed (File_Handle, (Count * File_Handle.Maximum_Line));
        else
            Line_Feed (File_Handle, (Count * File_Handle.Maximum_Line -
                                     File_Handle.Current_Line + 1));
        end if;

    end Page_Eject;
    pragma Page;
    procedure Set_Text_Area (Text_Handle : in out Variable_String_Array_Handle;
                             Area_Size : in Integer) is

        Temp_Handle : Variable_String_Array_Handle;

    begin

        if Area_Size <= 0 then
            return;
        end if;
        if Text_Handle = null or else Text_Handle'Last < Area_Size then
            Temp_Handle := Text_Handle;
            Text_Handle := new Variable_String_Array (1 .. Area_Size);
            if Temp_Handle /= null then
                for I in Temp_Handle'Range loop
                    Text_Handle (I) :=
                       String_Pkg.Make_Persistent (Temp_Handle (I));
                end loop;
                Clear_Text (Temp_Handle);
            end if;
        end if;

    end Set_Text_Area;
    pragma Page;
    procedure Write (File_Handle : in Paginated_File_Handle;
                     Text_Line : in String;
                     Feed : in Boolean) is

        --|-Algorithm:
        --| Validate paginated file structure (raise error if not valid)
        --| If at the top of the page
        --|    then write out the header
        --| Output the given line of text to the paginated file
        --| Write out a new line control character
        --| If at the bottom of the page
        --|    then write out the footer and eject the page
        --| Exit
        --|+

    begin

        Check_Valid (File_Handle);
        Line_Feed (File_Handle, 0);
        Text_Io.Put (File_Handle.File_Reference, Text_Line);
        if Feed then
            Line_Feed (File_Handle, 1);
        end if;
    end Write;
    pragma Page;
    procedure Create_Paginated_File (File_Name : in Host_File_Name := "";
                                     File_Handle : in out Paginated_File_Handle;
                                     Page_Size : in Integer := 60;
                                     Header_Size : in Integer := 6) is

        --|-Algorithm:
        --| If an active (ie. non-null) handle is given
        --|    then close that file first
        --| Create a paginated file structure
        --| If no file name is given
        --|    then assume standard output
        --|    else create (open) an external file
        --| Fill the paginated file structure with external file information,
        --| page layout information, and current date/time
        --| Return access to the completed structure
        --| Exit
        --|+

    begin

        Close_Paginated_File (File_Handle);
        File_Handle := new Paginated_File_Structure;
        if File_Name /= "" then
            File_Handle.File_Name := String_Pkg.Make_Persistent (File_Name);
            Text_Io.Create (File => File_Handle.File_Reference,
                            Name => File_Name);
        end if;
        Set_Page_Layout (File_Handle, Page_Size, Header_Size);
        Set_Date_Time (File_Handle);

    exception

        when Text_Io.Status_Error =>
            Abort_Paginated_Output (File_Handle);
            raise File_Already_Open;
        when Text_Io.Name_Error | Text_Io.Use_Error =>
            Abort_Paginated_Output (File_Handle);
            raise File_Error;
        when Page_Layout_Error =>
            Abort_Paginated_Output (File_Handle);
            raise Page_Layout_Error;

    end Create_Paginated_File;
    pragma Page;
    pragma Page;
    procedure Set_Page_Layout (File_Handle : in Paginated_File_Handle;
                               Page_Size : in Integer;
                               Header_Size : in Integer) is

        --|-Algorithm:
        --| Validate paginated file structure (raise error if not valid)
        --| If page layout is contradictory
        --|    then raise an error
        --| If not at the top of the page
        --|    then eject current page
        --| Set page size, header size, footer size, and text area size
        --| per page
        --| Exit
        --|+

        Temp_Handle : Variable_String_Array_Handle;

    begin

        Check_Valid (File_Handle);
        if Page_Size < 0 or Header_Size < 0 or
           (Page_Size /= 0 and Page_Size <= Header_Size) then
            raise Page_Layout_Error;
        end if;
        if File_Handle.Current_Line /= 0 and File_Handle.Page_Size /= 0 then
            Page_Eject (File_Handle, 1);
        end if;
        File_Handle.Page_Size := Page_Size;
        if Page_Size = 0 then
            File_Handle.Maximum_Line := 0;
        else
            File_Handle.Maximum_Line := Page_Size - Header_Size;
        end if;
        File_Handle.Header_Size := Header_Size;
        Set_Text_Area (File_Handle.Page_Header, File_Handle.Header_Size);
    end Set_Page_Layout;

    procedure Set_Header (File_Handle : in Paginated_File_Handle;
                          Header_Text : in Variable_String_Array) is

        --|-Algorithm:
        --| Set given header text as odd page header
        --| Exit
        --|+

    begin

        Set_Text (File_Handle, Header_Text);

    end Set_Header;
    pragma Page;
    procedure Set_Header (File_Handle : in Paginated_File_Handle;
                          Header_Line : in Integer;
                          Header_Text : in String_Pkg.String_Type) is

        --|-Algorithm:
        --| Validate paginated file structure (raise error if not valid)
        --| If requested header line number is out of range
        --|     then raise an error
        --| Set header text at requested line for odd pages
        --| Exit
        --|+

    begin

        Check_Valid (File_Handle);
        if Header_Line < 1 then
            raise Text_Underflow;
        end if;
        if Header_Line > File_Handle.Header_Size then
            raise Text_Overflow;
        end if;
        File_Handle.Page_Header (Header_Line) :=
           String_Pkg.Make_Persistent (Header_Text);

    end Set_Header;
    pragma Page;
    procedure Set_Header (File_Handle : in Paginated_File_Handle;
                          Header_Line : in Integer;
                          Header_Text : in String) is

        --|-Algorithm:
        --| Create a variable string
        --| Set odd page header
        --| Exit
        --|+

        Text : String_Pkg.String_Type;

    begin

        Text := String_Pkg.Make_Persistent (Header_Text);
        Set_Header (File_Handle, Header_Line, Text);
        String_Pkg.Flush (Text);

    end Set_Header;

    procedure Close_Paginated_File
                 (File_Handle : in out Paginated_File_Handle) is

        --|-Algorithm:
        --| If no file (ie. handle is null)
        --|    then return
        --| If not at the top of the page
        --|    then eject current page
        --| Return all storage used for this file to the heap
        --| Close the external file
        --| Exit
        --|+

    begin

        if File_Handle = null then
            return;
        end if;
        if File_Handle.Current_Line /= 0 and File_Handle.Page_Size /= 0 then
            Page_Eject (File_Handle, 1);
        end if;
        Abort_Paginated_Output (File_Handle);

    end Close_Paginated_File;
    pragma Page;
    procedure Put (File_Handle : in Paginated_File_Handle;
                   Text : in Character) is

    begin

        Write (File_Handle, "" & Text, False);

    end Put;
    pragma Page;
    procedure Put (File_Handle : in Paginated_File_Handle; Text : in String) is

        --|-Algorithm:
        --| Execute Write procedure with feed
        --| Exit
        --|+

    begin

        Write (File_Handle, Text, False);

    end Put;
    pragma Page;
    procedure Put (File_Handle : in Paginated_File_Handle;
                   Text : in String_Pkg.String_Type) is

        --|-Algorithm:
        --| Create a fixed length string
        --| Output the line
        --| Exit
        --|+

    begin

        Write (File_Handle, String_Pkg.Value (Text), False);

    end Put;
    pragma Page;
    procedure Put (File_Handle : in Paginated_File_Handle;
                   Text : in Variable_String_Array) is

        --|-Algorithm:
        --| Loop for all elements of the variable string array
        --|    Create a fixed length string
        --|    Output the line
        --| Exit
        --|+

    begin

        for I in Text'Range loop
            Write (File_Handle, String_Pkg.Value (Text (I)), False);
        end loop;

    end Put;
    pragma Page;
    procedure Space (File_Handle : in Paginated_File_Handle;
                     Count : in Integer) is

    begin

        Check_Valid (File_Handle);
        if Count <= 0 then
            return;
        end if;
        declare
            Space_String : String (1 .. Count) := (1 .. Count => ' ');
        begin
            Write (File_Handle, Space_String, False);
        end;

    end Space;
    pragma Page;
    procedure Put_Line (File_Handle : in Paginated_File_Handle;
                        Text_Line : in String) is

        --|-Algorithm:
        --| Execute Write procedure with feed
        --| Exit
        --|+

    begin

        Write (File_Handle, Text_Line, True);

    end Put_Line;
    pragma Page;
    procedure Put_Line (File_Handle : in Paginated_File_Handle;
                        Text_Line : in String_Pkg.String_Type) is

        --|-Algorithm:
        --| Create a fixed length string
        --| Output the line
        --| Exit
        --|+

    begin

        Write (File_Handle, String_Pkg.Value (Text_Line), True);

    end Put_Line;
    pragma Page;
    procedure Put_Line (File_Handle : in Paginated_File_Handle;
                        Text_Line : in Variable_String_Array) is

        --|-Algorithm:
        --| Loop for all elements of the variable string array
        --|    Create a fixed length string
        --|    Output the line
        --| Exit
        --|+

    begin

        for I in Text_Line'Range loop
            Write (File_Handle, String_Pkg.Value (Text_Line (I)), True);
        end loop;

    end Put_Line;
    pragma Page;
    procedure Space_Line (File_Handle : in Paginated_File_Handle;
                          Count : in Integer := 1) is

        --|-Algorithm:
        --| Validate paginated file structure (raise error if not valid)
        --| Raise Invalid_Count if space request is too large
        --| Write out the given number of new line control characters
        --| while taking into account header, footer, and pagination.
        --| Exit
        --|+

    begin

        Check_Valid (File_Handle);
        Line_Feed (File_Handle, Count);

    end Space_Line;
    pragma Page;
    procedure Skip_Line (File_Handle : in Paginated_File_Handle;
                         Count : in Integer := 1) is

        --|-Algorithm:
        --| Validate paginated file structure (raise error if not valid)
        --| Set the number of new line characters to be written as the
        --| number specified or the number of lines remaining on the
        --| page which ever is smaller.
        --| Write out this number of new line control characters
        --| while taking into account header, footer, and pagination.
        --| (If at the top of the page then Skip_Lines does nothing)
        --| Exit
        --|+

        Skip_Count : Integer;

    begin

        Check_Valid (File_Handle);
        if File_Handle.Current_Line /= 0 or File_Handle.Page_Size = 0 then
            Skip_Count := File_Handle.Maximum_Line -
                             File_Handle.Current_Line + 1;
            if Skip_Count > Count or File_Handle.Page_Size = 0 then
                Skip_Count := Count;
            end if;
            Line_Feed (File_Handle, Skip_Count);
        end if;
    end Skip_Line;
    pragma Page;
    procedure Put_Page (File_Handle : in Paginated_File_Handle;
                        Count : in Integer := 1) is

        --|-Algorithm:
        --| Validate paginated file structure (raise error if not valid)
        --| Raise Invalid_Count if page request is too large
        --| Convert the number of pages to skip into number of lines
        --| Write out this number of new line control characters
        --| while taking into account header, footer, and pagination.
        --| Exit
        --|+

    begin

        Check_Valid (File_Handle);
        Page_Eject (File_Handle, Count);

    end Put_Page;
    pragma Page;
    function Available_Lines
                (File_Handle : in Paginated_File_Handle) return Integer is

        --|-Algorithm:
        --| Validate paginated file structure (raise error if not valid)
        --| Return the number of lines remaining on the page
        --|+

    begin

        Check_Valid (File_Handle);
        if File_Handle.Page_Size = 0 then
            return -1;
        end if;
        if File_Handle.Current_Line = 0 then
            return File_Handle.Maximum_Line;
        else
            return File_Handle.Maximum_Line - File_Handle.Current_Line + 1;
        end if;

    end Available_Lines;

end Simple_Paginated_Output;