[GiNaC-list] Making ginsh interactive when the input is not a TTY
Vitaly Magerya
vmagerya at gmail.com
Mon Jun 12 10:51:20 CEST 2023
Hi, all. I've been trying to use ginsh as a subprocess: send some
input to it, have it evaluate it, read the result back, repeat.
I've found that this is impossible: in ginsh/ginsh_lexer.lpp:161
if yy_is_interactive (=isatty(0)) is false, ginsh uses fread()
to read the input, which means it will not stop after end of
the line -- it will instead wait until the whole buffer is
filled, and will only proceed to parse and evaluate afterwards.
This means I can not send "1+2\n" and expect an answer,
ginsh will wait for more input. This of course is unlike the
interactive mode (yy_is_interactive == 1), where the input is
read character-by-character until the end of line.
So, basically, I'd like ginsh to use the interactive(-ish) mode
even when the input stream is not a TTY.
Now, just forcing yy_is_interactive to 1 will work, but is not
a good solution: the interactive mode prints the prompt after
each line, so using it when the input stream is not a TTY will
break backward compatibility. Instead, something like this will
work for me:
diff --git a/ginsh/ginsh_lexer.lpp b/ginsh/ginsh_lexer.lpp
index 8692b1ac..a8d571dd 100644
--- a/ginsh/ginsh_lexer.lpp
+++ b/ginsh/ginsh_lexer.lpp
@@ -203,9 +203,16 @@ static int ginsh_input(char *buf, int max_size)
YY_FATAL_ERROR("input in flex scanner failed");
result = n;
#endif
- } else if (((result = fread(buf, 1, max_size, yyin)) == 0) &&
ferror(yyin))
- YY_FATAL_ERROR("input in flex scanner failed");
-
+ } else {
+ int c = '*', n;
+ for (n = 0; n < max_size && (c = getc(yyin)) != EOF &&
c != '\n'; ++n)
+ buf[n] = (char)c;
+ if (c == '\n')
+ buf[n++] = (char)c;
+ if (c == EOF && ferror(yyin))
+ YY_FATAL_ERROR("input in flex scanner failed");
+ result = n;
+ }
return result;
}
This will preserve backward compatibility.
There is however a concern that such a change will affect
the parsing performance, so I've run tests: when evaluating
some of my multi-MB expression files with mixed arithmetic,
there is no statistically visible performance difference. For
a synthetic test of a product of 10^6 of single-digit numbers
with 6 white-space characters per digit per -- no change. For a
sum of 10^6 single-digit integers with 6 spaces per integer I
see a 9% runtime regression; if the whitespace is removed, the
regression disappears. In short, I think the performance impact
in practice is zero.
Can I ask for this change to be applied?
More information about the GiNaC-list
mailing list