[metapost] MPlib: detect bye/end
Nicola
nvitacolonna at gmail.com
Thu Dec 15 15:23:42 CET 2016
On 15/12/2016 12:48, luigi scarso wrote:
> On Fri, Dec 9, 2016 at 11:50 AM, Nicola <nvitacolonna at gmail.com> wrote:
>> Hello,
>> when running a non-interactive MP instance, how can I detect that the last
>> executed command was `bye`, `end` or something that causes MetaPost to quit?
>>
>> For instance, after
>>
>> char *line = "bye."
>> int history = mp_execute(mp, line, strlen(line));
>>
>> mp_rundata(mp) returns non-zero size data (it returns zero-size data if I
>> execute another command).
>>
>> Nicola
>>
>> --
>> http://tug.org/metapost/
>
> The effect of scanning an "end" are the following calls:
>
> mp_final_cleanup (mp);
>
>
> │
> mp_close_files_and_terminate (mp);
>
> The last one ends with
> mp->finished = true;
>
> As first step mp_execute resets the streams, and if mp->finished =
> true then returns
>
>
> @ @c
> int mp_execute (MP mp, char *s, size_t l) {
> mp_reset_stream (&(mp->run_data.term_out));
> mp_reset_stream (&(mp->run_data.log_out));
> mp_reset_stream (&(mp->run_data.error_out));
> mp_reset_stream (&(mp->run_data.ship_out));
> if (mp->finished) {
> return mp->history;
>
>>From now whatever string is put into execute, the streams data are
> NULL and nothing is executed.
> We can execute a test string like "tracingall;tracingnone;": before
> and "end" this should put something into one stream,
> and if all the streams data are still NULL then we have already
> executed an "end" .
> Of course to execute a string we need a valid mp state .
>
> static char *tracingall =
> "tracingonline:=1; showstopping:=1;"
> "tracingcommands:=3; tracingtitles:=1; tracingequations:=1;"
> "tracingcapsules:=1; tracingspecs:=2; tracingchoices:=1; tracinglostchars:=1;"
> "tracingstats:=1; tracingoutput:=1; tracingmacros:=1; tracingrestores:=1;";
> static int strlen_tracingall=240;
>
> static char *tracingnone =
> "tracingcommands:=0; tracingtitles:=0; tracingequations:=0;"
> "tracingcapsules:=0; tracingspecs:=0; tracingchoices:=0; tracinglostchars:=0;"
> "tracingstats:=0; tracingoutput:=0; tracingmacros:=0; tracingrestores:=0;";
> static int strlen_tracingnone=206;
>
> int check_after_end_mp(MP mp)
> {
> mp_run_data *cmd_result ;
> int ret;
> ret = -1 ;
> if (mp==NULL)
> return ret;
> ret = 0;
> mp_execute(mp, tracingall, strlen_tracingall);
> cmd_result = mp_rundata(mp);
> if ( cmd_result->term_out.data == NULL &&
> cmd_result->error_out.data == NULL &&
> cmd_result->log_out.data == NULL &&
> cmd_result->ship_out.data == NULL )
> ret = 1;
> mp_execute(mp, tracingnone, strlen_tracingnone);
> return ret ;
> }
>
> MetaPost rev. 2107 has a new function mp_finished that returns
> mp->finished as boolean,
> so one can avoid the two calls of mp_execute
>
> int check_after_end_mp(MP mp)
> {
> mp_run_data *cmd_result ;
> int ret;
> ret = -1 ;
> if (mp==NULL)
> return ret;
> ret = 0;
> cmd_result = mp_rundata(mp);
> if ( mp_finished(mp) &&
> cmd_result->term_out.data == NULL &&
> cmd_result->error_out.data == NULL &&
> cmd_result->log_out.data == NULL &&
> cmd_result->ship_out.data == NULL )
> ret = 1;
> return ret ;
> }
Thanks for the thorough explanation. Is it really necessary to check all
the streams?
What I'm doing now is somewhat simpler:
mp_execute(imp, "\\", 1); // Send a token that expands to nothing
mp_run_data *cmd_result = mp_rundata(imp);
if (!cmd_result || !cmd_result->term_out.size) {
return 0; // Quit
}
This seems to work, but I guess that it is not robust enough. In which
case would it fail to recognize that it's time to quit (please note that
I'm using this in a REPL)?
Nicola
More information about the metapost
mailing list