gm2
[Top][All Lists]
Advanced

[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

reply via email to

[Prev in Thread] Current Thread [Next in Thread]