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: Gaius Mulley
Subject: Re: Problems Interfacing Modula-2 with GNU Readline library
Date: Tue, 05 Mar 2024 10:18:02 +0000
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux)

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



reply via email to

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