gm2
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Problems Interfacing Modula-2 with GNU Readline library


From: Michael Riedl
Subject: Re: Problems Interfacing Modula-2 with GNU Readline library
Date: Thu, 7 Mar 2024 19:10:02 +0100
User-agent: Mozilla/5.0 (X11; Linux i686; rv:102.0) Gecko/20100101 Thunderbird/102.11.0

Alice,

just for curiosity, I was fiddling around with quite similar issues when using Fortran and "C" code form a Modula-2 main program.

Attached my solution (procedures to be called after the respective Fortran or "C" code). The implementation is Fortran code for both languages, but if only "C" code is concerned, a pure "C" wrapper to call fflush(stdout) would be quite simple (see third attached file).

Only a call to empty the M2 IO buffer before a call to foreign code may, in more complex cases, result in a delayed (better: out of sequence) output from the foreign code - which will not happen for the case you described - at least if I am not totally mistaken.

When using the ISO IO modules, a call to Flush before the call to foreign code is helpful (IOChan.Flush(StdChans.StdOutChan());) - this is similar to what Gaius suggested for your case.

Gruß

Michael

Am 05.03.24 um 11:18 schrieb Gaius Mulley:
Alice Osako <alicetrillianosako@gmail.com> writes:

One minor error in the test code, in that I had somehow copied an older version 
of the code. The line 'Fin(input)' should be at the start of the loop, not the
end.

Alice Osako:

  I am working on a medium-sized project in Modula-2 (specifically, an 
implementation of the MAL interpreter - see https://github.com/kanaka/mal for
  details), and one of the soft requirements/recommended implementation details 
is editable input and input history. For this purpose, I intend to use the
  existing Readline library, and to this end I created a simple definition 
module as a binding.

  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  DEFINITION MODULE FOR "C" readline;

  FROM SYSTEM IMPORT ADDRESS;

  EXPORT UNQUALIFIED readline, add_history;

  PROCEDURE readline (prompt: ARRAY OF CHAR) : ADDRESS;

  PROCEDURE add_history (line: ARRAY OF CHAR);

  END readline.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  However, I am running into a problem when testing these bindings. When I run 
the following test program:

  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  MODULE rl_test;

  FROM SYSTEM IMPORT ADDRESS;

  FROM DynamicStrings IMPORT String, Fin, Length,
                                                         InitStringCharStar,
                                                        CopyOut, Equal;

  FROM StrIO IMPORT WriteString, WriteLn;

  FROM readline IMPORT readline, add_history;

  VAR
     input, exitCondition: String;
     temp: ARRAY [0..1024] OF CHAR;

  BEGIN
     exitCondition := InitString("exit");
     WHILE NOT Equal(input, exitCondition) DO
        input := InitStringCharStar(readline("Write something: "));

        IF Length(input) > 0 THEN
           WriteString("You Wrote: ");
           CopyOut(temp, input);

           WriteString(temp);
           WriteLn;
           add_history(temp);
        ELSE
           WriteString("No input");
           WriteLn;
        END;
        Fin(input);
     END;

  END rl_test.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  I expected that this would result in something like the following:

  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Write something: foo
  You Wrote: foo
  Write something: bar
  You Wrote: bar
  Write something:
  No input
  Write something: bar
  You Wrote: bar
  Write something: quux
  You Wrote: quux
  Write something: exit
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  However, the output I actually got was:

  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Write something: foo
  Write something: bar
  Write something:
  Write something: bar
  Write something: quux
  Write something: exit
  You Wrote: foo
  You Wrote: bar
  No input
  You Wrote: bar
  You Wrote: quux
  You Wrote: exit
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  So my issue is, why is the response not getting flushed until after the input 
is completed?

  Oddly enough, when I add

  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FROM InOut IMPORT WriteCard;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  and insert this following the input but before the IF statement:
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        WriteCard(Length(input), 3);
        WriteLn;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  The result is different:

  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Write something: foo
    3Write something: bar

  You Wrote: foo
    3Write something:

  You Wrote: bar
    0Write something: bar

  No input
    3Write something: quux

  You Wrote: bar
    4Write something: exit

  You Wrote: quux
    4
  You Wrote: exit
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Why this particular delayed interleaving is happening, and why the WriteLn is 
getting ignored,  is puzzling to me.

  Is there some known issue with interfacing the C libraries, or the Readline 
library specifically, that I need to be aware of?
Hi Alice,

yes the modula-2 libraries contain their own buffer which would need to
be flushed prior to using another C library.  I've added a
FIO.FlushOutError before the call to reaadline which does the trick:

MODULE rl_test;

FROM SYSTEM IMPORT ADDRESS;

FROM DynamicStrings IMPORT String, Fin, Length, InitString,
                            InitStringCharStar, CopyOut, Equal,
                            EqualArray, string ;

FROM StrIO IMPORT WriteString, WriteLn;

FROM readline IMPORT readline, add_history;
FROM FIO IMPORT FlushOutErr ;
FROM libc IMPORT printf ;

VAR
    input: String;
    temp : ARRAY [0..1024] OF CHAR;
BEGIN
    input := NIL ;
    REPEAT
       Fin(input);
       FlushOutErr ;
       input := InitStringCharStar (readline ("Write something: "));
       IF Length(input) > 0 THEN
          WriteString("You Wrote: ");
          CopyOut(temp, input);

          WriteString(temp);
          WriteLn;
          add_history(temp);
       ELSE
          WriteString("No input");
          WriteLn;
       END;
    UNTIL EqualArray (input, "exit")
END rl_test.


regards,
Gaius

Attachment: FlushStdOut.f90
Description: Text Data

Attachment: FlushStdOut.def
Description: Text document

Attachment: FlushStdOut.txt
Description: Text document


reply via email to

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