[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Losing character between SkipLine and ReadString from TextIO
From: |
Gaius Mulley |
Subject: |
Re: Losing character between SkipLine and ReadString from TextIO |
Date: |
Tue, 09 May 2023 14:35:49 +0100 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux) |
Rudolf Schubert <rudolf@muc.de> writes:
> Hi,
>
> I recently hit problems with my 'big squash program' when using SkipLine and
> ReadString from TextIO when reading text from files.
>
> In the meantime I've done some first steps with 'cgdb' and could indeed see
> that there is a problem somewhere in the 'lower IO routines'. My knowledge
> does not suffice to point out exactly what's going wrong. Perhaps it has
> something to do with a missing doUnReadChar when 'switching' from SkipLine
> to ReadString? But I'm just guessing.
>
> My question would just be: could someone please have a look at my test program
> which I've included here? I'm creating a file with 2 lines of text in it.
> Then after having created the file I'm opening it again, calling SkipLine
> in order to jump to the second line. A ReadString should then read the second
> line but obviously the first character of the second line is missing from the
> output then.
>
>
> Here is my test program:
>
> (BTW is it ok to put the program here as text or should I better append it?)
>
> MODULE port_test6_gm2;
>
> FROM ChanConsts IMPORT
> OpenResults, old, read, write;
> FROM IOChan IMPORT
> ChanId;
> FROM StdChans IMPORT
> StdOutChan;
> IMPORT StreamFile;
> FROM TextIO IMPORT
> ReadString, SkipLine, WriteLn, WriteString;
>
>
> PROCEDURE SkipReadTest();
> CONST
> arr_len= 128;
>
> TYPE
> arr_type= ARRAY[0..arr_len-1] OF CHAR;
>
> VAR
> cid_file: ChanId;
> cid_out: ChanId;
> file_name: arr_type;
> a_str: arr_type;
> res: OpenResults;
>
> BEGIN (* PROCEDURE SkipReadTest *)
> cid_out:=StdOutChan();
>
> file_name:='test_data';
>
> (* create file and write 2 lines to it *)
> StreamFile.Open(cid_file, file_name, write+old, res);
> IF res=opened THEN
> WriteString(cid_file, '# line1');
> WriteLn(cid_file);
> WriteString(cid_file, '# line2');
> WriteLn(cid_file);
> StreamFile.Close(cid_file);
> END; (* IF res=opened *)
>
> (* (re-)open file and read from it *)
> StreamFile.Open(cid_file, file_name, read, res);
> IF res=opened THEN
> SkipLine(cid_file);
> ReadString(cid_file, a_str);
> WriteString(cid_out, a_str);
> WriteLn(cid_out);
> StreamFile.Close(cid_file);
> END; (* IF res=opened *)
> END SkipReadTest;
>
>
> BEGIN (* MODULE port_test6_gm2 *)
> SkipReadTest();
> END port_test6_gm2.
Hi Rudolf,
here is a proposed patch, which I'll commit once (if) the bootstrap
finishes on another platform. Thanks for the bug report!
regards,
Gaius
diff --git a/gcc/m2/gm2-libs-iso/RTgen.mod b/gcc/m2/gm2-libs-iso/RTgen.mod
index 1da3709590c..b0a35a9bd54 100644
--- a/gcc/m2/gm2-libs-iso/RTgen.mod
+++ b/gcc/m2/gm2-libs-iso/RTgen.mod
@@ -290,21 +290,20 @@ BEGIN
checkErrno(g, d) ;
checkPreRead(g, d, RaiseEOFinLook(g), ChanConsts.rawFlag IN flags) ;
IF (result=IOConsts.allRight) OR (result=IOConsts.notKnown) OR
- (result=IOConsts.endOfLine)
+ (result=IOConsts.endOfLine)
THEN
old := result ;
ch := doReadChar(g^.genif, d) ;
setReadResult(g, d) ;
r := result ;
- ch := doUnReadChar(g^.genif, d, ch) ;
- result := old
+ ch := doUnReadChar(g^.genif, d, ch)
END
END
END doLook ;
(*
- doSkip -
+ doSkip -
*)
PROCEDURE doSkip (g: ChanDev;
diff --git a/gcc/m2/gm2-libs-iso/TextIO.mod b/gcc/m2/gm2-libs-iso/TextIO.mod
index 5e62ea6d032..75998300bed 100644
--- a/gcc/m2/gm2-libs-iso/TextIO.mod
+++ b/gcc/m2/gm2-libs-iso/TextIO.mod
@@ -30,45 +30,73 @@ IMPLEMENTATION MODULE TextIO ;
IMPORT IOChan, IOConsts, CharClass, ASCII ;
FROM SYSTEM IMPORT ADR ;
FROM FIO IMPORT FlushOutErr ;
+FROM libc IMPORT printf ;
+
+
+CONST
+ DebugState = FALSE ;
+
(* The following procedures do not read past line marks *)
-PROCEDURE CanRead (cid: IOChan.ChanId) : BOOLEAN ;
+PROCEDURE CharAvailable (cid: IOChan.ChanId) : BOOLEAN ;
BEGIN
- RETURN( (IOChan.ReadResult(cid)=IOConsts.notKnown) OR
- (IOChan.ReadResult(cid)=IOConsts.allRight) )
-END CanRead ;
+ RETURN( (IOChan.ReadResult (cid) = IOConsts.notKnown) OR
+ (IOChan.ReadResult (cid) = IOConsts.allRight) )
+END CharAvailable ;
+
-PROCEDURE WasGoodChar (cid: IOChan.ChanId) : BOOLEAN ;
+PROCEDURE EofOrEoln (cid: IOChan.ChanId) : BOOLEAN ;
BEGIN
- RETURN( (IOChan.ReadResult(cid)#IOConsts.endOfLine) AND
- (IOChan.ReadResult(cid)#IOConsts.endOfInput) )
-END WasGoodChar ;
+ RETURN( (IOChan.ReadResult (cid) = IOConsts.endOfLine) OR
+ (IOChan.ReadResult (cid) = IOConsts.endOfInput) )
+END EofOrEoln ;
+
+
+(*
+ DumpState
+*)
+
+PROCEDURE DumpState (cid: IOChan.ChanId) ;
+BEGIN
+ printf ("cid = %d, ", cid) ;
+ CASE IOChan.ReadResult (cid) OF
+
+ IOConsts.notKnown: printf ('notKnown') |
+ IOConsts.allRight: printf ('allRight') |
+ IOConsts.outOfRange: printf ('outOfRange') |
+ IOConsts.wrongFormat: printf ('wrongFormat') |
+ IOConsts.endOfLine: printf ('endOfLine') |
+ IOConsts.endOfInput: printf ('endOfInput')
+
+ END ;
+ printf ("\n")
+END DumpState ;
(*
- SetResult - assigns the result in cid.
+ SetNul - assigns the result in cid.
If s is empty then leave as endOfInput
or endOfLine
If s is not empty then assign allRight
If range and i exceeds, h, then assign outOfRange
*)
-PROCEDURE SetResult (cid: IOChan.ChanId; i: CARDINAL;
+PROCEDURE SetNul (cid: IOChan.ChanId; i: CARDINAL;
VAR s: ARRAY OF CHAR; range: BOOLEAN) ;
BEGIN
+ IF DebugState
+ THEN
+ DumpState (cid)
+ END ;
IF i<=HIGH(s)
THEN
- s[i] := ASCII.nul ;
- IF i>0
- THEN
- IOChan.SetReadResult(cid, IOConsts.allRight)
- END
+ s[i] := ASCII.nul
ELSIF range
THEN
- IOChan.SetReadResult(cid, IOConsts.outOfRange)
+ IOChan.SetReadResult (cid, IOConsts.outOfRange)
END
-END SetResult ;
+END SetNul ;
PROCEDURE ReadChar (cid: IOChan.ChanId; VAR ch: CHAR);
@@ -81,16 +109,17 @@ VAR
res: IOConsts.ReadResults ;
BEGIN
FlushOutErr ;
- IF CanRead(cid)
+ IF CharAvailable (cid)
THEN
- IOChan.Look(cid, ch, res) ;
- IF res=IOConsts.allRight
+ IOChan.Look (cid, ch, res) ;
+ IF res = IOConsts.allRight
THEN
- IOChan.Skip(cid)
+ IOChan.Skip (cid)
END
END
END ReadChar ;
+
PROCEDURE ReadRestLine (cid: IOChan.ChanId; VAR s: ARRAY OF CHAR);
(* Removes any remaining characters from the input stream
cid before the next line mark, copying to s as many as
@@ -105,21 +134,22 @@ BEGIN
h := HIGH(s) ;
i := 0 ;
finished := FALSE ;
- WHILE (i<=h) AND CanRead(cid) AND (NOT finished) DO
- ReadChar(cid, s[i]) ;
- IF WasGoodChar(cid)
+ WHILE (i<=h) AND CharAvailable (cid) AND (NOT finished) DO
+ ReadChar (cid, s[i]) ;
+ IF EofOrEoln (cid)
THEN
- INC(i)
- ELSE
finished := TRUE
+ ELSE
+ INC (i)
END
END ;
- WHILE CanRead(cid) DO
- IOChan.Skip(cid)
+ WHILE CharAvailable (cid) DO
+ IOChan.Skip (cid)
END ;
- SetResult(cid, i, s, TRUE)
+ SetNul (cid, i, s, TRUE)
END ReadRestLine ;
+
PROCEDURE ReadString (cid: IOChan.ChanId; VAR s: ARRAY OF CHAR);
(* Removes only those characters from the input stream cid
before the next line mark that can be accommodated in s
@@ -130,19 +160,19 @@ VAR
i, h : CARDINAL ;
finished: BOOLEAN ;
BEGIN
- h := HIGH(s) ;
+ h := HIGH (s) ;
i := 0 ;
finished := FALSE ;
- WHILE (i<=h) AND CanRead(cid) AND (NOT finished) DO
- ReadChar(cid, s[i]) ;
- IF WasGoodChar(cid)
+ WHILE (i<=h) AND CharAvailable (cid) AND (NOT finished) DO
+ ReadChar (cid, s[i]) ;
+ IF EofOrEoln (cid)
THEN
- INC(i)
- ELSE
finished := TRUE
+ ELSE
+ INC (i)
END
END ;
- SetResult(cid, i, s, FALSE)
+ SetNul (cid, i, s, FALSE)
END ReadString ;
@@ -155,16 +185,11 @@ VAR
ch : CHAR ;
res: IOConsts.ReadResults ;
BEGIN
- WHILE CanRead(cid) DO
+ WHILE CharAvailable (cid) DO
IOChan.Look(cid, ch, res) ;
- IF res=IOConsts.allRight
+ IF (res=IOConsts.allRight) AND CharClass.IsWhiteSpace (ch)
THEN
- IF CharClass.IsWhiteSpace(ch)
- THEN
- IOChan.Skip(cid)
- ELSE
- RETURN
- END
+ IOChan.Skip (cid)
ELSE
RETURN
END
@@ -182,19 +207,19 @@ PROCEDURE ReadToken (cid: IOChan.ChanId; VAR s: ARRAY OF
CHAR);
VAR
i, h: CARDINAL ;
BEGIN
- SkipSpaces(cid) ;
- h := HIGH(s) ;
+ SkipSpaces (cid) ;
+ h := HIGH (s) ;
i := 0 ;
- WHILE (i<=h) AND CanRead(cid) DO
- ReadChar(cid, s[i]) ;
- IF (s[i]=ASCII.nul) OR CharClass.IsWhiteSpace(s[i])
+ WHILE (i<=h) AND CharAvailable (cid) DO
+ ReadChar (cid, s[i]) ;
+ IF (s[i]=ASCII.nul) OR CharClass.IsWhiteSpace (s[i])
THEN
- SetResult(cid, i, s, TRUE) ;
+ SetNul (cid, i, s, TRUE) ;
RETURN
END ;
- INC(i)
+ INC (i)
END ;
- SetResult(cid, i, s, TRUE)
+ SetNul (cid, i, s, TRUE)
END ReadToken ;
(* The following procedure reads past the next line mark *)
@@ -209,13 +234,14 @@ VAR
ch : CHAR ;
res: IOConsts.ReadResults ;
BEGIN
- IOChan.Look(cid, ch, res) ;
- WHILE res=IOConsts.allRight DO
- IOChan.SkipLook(cid, ch, res)
+ IOChan.Look (cid, ch, res) ;
+ WHILE res = IOConsts.allRight DO
+ IOChan.SkipLook (cid, ch, res)
END ;
- IF res=IOConsts.endOfLine
+ IF res = IOConsts.endOfLine
THEN
- IOChan.Skip(cid)
+ IOChan.Skip (cid) ;
+ IOChan.SetReadResult (cid, IOConsts.allRight)
END
END SkipLine ;
@@ -224,19 +250,19 @@ END SkipLine ;
PROCEDURE WriteChar (cid: IOChan.ChanId; ch: CHAR);
(* Writes the value of ch to the output stream cid. *)
BEGIN
- IOChan.TextWrite(cid, ADR(ch), SIZE(ch))
+ IOChan.TextWrite (cid, ADR (ch), SIZE (ch))
END WriteChar ;
PROCEDURE WriteLn (cid: IOChan.ChanId);
(* Writes a line mark to the output stream cid. *)
BEGIN
- IOChan.WriteLn(cid)
+ IOChan.WriteLn (cid)
END WriteLn ;
PROCEDURE WriteString (cid: IOChan.ChanId; s: ARRAY OF CHAR);
(* Writes the string value in s to the output stream cid. *)
BEGIN
- IOChan.TextWrite(cid, ADR(s), LENGTH(s))
+ IOChan.TextWrite (cid, ADR (s), LENGTH (s))
END WriteString ;
diff --git a/gcc/testsuite/gm2/isolib/run/pass/skiplinetest.mod
b/gcc/testsuite/gm2/isolib/run/pass/skiplinetest.mod
new file mode 100644
index 00000000000..4460a88dcf6
--- /dev/null
+++ b/gcc/testsuite/gm2/isolib/run/pass/skiplinetest.mod
@@ -0,0 +1,52 @@
+MODULE skiplinetest ;
+
+FROM ChanConsts IMPORT OpenResults, old, read, write;
+FROM IOChan IMPORT ChanId;
+FROM StdChans IMPORT StdOutChan ;
+IMPORT StreamFile;
+FROM TextIO IMPORT ReadString, SkipLine, WriteLn, WriteString;
+FROM StrLib IMPORT StrEqual ;
+FROM libc IMPORT exit, printf ;
+
+
+PROCEDURE StressSkip ;
+VAR
+ stdout,
+ cid : ChanId;
+ filename: ARRAY [0..20] OF CHAR ;
+ str : ARRAY [0..79] OF CHAR ;
+ result : OpenResults;
+BEGIN
+ stdout := StdOutChan();
+ filename := 'testdata';
+
+ StreamFile.Open (cid, filename, write+old, result) ;
+ IF result = opened
+ THEN
+ WriteString (cid, '# line1');
+ WriteLn (cid);
+ WriteString (cid, '# line2');
+ WriteLn (cid) ;
+ StreamFile.Close (cid);
+ END ;
+
+ StreamFile.Open (cid, filename, read, result) ;
+ IF result = opened
+ THEN
+ SkipLine (cid);
+ ReadString (cid, str);
+ IF NOT StrEqual (str, '# line2')
+ THEN
+ printf ("ReadString failed, read %s\n", str) ;
+ exit (1)
+ END ;
+ WriteString (stdout, str);
+ WriteLn (stdout) ;
+ StreamFile.Close (cid)
+ END
+END StressSkip ;
+
+
+BEGIN
+ StressSkip
+END skiplinetest.
\ No newline at end of file