/*
* Simple example to call Mathematica to generate a PostScript plot.
*
* For a final program, you would have to include a number of other
* elements, in particular, error recovery from this program is poor.
*
* We use the Enter function to give strings to the kernel.
*

* Original program written for Mathematica 2.1.
* Updated for Mathematica 3.0 by
* Kevin Leuthold, Wolfram Research on 12/12/97.
*

* To build this program, use the instructions in the MathLink Developer's
* Guide for building factor with your particular compiler - substitute
* this file for factor.c.

*  To run this program use the command-line below:
*      Unix:           psgen -linkname "math -mathlink"
*      Mac or Windows: psgen -linklaunch
*/

#include <stdio.h>
#include <stdlib.h>
#include "mathlink.h"

#if MACINTOSH_MATHLINK
extern int mlmactty_init( char*** argvp);
#endif

MLENV env = (MLENV)0;
MLINK kernel_link = (MLINK)0;

static void init_and_openlink( int argc, char* argv[]);
static void exit_and_deinit( );

int main(int argc, char* argv[]){
 long length;
 const unsigned char* postline;
 int p, res;

 init_and_openlink( argc, argv);

 MLPutFunction(kernel_link, "Enter", 1);
 MLPutString(kernel_link, "<< PSDirect.m");
 MLEndPacket(kernel_link);

 /* Now give Mathematica the Plot command */
 MLPutFunction(kernel_link, "Enter", 1);
 MLPutString(kernel_link, "Plot3D[Sin[x Cos[y]],{x,0,Pi},{y,0,Pi}]");
 MLEndPacket(kernel_link);

 /* Pick up the Display. Notice that if we were writing a full
    program, we would want to pick up all output, so we could tell
    if the file load failed */

 while ((p = MLNextPacket(kernel_link), p) && p != DISPLAYPKT) {
    MLNewPacket(kernel_link);
    if (p == 0) {
       fprintf (stdout, "error is %d\n", MLError(kernel_link));
       exit_and_deinit();
    }
 }

 /* Now we read in all packets, looking for a DISPLAYENDPKT */

 while( p != DISPLAYENDPKT){
       res = MLGetByteString(kernel_link, &postline, &length, 255);
       if (res == 0) {
       fprintf (stdout, "error is %d\n", MLError(kernel_link));
               exit_and_deinit();
       }
       fprintf (stdout, "%s", postline);
       MLDisownByteString( kernel_link, postline, length);
       p = MLNextPacket(kernel_link);
 }

 MLClose(kernel_link);
 MLDeinitialize( env);

 return 0;
}

static void exit_and_deinit( ){
       if( kernel_link) MLClose( kernel_link);
       if( env) MLDeinitialize( env);
       exit( 0);
}

static void init_and_openlink( int argc, char* argv[])
{
       long err;

#if MACINTOSH_MATHLINK
       MLYieldFunctionObject yielder;
       argc = mlmactty_init( &argv);
#endif

       env =  MLInitialize( 0);
       if( env == (MLENV)0) exit_and_deinit();

#if MACINTOSH_MATHLINK
       yielder = MLCreateYieldFunction( env, NewMLYielderProc(
MLDefaultYielder), 0);
#endif

       kernel_link = MLOpenArgv( env, argv, argv + argc, &err);
       if(kernel_link == (MLINK)0) exit_and_deinit();

#if MACINTOSH_MATHLINK
       MLSetYieldFunction( kernel_link, yielder);
#endif

}