package org.jmlspecs.openjml.utils;
import org.jmlspecs.annotation.Nullable;
import org.jmlspecs.openjml.proverinterface.ProverException;
/** This class interface the Java functionality to spawn external processes,
* reading the external process's output and error
* streams. There are two ways to use this class.
* <P>
* <B>Execute to completion (non-interactive):</B>
* <UL>
* <LI>Create an ExecProcess with the 'prompt' argument set to null.
* <LI>Call start()
* <LI>Send any input, using send(). Skip this step if the executable is not
* expecting any input.
* <LI>Call readToCompletion(). It will block until the process is finished.
* The return value is the exit value of the external process.
* <LI>Use outputString.toString() and errorString.toString() to get the
* outputs from the external process.
* </UL>
* <B>Execute interactively:</B> The model is that the external process accepts
* input and responds with output, ending in a prompt. So the output reader
* accumulates the output and terminates with the prompt sequence is seen.
* The error reader is then terminated as well, given a bit of an opportunity
* to read anything in its stream.
* The reader expects the prompt to be at the end of the output; if the prompt
* sequence is within the output, the reader may or may not terminate.
* <UL>
* <LI>Create an ExecProcess with the desired prompt string
* <LI>Call start()
* <LI>Call eatPrompt() to consume the first prompt after starting the process.
* Use outputString.toString() and errorString.toString() to get the
* outputs from the external process.
* <LI>Repeat:
* <UL>
* <LI> Call send() to send input to the external process
* <LI> Call eatPrompt() to get output and consume the prompt.
* Use outputString.toString() and errorString.toString() to get the
* outputs from the external process.
* </UL>
* <LI> To terminate: Either send input (using send()) that terminates the
* process, or call kill().
* </UL>
*
*
* @author David Cok
*
*/
public interface IExternalProcess {
/** Returns the stored executable command line */
public abstract String[] app();
/** Returns the prover-specific prompt string that the eatPrompt method
* should look for.
* @return the prompt string
*/
public @Nullable
abstract String prompt();
/** Starts the executable and the threads that read the executable's output;
* the StringBuilders are reset to empty to start with. */
public abstract void start() throws ProverException;
/** Ends the external process */
public abstract void kill();
/** Does the actual work of sending information to the prover process. You
* need to call eatPrompt for each newline you send. This method does not
* add any newlines to the supplied String.
* @param s the String to send
* @throws ProverException if something goes wrong
*/
public abstract void send(String s) throws ProverException;
/** Waits for the external process to complete, reading the output along
* the way; expects 'prompt' to be null.
* @return
*/
public abstract int readToCompletion() throws ProverException;
/** Reads output from the external process until the regular output is
* waiting for more input, but sees the prompt sequence at the end of the
* output already seen. Returns the regular output; error output is
* available using errorString.toString()
* @throws ProverException
*/
public abstract String eatPrompt() throws ProverException;
// /** Returns the regular output from the most recent eatPrompt or
// * readToCompletion call
// */
// public abstract String output();
//
// /** Returns the error output from the most recent eatPrompt or
// * readToCompletion call
// */
// public abstract String errorOutput();
}