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