#include <exec/types.h>
#include <exec/exec.h>
#include <libraries/dosextens.h>

extern void	*AllocMem(), *CreatePort(), *GetMsg(), *FindTask();

extern LONG	Open(), Output(), CreateProc();


/*
 * Cursor manipulation strings.
 */
char	fwdcursor[] = "\033[C";
char	backcursor = '\b';

struct PhonySegList {
	BPTR	psl_NextSeg;		/*  BPTR to next element in list  */
	UWORD	psl_JMP;		/*  A 68000 JMP abs.l instruction  */
	LONG	(*psl_EntryPoint)();	/*  The address of the function  */
};

struct PhonySegList template = {
	NULL,				/*  No next element.		  */
	0x4EF9,				/*  JMP abs.l			  */
	NULL				/*  Argument for JMP instruction  */
};

LONG
coprocess ()
{
	register int	i, n;
	struct Process	*me;
	struct Message	*startupmsg;
	LONG		doswin;
	char		buf[256];

	me = FindTask (NULL);
	WaitPort (&me -> pr_MsgPort);
	startupmsg = GetMsg (&me -> pr_MsgPort);

	if (!(doswin = Open ("CON:0/0/320/100/Sub-Process", MODE_NEWFILE)))
		goto xit;

	Write (doswin, "This is the child speaking.\n", 28L);

	sprintf (buf, "I'm at 0x%lx\n", me);
	Write (doswin, buf, (LONG) strlen (buf));

	sprintf (buf, "My stack size appears to be\n%ld bytes.\n",
		 me -> pr_StackSize);
	Write (doswin, buf, (LONG) strlen (buf));

	sprintf (buf, "pr_StackBase is 0x%lx\n", me -> pr_StackBase);
	Write (doswin, buf, (LONG) strlen (buf));

	for (n = 20;  n--; ) {
		for (i = 35;  i--; )
			Write (doswin, fwdcursor, sizeof (fwdcursor) - 1L);
		for (i = 35;  i--; )
			Write (doswin, &backcursor, 1L);
	}

	Close (doswin);			/*  Get ridda da window.  */
xit:
	Forbid ();
	ReplyMsg (startupmsg);
	return (0);
}


main ()
{
	register int		i;
	struct Process		*me;
	struct MsgPort		*replyport = NULL;
	struct Message		startupmsg;
	struct PhonySegList	*fakelist = NULL;
	LONG			child,
				priority,
				term;

	if (!(term = Output ()))
		goto xit;

	if (!(replyport = CreatePort (NULL, NULL)))
		goto xit;

	if (!(fakelist = AllocMem ((LONG) sizeof (*fakelist), NULL)))
		goto xit;

	CopyMem (&template, fakelist, (LONG) sizeof (template));
	fakelist -> psl_EntryPoint = coprocess;

	startupmsg.mn_Node.ln_Type	= NT_MESSAGE;
	startupmsg.mn_Node.ln_Pri	= 0;
	startupmsg.mn_ReplyPort		= replyport;

	me = FindTask (NULL);
	priority = me -> pr_Task.tc_Node.ln_Pri;

	puts ("This is the parent speaking.");
	printf ("I'm at 0x%lx\n", me);
	printf ("My stack size appears to be\n%ld bytes.\n",
		 me -> pr_StackSize);
	printf ("pr_StackBase is 0x%lx\n", me -> pr_StackBase);

	if (!(child = CreateProc ("Sub-Process",
				  priority,
				  (LONG) fakelist >> 2,
				  2048L)))
		goto xit;

	PutMsg (child, &startupmsg);

	while (!GetMsg (replyport)) {
		for (i = 64;  i--; )
			Write (term, fwdcursor, sizeof (fwdcursor) - 1L);
		for (i = 64;  i--; )
			Write (term, &backcursor, 1L);
	}

	puts ("Child terminated.");
xit:
	if (fakelist)	FreeMem (fakelist, (LONG) sizeof (*fakelist));
	if (replyport)	DeletePort (replyport);
}
