diff options
author | Tristan Gingold <tgingold@free.fr> | 2020-02-25 01:58:42 +0100 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2020-02-25 19:19:23 +0100 |
commit | 83449709c345372656d849d893d2d797a83bd683 (patch) | |
tree | 44c12e5beedde39c6aa744a7934e6362710708ee | |
parent | ab2e4632eb987f9173f56bab05adf18308e060fb (diff) | |
download | ghdl-83449709c345372656d849d893d2d797a83bd683.tar.gz ghdl-83449709c345372656d849d893d2d797a83bd683.tar.bz2 ghdl-83449709c345372656d849d893d2d797a83bd683.zip |
vhdl: handle CR+LF for readline in grt. Fix #1145
Previously CR+LF was handled in std.textio.readline. But that
doesn't work if CR is at position 128 because we would need to read the
next character. Now untruncated_text_read handles CR/CR+LF/LF and
calls ungetc if needed.
-rw-r--r-- | libraries/std/textio-body.vhdl | 8 | ||||
-rw-r--r-- | src/grt/grt-files.adb | 35 | ||||
-rw-r--r-- | src/grt/grt-files_operations.adb | 45 |
3 files changed, 65 insertions, 23 deletions
diff --git a/libraries/std/textio-body.vhdl b/libraries/std/textio-body.vhdl index 235da706a..8ea3dc789 100644 --- a/libraries/std/textio-body.vhdl +++ b/libraries/std/textio-body.vhdl @@ -428,16 +428,14 @@ package body textio is loop untruncated_text_read (f, str, len); exit when len = 0; - if str (len) = LF or str (len) = CR then + if str (len) = LF then -- LRM 14.3 -- The representation of the line does not contain the representation -- of the end of the line. is_eol := true; len := len - 1; - -- End of line is any of LF/CR/CR+LF/LF+CR. - if len > 0 and (str (len) = LF or str (len) = CR) then - len := len - 1; - end if; + -- End of line is any of LF/CR/CR+LF. This is now handled + -- by untruncated_text_read because we need to do a look-ahead. elsif endfile (f) then is_eol := true; else diff --git a/src/grt/grt-files.adb b/src/grt/grt-files.adb index 826e9b05f..5d214052e 100644 --- a/src/grt/grt-files.adb +++ b/src/grt/grt-files.adb @@ -34,6 +34,10 @@ pragma Elaborate_All (Grt.Table); package body Grt.Files is subtype C_Files is Grt.Stdio.FILEs; + -- The end of lines + C_LF : constant int := 10; -- \n + C_CR : constant int := 13; -- \r + Auto_Flush : constant Boolean := False; type File_Entry_Type is record @@ -470,22 +474,37 @@ package body Grt.Files is is Stream : C_Files; Max_Len : int; + C : int; + L : Ghdl_Index_Type; begin Stream := Get_File (File); Check_Read (File, True); Max_Len := int (Str.Bounds.Dim_1.Length); - if fgets (Str.Base (0)'Address, Max_Len, Stream) = Null_Address then - Internal_Error ("ghdl_untruncated_text_read: end of file"); - end if; - -- Compute the length. - for I in Ghdl_Index_Type loop - if Str.Base (I) = NUL then - Len.all := Std_Integer (I); - exit; + -- Read at most LEN characters, stop at EOL. + L := 0; + for I in 1 .. Max_Len loop + C := fgetc (Stream); + exit when C < 0; + -- Be nice with DOS files: handle CR/CR+LF/LF. + -- Note: LF+CR is not handled, so that on unix we don't need + -- to read the next line. + -- Always return LF as end of line. + if C = C_CR then + C := fgetc (Stream); + if C > 0 and C /= C_LF then + C := ungetc (C, Stream); + pragma Assert (C >= 0); + end if; + C := C_LF; end if; + Str.Base (L) := Character'Val (C); + L := L + 1; + exit when C = C_LF; end loop; + + Len.all := Std_Integer (L); end Ghdl_Untruncated_Text_Read; procedure File_Close (File : Ghdl_File_Index; Is_Text : Boolean) diff --git a/src/grt/grt-files_operations.adb b/src/grt/grt-files_operations.adb index c7770b5f3..b1f504dc9 100644 --- a/src/grt/grt-files_operations.adb +++ b/src/grt/grt-files_operations.adb @@ -31,6 +31,10 @@ pragma Elaborate_All (Grt.Table); package body Grt.Files_Operations is subtype C_Files is Grt.Stdio.FILEs; + -- The end of lines + C_LF : constant int := 10; -- \n + C_CR : constant int := 13; -- \r + Auto_Flush : constant Boolean := False; type File_Entry_Type is record @@ -518,7 +522,7 @@ package body Grt.Files_Operations is Str.Base (I) := Character'Val (C); end if; -- End of line is '\n' or LF or character # 10. - if C = 10 then + if C = C_LF then Length := Std_Integer (I + 1); Status := Op_Ok; return; @@ -534,7 +538,8 @@ package body Grt.Files_Operations is Status : out Op_Status) is Stream : C_Files; - Max_Len : int; + L : Natural; + C : int; begin Get_File (File, Stream, Status); if Status /= Op_Ok then @@ -545,15 +550,35 @@ package body Grt.Files_Operations is return; end if; - Max_Len := int (Len); - if fgets (To_Address (Buf), Max_Len, Stream) = Null_Address then - Status := Op_End_Of_File; - return; - end if; - - -- Compute the length. - Len := Std_Integer (strlen (Buf)); + -- Default status. Status := Op_Ok; + + -- Read at most LEN characters, stop at EOL. + L := 0; + for I in 1 .. Len loop + C := fgetc (Stream); + if C < 0 then + Status := Op_End_Of_File; + exit; + end if; + -- Be nice with DOS files: handle CR/CR+LF/LF. + -- Note: LF+CR is not handled, so that on unix we don't need + -- to read the next line. + -- Always return LF as end of line. + if C = C_CR then + C := fgetc (Stream); + if C > 0 and C /= C_LF then + C := ungetc (C, Stream); + pragma Assert (C >= 0); + end if; + C := C_LF; + end if; + L := L + 1; + Buf (L) := Character'Val (C); + exit when C = C_LF; + end loop; + + Len := Std_Integer (L); end Ghdl_Untruncated_Text_Read; procedure File_Close |