diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /gcc/ada/tree_io.adb | |
download | cbb-gcc-4.6.4-15d2061ac0796199866debe9ac87130894b0cdd3.tar.bz2 cbb-gcc-4.6.4-15d2061ac0796199866debe9ac87130894b0cdd3.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'gcc/ada/tree_io.adb')
-rw-r--r-- | gcc/ada/tree_io.adb | 661 |
1 files changed, 661 insertions, 0 deletions
diff --git a/gcc/ada/tree_io.adb b/gcc/ada/tree_io.adb new file mode 100644 index 000000000..6f5647823 --- /dev/null +++ b/gcc/ada/tree_io.adb @@ -0,0 +1,661 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT COMPILER COMPONENTS -- +-- -- +-- T R E E _ I O -- +-- -- +-- B o d y -- +-- -- +-- Copyright (C) 1992-2009 Free Software Foundation, Inc. -- +-- -- +-- GNAT is free software; you can redistribute it and/or modify it under -- +-- terms of the GNU General Public License as published by the Free Soft- -- +-- ware Foundation; either version 3, or (at your option) any later ver- -- +-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- +-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- +-- or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- <http://www.gnu.org/licenses/>. -- +-- -- +-- GNAT was originally developed by the GNAT team at New York University. -- +-- Extensive contributions were provided by Ada Core Technologies Inc. -- +-- -- +------------------------------------------------------------------------------ + +with Debug; use Debug; +with Output; use Output; +with Unchecked_Conversion; + +package body Tree_IO is + Debug_Flag_Tree : Boolean := False; + -- Debug flag for debug output from tree read/write + + ------------------------------------------- + -- Compression Scheme Used for Tree File -- + ------------------------------------------- + + -- We don't just write the data directly, but instead do a mild form + -- of compression, since we expect lots of compressible zeroes and + -- blanks. The compression scheme is as follows: + + -- 00nnnnnn followed by nnnnnn bytes (non compressed data) + -- 01nnnnnn indicates nnnnnn binary zero bytes + -- 10nnnnnn indicates nnnnnn ASCII space bytes + -- 11nnnnnn bbbbbbbb indicates nnnnnnnn occurrences of byte bbbbbbbb + + -- Since we expect many zeroes in trees, and many spaces in sources, + -- this compression should be reasonably efficient. We can put in + -- something better later on. + + -- Note that this compression applies to the Write_Tree_Data and + -- Read_Tree_Data calls, not to the calls to read and write single + -- scalar values, which are written in memory format without any + -- compression. + + C_Noncomp : constant := 2#00_000000#; + C_Zeros : constant := 2#01_000000#; + C_Spaces : constant := 2#10_000000#; + C_Repeat : constant := 2#11_000000#; + -- Codes for compression sequences + + Max_Count : constant := 63; + -- Maximum data length for one compression sequence + + -- The above compression scheme applies only to data written with the + -- Tree_Write routine and read with Tree_Read. Data written using the + -- Tree_Write_Char or Tree_Write_Int routines and read using the + -- corresponding input routines is not compressed. + + type Int_Bytes is array (1 .. 4) of Byte; + for Int_Bytes'Size use 32; + + function To_Int_Bytes is new Unchecked_Conversion (Int, Int_Bytes); + function To_Int is new Unchecked_Conversion (Int_Bytes, Int); + + ---------------------- + -- Global Variables -- + ---------------------- + + Tree_FD : File_Descriptor; + -- File descriptor for tree + + Buflen : constant Int := 8_192; + -- Length of buffer for read and write file data + + Buf : array (Pos range 1 .. Buflen) of Byte; + -- Read/write file data buffer + + Bufn : Nat; + -- Number of bytes read/written from/to buffer + + Buft : Nat; + -- Total number of bytes in input buffer containing valid data. Used only + -- for input operations. There is data left to be processed in the buffer + -- if Buft > Bufn. A value of zero for Buft means that the buffer is empty. + + ----------------------- + -- Local Subprograms -- + ----------------------- + + procedure Read_Buffer; + -- Reads data into buffer, setting Bufn appropriately + + function Read_Byte return Byte; + pragma Inline (Read_Byte); + -- Returns next byte from input file, raises Tree_Format_Error if none left + + procedure Write_Buffer; + -- Writes out current buffer contents + + procedure Write_Byte (B : Byte); + pragma Inline (Write_Byte); + -- Write one byte to output buffer, checking for buffer-full condition + + ----------------- + -- Read_Buffer -- + ----------------- + + procedure Read_Buffer is + begin + Buft := Int (Read (Tree_FD, Buf (1)'Address, Integer (Buflen))); + + if Buft = 0 then + raise Tree_Format_Error; + else + Bufn := 0; + end if; + end Read_Buffer; + + --------------- + -- Read_Byte -- + --------------- + + function Read_Byte return Byte is + begin + if Bufn = Buft then + Read_Buffer; + end if; + + Bufn := Bufn + 1; + return Buf (Bufn); + end Read_Byte; + + -------------------- + -- Tree_Read_Bool -- + -------------------- + + procedure Tree_Read_Bool (B : out Boolean) is + begin + B := Boolean'Val (Read_Byte); + + if Debug_Flag_Tree then + if B then + Write_Str ("True"); + else + Write_Str ("False"); + end if; + + Write_Eol; + end if; + end Tree_Read_Bool; + + -------------------- + -- Tree_Read_Char -- + -------------------- + + procedure Tree_Read_Char (C : out Character) is + begin + C := Character'Val (Read_Byte); + + if Debug_Flag_Tree then + Write_Str ("==> transmitting Character = "); + Write_Char (C); + Write_Eol; + end if; + end Tree_Read_Char; + + -------------------- + -- Tree_Read_Data -- + -------------------- + + procedure Tree_Read_Data (Addr : Address; Length : Int) is + + type S is array (Pos) of Byte; + -- This is a big array, for which we have to suppress the warning + + type SP is access all S; + + function To_SP is new Unchecked_Conversion (Address, SP); + + Data : constant SP := To_SP (Addr); + -- Data buffer to be read as an indexable array of bytes + + OP : Pos := 1; + -- Pointer to next byte of data buffer to be read into + + B : Byte; + C : Byte; + L : Int; + + begin + if Debug_Flag_Tree then + Write_Str ("==> transmitting "); + Write_Int (Length); + Write_Str (" data bytes"); + Write_Eol; + end if; + + -- Verify data length + + Tree_Read_Int (L); + + if L /= Length then + Write_Str ("==> transmitting, expected "); + Write_Int (Length); + Write_Str (" bytes, found length = "); + Write_Int (L); + Write_Eol; + raise Tree_Format_Error; + end if; + + -- Loop to read data + + while OP <= Length loop + + -- Get compression control character + + B := Read_Byte; + C := B and 2#00_111111#; + B := B and 2#11_000000#; + + -- Non-repeat case + + if B = C_Noncomp then + if Debug_Flag_Tree then + Write_Str ("==> uncompressed: "); + Write_Int (Int (C)); + Write_Str (", starting at "); + Write_Int (OP); + Write_Eol; + end if; + + for J in 1 .. C loop + Data (OP) := Read_Byte; + OP := OP + 1; + end loop; + + -- Repeated zeroes + + elsif B = C_Zeros then + if Debug_Flag_Tree then + Write_Str ("==> zeroes: "); + Write_Int (Int (C)); + Write_Str (", starting at "); + Write_Int (OP); + Write_Eol; + end if; + + for J in 1 .. C loop + Data (OP) := 0; + OP := OP + 1; + end loop; + + -- Repeated spaces + + elsif B = C_Spaces then + if Debug_Flag_Tree then + Write_Str ("==> spaces: "); + Write_Int (Int (C)); + Write_Str (", starting at "); + Write_Int (OP); + Write_Eol; + end if; + + for J in 1 .. C loop + Data (OP) := Character'Pos (' '); + OP := OP + 1; + end loop; + + -- Specified repeated character + + else -- B = C_Repeat + B := Read_Byte; + + if Debug_Flag_Tree then + Write_Str ("==> other char: "); + Write_Int (Int (C)); + Write_Str (" ("); + Write_Int (Int (B)); + Write_Char (')'); + Write_Str (", starting at "); + Write_Int (OP); + Write_Eol; + end if; + + for J in 1 .. C loop + Data (OP) := B; + OP := OP + 1; + end loop; + end if; + end loop; + + -- At end of loop, data item must be exactly filled + + if OP /= Length + 1 then + raise Tree_Format_Error; + end if; + + end Tree_Read_Data; + + -------------------------- + -- Tree_Read_Initialize -- + -------------------------- + + procedure Tree_Read_Initialize (Desc : File_Descriptor) is + begin + Buft := 0; + Bufn := 0; + Tree_FD := Desc; + Debug_Flag_Tree := Debug_Flag_5; + end Tree_Read_Initialize; + + ------------------- + -- Tree_Read_Int -- + ------------------- + + procedure Tree_Read_Int (N : out Int) is + N_Bytes : Int_Bytes; + + begin + for J in 1 .. 4 loop + N_Bytes (J) := Read_Byte; + end loop; + + N := To_Int (N_Bytes); + + if Debug_Flag_Tree then + Write_Str ("==> transmitting Int = "); + Write_Int (N); + Write_Eol; + end if; + end Tree_Read_Int; + + ------------------- + -- Tree_Read_Str -- + ------------------- + + procedure Tree_Read_Str (S : out String_Ptr) is + N : Nat; + + begin + Tree_Read_Int (N); + S := new String (1 .. Natural (N)); + Tree_Read_Data (S.all (1)'Address, N); + end Tree_Read_Str; + + ------------------------- + -- Tree_Read_Terminate -- + ------------------------- + + procedure Tree_Read_Terminate is + begin + -- Must be at end of input buffer, so we should get Tree_Format_Error + -- if we try to read one more byte, if not, we have a format error. + + declare + B : Byte; + pragma Warnings (Off, B); + + begin + B := Read_Byte; + + exception + when Tree_Format_Error => return; + end; + + raise Tree_Format_Error; + end Tree_Read_Terminate; + + --------------------- + -- Tree_Write_Bool -- + --------------------- + + procedure Tree_Write_Bool (B : Boolean) is + begin + if Debug_Flag_Tree then + Write_Str ("==> transmitting Boolean = "); + + if B then + Write_Str ("True"); + else + Write_Str ("False"); + end if; + + Write_Eol; + end if; + + Write_Byte (Boolean'Pos (B)); + end Tree_Write_Bool; + + --------------------- + -- Tree_Write_Char -- + --------------------- + + procedure Tree_Write_Char (C : Character) is + begin + if Debug_Flag_Tree then + Write_Str ("==> transmitting Character = "); + Write_Char (C); + Write_Eol; + end if; + + Write_Byte (Character'Pos (C)); + end Tree_Write_Char; + + --------------------- + -- Tree_Write_Data -- + --------------------- + + procedure Tree_Write_Data (Addr : Address; Length : Int) is + + type S is array (Pos) of Byte; + -- This is a big array, for which we have to suppress the warning + + type SP is access all S; + + function To_SP is new Unchecked_Conversion (Address, SP); + + Data : constant SP := To_SP (Addr); + -- Pointer to data to be written, converted to array type + + IP : Pos := 1; + -- Input buffer pointer, next byte to be processed + + NC : Nat range 0 .. Max_Count := 0; + -- Number of bytes of non-compressible sequence + + C : Byte; + + procedure Write_Non_Compressed_Sequence; + -- Output currently collected sequence of non-compressible data + + ----------------------------------- + -- Write_Non_Compressed_Sequence -- + ----------------------------------- + + procedure Write_Non_Compressed_Sequence is + begin + if NC > 0 then + Write_Byte (C_Noncomp + Byte (NC)); + + if Debug_Flag_Tree then + Write_Str ("==> uncompressed: "); + Write_Int (NC); + Write_Str (", starting at "); + Write_Int (IP - NC); + Write_Eol; + end if; + + for J in reverse 1 .. NC loop + Write_Byte (Data (IP - J)); + end loop; + + NC := 0; + end if; + end Write_Non_Compressed_Sequence; + + -- Start of processing for Tree_Write_Data + + begin + if Debug_Flag_Tree then + Write_Str ("==> transmitting "); + Write_Int (Length); + Write_Str (" data bytes"); + Write_Eol; + end if; + + -- We write the count at the start, so that we can check it on + -- the corresponding read to make sure that reads and writes match + + Tree_Write_Int (Length); + + -- Conversion loop + -- IP is index of next input character + -- NC is number of non-compressible bytes saved up + + loop + -- If input is completely processed, then we are all done + + if IP > Length then + Write_Non_Compressed_Sequence; + return; + end if; + + -- Test for compressible sequence, must be at least three identical + -- bytes in a row to be worthwhile compressing. + + if IP + 2 <= Length + and then Data (IP) = Data (IP + 1) + and then Data (IP) = Data (IP + 2) + then + Write_Non_Compressed_Sequence; + + -- Count length of new compression sequence + + C := 3; + IP := IP + 3; + + while IP < Length + and then Data (IP) = Data (IP - 1) + and then C < Max_Count + loop + C := C + 1; + IP := IP + 1; + end loop; + + -- Output compression sequence + + if Data (IP - 1) = 0 then + if Debug_Flag_Tree then + Write_Str ("==> zeroes: "); + Write_Int (Int (C)); + Write_Str (", starting at "); + Write_Int (IP - Int (C)); + Write_Eol; + end if; + + Write_Byte (C_Zeros + C); + + elsif Data (IP - 1) = Character'Pos (' ') then + if Debug_Flag_Tree then + Write_Str ("==> spaces: "); + Write_Int (Int (C)); + Write_Str (", starting at "); + Write_Int (IP - Int (C)); + Write_Eol; + end if; + + Write_Byte (C_Spaces + C); + + else + if Debug_Flag_Tree then + Write_Str ("==> other char: "); + Write_Int (Int (C)); + Write_Str (" ("); + Write_Int (Int (Data (IP - 1))); + Write_Char (')'); + Write_Str (", starting at "); + Write_Int (IP - Int (C)); + Write_Eol; + end if; + + Write_Byte (C_Repeat + C); + Write_Byte (Data (IP - 1)); + end if; + + -- No compression possible here + + else + -- Output non-compressed sequence if at maximum length + + if NC = Max_Count then + Write_Non_Compressed_Sequence; + end if; + + NC := NC + 1; + IP := IP + 1; + end if; + end loop; + + end Tree_Write_Data; + + --------------------------- + -- Tree_Write_Initialize -- + --------------------------- + + procedure Tree_Write_Initialize (Desc : File_Descriptor) is + begin + Bufn := 0; + Tree_FD := Desc; + Set_Standard_Error; + Debug_Flag_Tree := Debug_Flag_5; + end Tree_Write_Initialize; + + -------------------- + -- Tree_Write_Int -- + -------------------- + + procedure Tree_Write_Int (N : Int) is + N_Bytes : constant Int_Bytes := To_Int_Bytes (N); + + begin + if Debug_Flag_Tree then + Write_Str ("==> transmitting Int = "); + Write_Int (N); + Write_Eol; + end if; + + for J in 1 .. 4 loop + Write_Byte (N_Bytes (J)); + end loop; + end Tree_Write_Int; + + -------------------- + -- Tree_Write_Str -- + -------------------- + + procedure Tree_Write_Str (S : String_Ptr) is + begin + Tree_Write_Int (S'Length); + Tree_Write_Data (S (1)'Address, S'Length); + end Tree_Write_Str; + + -------------------------- + -- Tree_Write_Terminate -- + -------------------------- + + procedure Tree_Write_Terminate is + begin + if Bufn > 0 then + Write_Buffer; + end if; + end Tree_Write_Terminate; + + ------------------ + -- Write_Buffer -- + ------------------ + + procedure Write_Buffer is + begin + if Integer (Bufn) = Write (Tree_FD, Buf'Address, Integer (Bufn)) then + Bufn := 0; + + else + Set_Standard_Error; + Write_Str ("fatal error: disk full"); + OS_Exit (2); + end if; + end Write_Buffer; + + ---------------- + -- Write_Byte -- + ---------------- + + procedure Write_Byte (B : Byte) is + begin + Bufn := Bufn + 1; + Buf (Bufn) := B; + + if Bufn = Buflen then + Write_Buffer; + end if; + end Write_Byte; + +end Tree_IO; |