with Text_Io; with String_Pack; use String_Pack; package body Variable_Io is -- GENERIC INPUTS => -- Segment_Length : Natural := 80; -- END. -- ************************************************************************** -- Functional Description : Variable_Io controls the length of an output line. -- The user of the package sets the length of output at instantiation time. subtype Segment is String (1 .. Segment_Length); type Segment_Array is array (Integer range 1 .. Max_Length / Segment_Length + 1) of Segment; -- output line buffer Buffer : Segment_Array; -- buffer pointers Line_Indx, Segment_Indx : Natural := 1; Source_Indx : Natural := 1; Buffer_Indx : Natural := 1; Seg_Length : Natural := 0; -- *********************************************************************** -- Functional Description : All the data sent between calls to Put_Line -- are buffered into an array. -- Major Memory Usage : N/A -- Entry and Exit Parameters : See formal parameters -- Subroutines Called : String_Pack.Substr -- *********************************************************************** procedure Put (File_Name : in Text_Io.File_Type; Source : in String) is begin if Buffer_Indx = 1 then -- Start at the beginning of the buffer for this segment Seg_Length := Segment_Length; elsif Buffer_Indx > (Segment_Length * 2) / 3 then -- The buffer for this segment already has some data in it/ -- If the buffer is already 2/3 full, then start on a new one Seg_Length := Segment_Length; Buffer_Indx := 1; else -- The buffer is aldready partially used. Calculate -- the remaining segment length. Seg_Length := Segment_Length - Buffer_Indx + 1; Line_Indx := Line_Indx - 1; end if; while Source'Length - Source_Indx + 1 > Seg_Length loop -- Break the source up into segments -- Check to see if a word is being split. if Source (Source_Indx + Seg_Length) /= ' ' then -- back up and find the previous blank. Segment_indx -- will be pointing to the first blank before the last -- word. Segment_Indx := Source_Indx + Seg_Length - 1; while Source (Segment_Indx) /= ' ' loop Segment_Indx := Segment_Indx - 1; end loop; else Segment_Indx := Source_Indx + Seg_Length - 1; end if; -- if the word continues into the next segment, move the segment -- up to the last blank. Substr (Source, Source_Indx, Segment_Indx, Buffer (Line_Indx), Buffer_Indx, Segment_Indx - Source_Indx + 1); -- Increment the pointers Line_Indx := Line_Indx + 1; Source_Indx := Segment_Indx + 1; -- Reset the buffer index. The entire segment was filled last -- time. Buffer_Indx := 1; Seg_Length := Segment_Length; end loop; -- Store the remaining characters of the source string into the -- buffer. Substr (Source, Source_Indx, Source'Length - Source_Indx + 1, Buffer (Line_Indx), Buffer_Indx, Source'Length - Source_Indx + 1); -- reset index pointers Line_Indx := Line_Indx + 1; Buffer_Indx := Buffer_Indx + Source'Length - Source_Indx + 1; Source_Indx := 1; end Put; -- *********************************************************************** -- Functional Description : Put_Line initiates the transmission of the -- contents in the output buffer and reinitializes all the summing -- variables and buffer pointers. -- Major Memory Usage : N/A -- Entry and Exit Parameters : See formal parameters -- Subroutines Called : Text_Io.Put_Line -- Put (internal) -- *********************************************************************** procedure Put_Line (File_Name : in Text_Io.File_Type; Source : in String) is begin -- add this source to the segment array Put (File_Name, Source); -- output all the segments in the array for I in 1 .. Line_Indx - 1 loop if I > 1 then text_io.put_line(file_name, " " & buffer(i)); else Text_Io.Put_Line (File_Name, Buffer (I)); end if; end loop; -- reset the summing variables Line_Indx := 1; Source_Indx := 1; Buffer_Indx := 1; -- clear the array for I in 1 .. Max_Length / Segment_Length + 1 loop Buffer (I) := (others => ' '); end loop; end Put_Line; begin -- clear the array for I in 1 .. Max_Length / Segment_Length + 1 loop Buffer (I) := (others => ' '); end loop; end Variable_Io;