/*************************************************************************

        Copyright 1986 through 1993 by Wolfram Research Inc.
        All rights reserved

$Id: mathlink.h,v 1.36.2.1 1993/04/07 22:50:53 rory Exp $

*************************************************************************/

#ifndef _MATHLINK_H
#define _MATHLINK_H

#ifdef __cplusplus
extern "C" {
#endif



/* edit both here and in platform.h */
#if (defined(applec) || defined(THINK_C)) && !defined(MACINTOSH)
#  define MACINTOSH
#endif

#if !defined(MACINTOSH) && !defined(WIN16) && !defined(WIN32)
#  define UNIX
#endif



/* edit both here and in proto.h */
#ifndef P
#  if defined(__STDC__) || defined(__cplusplus) || defined(MACINTOSH) || defined( WIN16) || defined( WIN32)
#    define P(s) s
#  else
#    define P(s) ()
#  endif
#endif



/* edit both here and in _utils.h */
#if defined( __STDC__) || defined(__cplusplus) || defined(MACINTOSH)
#define ml_extended long double
#else
#define ml_extended double
#define ML_EXTENDED_IS_DOUBLE
#endif




#ifndef NULL
#define NULL ((void *) 0)
#endif


#ifdef WIN16
# include	<windows.h>
# ifndef APIENTRY
#   define APIENTRY far pascal
# endif
# define CB APIENTRY
# define MLAPI APIENTRY
  typedef LPSTR MLEnvironment;
  typedef LPSTR MLPointer;
  typedef LPSTR MLBuffer;
  typedef LPSTR FAR* MLBufferArray;
#else
# define CB
# define MLAPI
  typedef void* MLEnvironment;
  typedef void* MLPointer;
  typedef char* MLBuffer;
  typedef char** MLBufferArray;
#endif
typedef MLPointer (CB *MLallocator) P((unsigned long));
typedef void (CB *MLdeallocator) P((MLPointer));


/* --binding layer-- */
/*************** Starting MathLink ***************/

typedef struct MLParameters {
	short version; /* must be zero! */
	MLallocator allocator; /* both NULL or both non-NULL */
	MLdeallocator deallocator;
} MLParameters;


extern MLEnvironment MLAPI MLInitialize P(( MLParameters* )); /* pass in NULL */
extern void MLAPI MLDeinitialize P((MLEnvironment env));

/* or, if you use MLBeginInEnv, ...*/

extern MLEnvironment MLAPI MLBegin P(( MLParameters* )); /* pass in NULL */
extern void MLAPI MLEnd P(( MLEnvironment env));


/*************** Connection interface ***************/

typedef struct MLink *MLINK;

extern MLINK MLAPI MLOpen P(( int, char**));
extern MLINK MLAPI MLOpenInEnv P(( MLEnvironment, int, char**, long* ));
extern int   MLAPI MLConnect P((MLINK));
extern int   MLAPI MLFlush P((MLINK));
extern int   MLAPI MLReady P((MLINK));
extern void  MLAPI MLClose P((MLINK));

extern void  MLAPI MLSetUserData P(( MLINK, void*, void (CB *) P((MLINK)) ));
extern void* MLAPI MLUserData P(( MLINK , void (**) P((MLINK)) ));



/* MLName returns a pointer to the link's name.
 * Links are generally named when they are created
 * and are based on information that is potentially
 * useful and is available at that time.
 * Do not attempt to deallocate the name's storage
 * through this pointer.  The storage should be
 * considered in read-only memory.
 */
extern char* MLAPI MLName P((MLINK));





/* The following functions and defines are
 * currently for internal use only.
 */

/* edit here and in _devtype.h */
#define MLNetworkVisibleMask	((unsigned long)0x00000003)
#define MLBrowseMask		((unsigned long)0x00000010)
#define MLNonBlockingMask	((unsigned long)0x00000020)
#define MLInteractMask		((unsigned long)0x00000100)
#define MLVersionMask		((unsigned long)0x0F000000)

#define MLDefaultOptions  ((unsigned long)0x00000000)


#define MLNetworkVisible	((unsigned long)0x00000000)
#define MLLocallyVisible	((unsigned long)0x00000001)
#define MLInternetVisible	((unsigned long)0x00000002)

#define MLBrowse		((unsigned long)0x00000000)
#define MLDontBrowse		((unsigned long)0x00000010)

#define MLNonBlocking		((unsigned long)0x00000000)
#define MLBlocking		((unsigned long)0x00000020)

#define MLInteract		((unsigned long)0x00000000)
#define MLDontInteract		((unsigned long)0x00000100)




/*************** encoding layer -- for internal use only ***************/

extern MLPointer MLAPI MLInit P(( int version, MLallocator alloc, MLdeallocator dealloc));
extern void  MLAPI MLDeinit P(( MLPointer env));
struct _MLink;
extern MLINK MLAPI MLmake P(( MLPointer env, struct _MLink* _mlp, char* name, long* errp));


extern int   MLAPI MLFill P((MLINK));
extern int   MLAPI MLNumber P((MLINK));
extern char* MLAPI MLSetName P(( MLINK, char* ));



/*************** Textual interface ***************/

#define	MLTKSYM		'Y'		/* symbol leaf node */
#define	MLTKSTR		'S'		/* string leaf node */
#define	MLTKINT		'I'		/* integer leaf node */
#define	MLTKREAL	'R'		/* real leaf node */
#define	MLTKFUNC	'F'		/* non-leaf node */
#define	MLTKPCTEND	']'		/* at end of top level expression */
#define	MLTKERROR	(0)		/* bad token */

extern int   MLAPI MLGetNext P((MLINK));
extern int   MLAPI MLGetType P((MLINK));
extern int   MLAPI MLGetData P((MLINK, char*, long, long* ));
extern int   MLAPI MLGetArgCount P((MLINK, long* ));
extern int   MLAPI MLBytesToGet P((MLINK, long* ));

extern int   MLAPI MLPutNext P((MLINK, int));
extern int   MLAPI MLPutSize P((MLINK, long));
extern int   MLAPI MLPutData P((MLINK, char *, long));
extern int   MLAPI MLPutArgCount P((MLINK, long));
extern int   MLAPI MLBytesToPut P((MLINK, long*));

/* MLTKEND, MLTKAEND, MLTKELEN, and MLTKINIT are for internal use only */
#define	MLTKEND		'\n'
#define	MLTKAEND	'\r'
#define	MLTKELEN	' '
#define	MLTKINIT	'M'

/*************** Native C types interface ***************/

/* The functions MLGetString, MLGetSymbol, MLGetString,
 * MLGetFunction, MLGetIntegerList, and
 * MLGetRealList return a pointer to a buffer inside
 * of MathLink.  This buffer should be considered read-
 * only and must be returned to MathLink when you are
 * through using it.  MathLink is only lending you
 * access to its internal data.  You MUST not free
 * this buffer as it may not have been allocated on
 * the free store.  You should not change the contents
 * of the buffer as the data may be used elsewhere
 * within MathLink or elsewhere in your program.
 * For example:
 *	f(){
 *		char* s;
 *		...
 *		if( MLGetSymbol(stdlink, &s) ){
 *			deal_with_symbol(s);
 *			MLDisownSymbol(stdlink, s);
 *		}
 *		...
 * 	}
 */

extern int   MLAPI MLGetShortInteger P(( MLINK, short* ));
extern int   MLAPI MLGetInteger      P(( MLINK, int* ));
extern int   MLAPI MLGetLongInteger  P(( MLINK, long* ));
extern int   MLAPI MLGetFloat        P(( MLINK, float* ));
extern int   MLAPI MLGetReal         P(( MLINK, double* ));
extern int   MLAPI MLGetDouble       P(( MLINK, double* ));
#define      MLGetReal( mlp, xp) MLGetDouble(mlp, xp)

extern int   MLAPI MLGetString     P(( MLINK, char** ));
extern void  MLAPI MLDisownString  P(( MLINK, char* ));
extern int   MLAPI MLGetSymbol     P(( MLINK, char** ));
extern int   MLAPI MLGetFunction   P(( MLINK, char**, long* ));
extern void  MLAPI MLDisownSymbol  P(( MLINK, char* ));

extern int   MLAPI MLCheckFunction   P(( MLINK, char*, long* ));
extern int   MLAPI MLCheckFunctionWithArgCount P(( MLINK, char*, long* ));


extern int   MLAPI MLGetIntegerList    P(( MLINK, int**, long* ));
extern void  MLAPI MLDisownIntegerList P(( MLINK, int*, long ));
extern int   MLAPI MLGetRealList       P(( MLINK, double**, long* ));
extern void  MLAPI MLDisownRealList    P(( MLINK, double*, long ));


extern int   MLAPI MLPutShortInteger   P(( MLINK, int ));
extern int   MLAPI MLPutInteger     P(( MLINK, int ));
extern int   MLAPI MLPutLongInteger P(( MLINK, long ));

extern int   MLAPI MLPutFloat       P(( MLINK, double ));
extern int   MLAPI MLPutReal        P(( MLINK, double ));
extern int   MLAPI MLPutDouble      P(( MLINK, double ));
#define      MLPutReal( mlp, x) MLPutDouble(mlp, x)

extern int   MLAPI MLPutString  P(( MLINK, char* ));
extern int   MLAPI MLPutSymbol  P(( MLINK, char* ));

#define	    MLPutExpression( mlp, argn) is obsolete, use \
		(MLPutNext( mlp, MLTKFUNC) \
		&& MLPutArgCount( mlp, argn))

extern int   MLAPI MLPutComposite P(( MLINK, long ));
extern int   MLAPI MLPutFunction P(( MLINK, char*, long ));

extern int   MLAPI MLPutIntegerList P(( MLINK, int*, long));
extern int   MLAPI MLPutRealList P(( MLINK, double*, long));


/*************** Mathematica packet interface ***************/

extern int  MLAPI MLNextPacket P((MLINK));
			/* get the next packet, return one of... */

#define ILLEGALPKT      0

#define CALLPKT         7
#define EVALUATEPKT    13
#define RETURNPKT       3

#define INPUTNAMEPKT    8
#define ENTERTEXTPKT   14
#define ENTEREXPRPKT   15
#define OUTPUTNAMEPKT   9
#define RETURNTEXTPKT   4
#define RETURNEXPRPKT  16

#define DISPLAYPKT     11
#define DISPLAYENDPKT  12

#define MESSAGEPKT      5
#define TEXTPKT         2

#define INPUTPKT        1
#define INPUTSTRPKT    21
#define MENUPKT         6
#define SYNTAXPKT      10

#define SUSPENDPKT     17
#define RESUMEPKT      18

#define BEGINDLGPKT    19
#define ENDDLGPKT      20

#define FIRSTUSERPKT  128
#define LASTUSERPKT   255

extern int  MLAPI MLNewPacket P((MLINK));
			/* skip to the end of the current packet */

extern int  MLAPI MLEndPacket P((MLINK));
			/* send an end-of-packet marker */

/*************** Template interface ***************/

/* The following are useful only when using template files as
 * their definitions are produced by mprep.
 */

extern MLINK	stdlink;
extern int	MLMain P((int, char**)); /* pass in argc and argv */

extern int	MLInstall P((MLINK));
extern int	MLAnswer P((MLINK));
extern int	MLDoCallPacket P((MLINK));
extern int	MLEvaluate P(( MLINK, char* ));
extern void	MLDefaultHandler P(( MLINK, unsigned long, unsigned long));

extern int	MLAbort, MLDone;

#ifdef ML_OBSOLETE
/* Use MLAnswer and MLDoCallPacket */
extern int	MLMainStep P((MLINK));
#endif

/*************** Experimental enhancements ***************/

extern int   MLAPI MLPutIntegerArray
	P(( MLINK mlp, int* data, long* dims, char** heads, long depth));

extern int   MLAPI MLPutShortIntegerArray
	P(( MLINK mlp, short* data, long* dims, char** heads, long depth));

extern int   MLAPI MLPutLongIntegerArray
	P(( MLINK mlp, long* data, long* dims, char** heads, long depth));

extern int   MLAPI MLPutDoubleArray
	P(( MLINK mlp, double* data, long* dims, char** heads, long depth));

extern int   MLAPI MLPutFloatArray
	P(( MLINK mlp, float* data, long* dims, char** heads, long depth));



extern int   MLAPI MLGetIntegerArray
	 P(( MLINK mlp, int **data, long **dims, char ***heads, long *depth));
extern void  MLAPI MLDisownIntegerArray P(( MLINK, int*, long*, char**, long));

extern int   MLAPI MLGetShortIntegerArray
	 P(( MLINK mlp, short **data, long **dims, char ***heads, long *depth));
extern void  MLAPI MLDisownShortIntegerArray P(( MLINK, short*, long*, char**, long));

extern int   MLAPI MLGetLongIntegerArray
	 P(( MLINK mlp, long **data, long **dims, char ***heads, long *depth));
extern void  MLDisownLongIntegerArray P(( MLINK, long*, long*, char**, long));


extern int   MLAPI MLGetDoubleArray
	P(( MLINK mlp, double** data, long** dims, char*** heads, long* depth));
extern void  MLDisownDoubleArray P(( MLINK, double*, long*, char**, long));

extern int   MLAPI MLGetFloatArray
	P(( MLINK mlp, float** data, long** dims, char*** heads, long* depth));
extern void  MLAPI MLDisownFloatArray P(( MLINK, float*, long*, char**, long));

/*NOPRE*/
extern int   MLAPI MLGetLongDouble  P(( MLINK mlp, ml_extended* xp));
extern int   MLAPI MLPutLongDouble  P(( MLINK mlp, ml_extended x));
extern int   MLAPI MLPutLongDoubleArray
	P(( MLINK mlp, ml_extended* data, long* dims, char** heads, long depth));
extern int   MLAPI MLGetLongDoubleArray
	P(( MLINK mlp, ml_extended** data, long** dims, char*** heads, long* depth));
extern void  MLAPI MLDisownLongDoubleArray P(( MLINK, ml_extended*, long*, char**, long));
/*ENDNOPRE*/


#ifdef ML_OBSOLETE
#define MLEchoExpression MLTransferExpression
#endif
extern int MLAPI MLTransferExpression P(( MLINK dmlp, MLINK smlp));

/*************** Message interface ***************/
typedef void (CB *MLMessageHandlerType) P((MLINK, unsigned long, unsigned long));

enum {	MLTerminateMessage = 1, MLInterruptMessage, MLAbortMessage,
	MLEndPacketMessage, MLSynchronizeMessage, MLImDyingMessage,
	MLWaitingAcknowledgment,
	MLFirstUserMessage = 128, MLLastUserMessage = 255 };

extern int   MLAPI MLPutMessage P(( MLINK, unsigned long));
extern int   MLAPI MLMessageReady P(( MLINK mlp));
extern int   MLAPI MLGetMessage P(( MLINK, unsigned long *, unsigned long *));

extern MLMessageHandlerType MLAPI MLMessageHandler P((MLINK mlp));
extern int   MLAPI MLSetMessageHandler P((MLINK mlp, MLMessageHandlerType h));


#ifdef ML_OBSOLETE
extern int MLCheck P(( MLINK mlp));
#if defined(__cplusplus) || defined(THINK_C)
extern int   MLAPI MLGetMessageHandler P(( ...));
extern int   MLAPI MLSetSignalHandler P(( ...));
#else
extern int   MLAPI MLGetMessageHandler P(());
extern int   MLAPI MLSetSignalHandler P(());
#endif
#endif
/*************** Threads interface ***************/
typedef struct MLYieldParams * MLYieldParameters;
typedef int (CB *MLYieldFunctionType) P((MLINK, MLYieldParameters));

extern MLYieldFunctionType MLAPI MLYieldFunction P(( MLINK mlp));
extern int   MLAPI MLSetYieldFunction P((  MLINK mlp, MLYieldFunctionType yf));

/* the following two functions are for internal use only */
extern MLYieldFunctionType MLAPI MLDefaultYieldFunction P(( MLEnvironment env));
extern int MLAPI MLSetDefaultYieldFunction P((  MLEnvironment env, MLYieldFunctionType yf ));

#ifdef ML_OBSOLETE
#if defined(__cplusplus) || defined(THINK_C)
extern int   MLAPI MLGetYieldFunction P(( ...));
#else
extern int   MLAPI MLGetYieldFunction P(());
#endif
#endif

/*************** MathLink errors ***************/
/*
 * When some problem is detected within MathLink, routines
 * will return a simple indication of failure and store
 * an error code internally. (For routines that have nothing
 * else useful to return, success is indicated by returning
 * non-zero and failure by returning 0.)  MLerror() returns
 * the current error code;  MLErrorMessage returns an English
 * language description of the error.
 * The error MLEDEAD is irrecoverable.  For the others, MLClearError()
 * will reset the error code to MLEOK.
 */

extern int   MLAPI MLError P((MLINK));
			 /* return link error code */
extern int   MLAPI MLClearError P((MLINK));
			 /* reset errno to MLEOK, if possible */
extern int   MLAPI MLSetError P((MLINK, int));
			 /* set errno if currently MLEOK */
extern char* MLAPI MLErrorMessage P((MLINK));

#define	MLEUNKNOWN	-1	/* unknown error */
#define	MLEOK		0	/* everything ok so far */
#define	MLEDEAD		1	/* link died -- unrecoverable error */
#define	MLEGBAD		2	/* inconsistent data was read */
#define	MLEGSEQ		3	/* MLGet? out of sequence */
#define	MLEPBTK		4	/* MLPutNext() was passed a bad token */
#define	MLEPSEQ		5	/* MLPut? out of sequence */
#define	MLEPBIG		6	/* MLPutData given too much data */
#define	MLEOVFL		7	/* machine integer overflow */
#define	MLEMEM		8	/* out of memory */
#define	MLEACCEPT	9	/* failure to accept socket connection */
#define	MLECONNECT	10	/* a deferred connection is
				 * still unconnected
				 */
#define	MLECLOSED	11	/* the other side closed the link, you may
				 * still get undelivered data
				 */

#define	MLEPUTENDPACKET	 21
		/* unexpected call of MLEndPacket; currently atoms aren't
		 * counted on the way out so this error is raised only when
		 * MLEndPacket is called in the midst of an atom
		 */
#define	MLENEXTPACKET	22
		/* MLNextPacket called while the current packet has
		 * unread data
		 */
#define	MLEUNKNOWNPACKET 23
		/* MLNextPacket read in an unknown packet head */
#define	MLEGETENDPACKET  24	 /* unexpected end-of-packet token */
#define MLEABORT         25	 /* a put or get was aborted before
				  * affecting the link
				  */

#define	MLEINIT		32	/* the MathLink environment was not initialized */
#define	MLEARGV		33	/* insufficient arguments to open the link */
#define	MLEPROTOCOL	34	/* protocol unavailable */
#define	MLEMODE		35	/* mode unavailable */
#define	MLELAUNCH	36	/* launch unsupported */
#define	MLELAUNCHAGAIN	37	/* cannot launch the program again from the same file */
#define	MLELAUNCHSPACE	38	/* insufficient space to launch the program */
#define	MLENOPARENT	39	/* found no parent to connect to */
#define	MLENAMETAKEN	40	/* the linkname was already in use */
#define	MLENOLISTEN	41	/* the linkname was not found to be listening */
#define	MLEBADNAME	42	/* the linkname was missing or not in the proper form */
#define	MLEBADHOST	43	/* the location was unreachable or not in the proper form */

#define	MLEUSER        1000	 /* start of user defined errors */


/*************** User interaction--for internal use only ***************/

typedef void (CB *MLAlertFunctionType) P((MLEnvironment env, MLBuffer message));
typedef MLBuffer (CB *MLRequestFunctionType) P((MLEnvironment env, MLBuffer prompt, MLBuffer response, long sizeof_response));
typedef int (CB *MLConfirmFunctionType) P((MLEnvironment env, MLBuffer question, int default_answer));
typedef int (CB *MLRequestArgvFunctionType) P((MLEnvironment env,  MLBufferArray argv, int cardof_argv, MLBuffer buf, int sizeof_buf));
typedef int (CB *MLRequestToInteractFunctionType) P((MLEnvironment env, int wait_for_permission));
typedef void (CB *MLDialogFunctionType) P(( MLEnvironment env));


enum {	MLAlertFunction = 1, MLRequestFunction, MLConfirmFunction,
	MLRequestArgvFunction, MLRequestToInteractFunction };

extern void MLAPI MLAlert
	P(( MLEnvironment env, char* message));

extern char* MLAPI MLRequest
	P(( MLEnvironment env, char* prompt, char* response /* initialized to default*/, long len ));

extern int MLAPI MLConfirm
	P(( MLEnvironment env, char* question, int defaultanswer ));

extern int MLAPI MLRequestArgv
	P(( MLEnvironment env, char* argv[], int len, char* buff, int size));

extern int MLAPI MLRequestToInteract
	P(( MLEnvironment env, int wait));

#define ML_DEFAULT_DIALOG ( (MLDialogFunctionType) 1)
#define ML_IGNORE_DIALOG ( (MLDialogFunctionType) 0)

extern int MLAPI MLSetDialogFunction P(( MLEnvironment ep, int funcnum, MLDialogFunctionType func ));


/*************** 2.2 experimental enhancements ***************/
/* in response to a reset message */
void MLAPI MLForwardReset P((MLINK mlp, unsigned long marker));

typedef struct MLinkMark* MLINKMark;
extern MLINKMark  MLAPI MLCreateMark P(( MLINK mlp ));
extern MLINKMark  MLAPI MLSeekToMark P(( MLINK mlp , MLINKMark mark, long index));
extern void       MLAPI MLDestroyMark P(( MLINK mlp , MLINKMark mark));

extern int  MLAPI MLNewExpression P(( MLINK mlp));
extern MLINK MLAPI MLDuplicateLink P(( MLINK parent_mlp, char* name, long* errp ));

/* values returned by selector DEVICE_TYPE */
#define UNREGISTERED_TYPE	0
#define UNIXPIPE_TYPE	1
#define UNIXSOCKET_TYPE 2
#define PPC_TYPE	3
#define MACTCP_TYPE	4
#define LOOPBACK_TYPE	5
#define COMMTB_TYPE	6
#define ADSP_TYPE	7
#define LOCAL_TYPE	8
#define WINLOCAL_TYPE	9

/* selectors */
#define DEVICE_TYPE 0                                       /* int */
#define DEVICE_NAME 1                                       /* char */
#define PIPE_FD                (UNIXPIPE_TYPE * 256 + 0)    /* int */
#define PIPE_CHILD_PID         (UNIXPIPE_TYPE * 256 + 1)    /* int */
#define SOCKET_FD              (UNIXSOCKET_TYPE * 256 + 0)  /* int */
#define SOCKET_PARTNER_ADDR    (UNIXSOCKET_TYPE * 256 + 1)  /* unsigned long */
#define SOCKET_PARTNER_PORT    (UNIXSOCKET_TYPE * 256 + 2)  /* unsigned short */
#define PPC_SESS_REF_NUM       (PPC_TYPE * 256 + 0)         /* PPCSessRefNum */
#define PPC_PARTNER_PSN        (PPC_TYPE * 256 + 1)         /* ProcessSerialNumber */
#define PPC_PARTNER_LOCATION   (PPC_TYPE * 256 + 2)         /* LocationNameRec */
#define PPC_PARTNER_PORT       (PPC_TYPE * 256 + 3)         /* PPCPortRec */
#define MACTCP_STREAM          (MACTCP_TYPE * 256 + 0)      /* StreamPtr */
#define MACTCP_PARTNER_ADDR    (MACTCP_TYPE * 256 + 1)      /* ip_addr */
#define MACTCP_PARTNER_PORT    (MACTCP_TYPE * 256 + 2)      /* tcp_port */
#define MACTCP_IPDRIVER        (MACTCP_TYPE * 256 + 3)      /* short */
#define COMMTB_CONNHANDLE      (COMMTB_TYPE * 256 + 0)      /* ConnHandle */
#define ADSP_CCBREFNUM         (ADSP_TYPE * 256 + 0)        /* short */
#define ADSP_IOCREFNUM         (ADSP_TYPE * 256 + 3)        /* short */

int MLAPI MLDeviceInformation P(( MLINK mlp, unsigned long selector, void* buf, long* buflen));

/*************** MathLink non-ASCII string interface ***************/

/*
 * To iterate over the character codes in a MathLink string,
 * use MLStringChar inside of an MLforString loop.
 *
 *	f()
 *	{
 *		MLStringPosition pos;
 *		int code;
 *		char *s;
 *		if( MLGetString(stdlink, &s)) {
 *			MLforString (s, pos) {
 *				code = MLStringChar(pos);
 *				use_the_character_code(code);
 *			}
 *			MLDisownString(stdlink, s);
 *		}
 *	}
 *
 * To construct a MathLink string from a sequence of
 * character codes, use MLPutCharToString inside a for
 * loop. MLPutCharToString(code, NULL) returns the number of
 * bytes required to encode code.
 *
 *	g(codes, len)
 *		int codes[];
 *		int len;
 *	{
 *		int i, size = 0;
 *		char *s, *p;
 *		for( i = 0; i<len; i++)
 *			size += MLPutCharToString(codes[i], NULL);
 *
 *		if( p = s = (char*)malloc(size + 1) ) {
 *			for( i = 0; i<len; i++)
 *				MLPutCharToString(codes[i], &p);
 *			*p = '\0';
 *			MLPutString(stdlink, s);
 *			free(s);
 *		}
 *	}
 */

typedef struct {
	unsigned char *cc;
	int  mode;
	int  more;
	unsigned char *head;
	} MLStringPosition;

extern int MLAPI MLPutCharToString P((int, char**));

#define MLforString( s, pos) \
  for ( MLStringFirstPos( s, pos); (pos).more; MLStringNextPos( pos))

#define MLStringChar(pos) \
  ( ((pos).mode <= 1) ? *(unsigned char*)((pos).cc) : MLStringCharFun( &pos) )



/* The following names are for internal use only */

#define MLStringFirstPos(s,pos) MLStringFirstPosFun( s, &(pos))

#define MLStringNextPos(pos)  (                   \
	((pos).mode == 0)                           \
	? ((*(*(pos).cc ? ++(pos).cc : (pos).cc)     \
		? 0                                  \
		: ((pos).more = 0)),                     \
  	   (pos).cc)                                \
	: MLStringNextPosFun( &pos) )


extern unsigned char* MLAPI MLStringNextPosFun P((MLStringPosition *));
extern unsigned char* MLAPI MLStringFirstPosFun P((char *, MLStringPosition *));
extern int MLAPI MLStringCharFun P(( MLStringPosition *));

#ifdef __cplusplus
 }
#endif

#endif /* _MATHLINK_H */
