Re: MPlib: detect bye/end

Nicola <[email protected]>
Newsgroups gmane.comp.tex.metapost
Message-ID <[email protected]>
On 15/12/2016 12:48, luigi scarso wrote:
> On Fri, Dec 9, 2016 at 11:50 AM, Nicola <[email protected]> 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





--
http://tug.org/metapost/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.