[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