/* $Revision Header * Header built automatically - do not edit! *************
 *
 *	(C) Copyright 1990 by ???
 *
 *	Name .....: RexxHostLib.c
 *	Created ..: Sunday 07-Jan-90 18:55
 *	Revision .: 6
 *
 *	Date            Author          Comment
 *	=========       ========        ====================
 *	07-Jan-90       Olsen           Added string conversion functions
 *	07-Jan-90       Olsen           Added GetToken
 *	07-Jan-90       Olsen           - Empty log message -
 *	07-Jan-90       Olsen           Removed bug in SendRexxCommand
 *	07-Jan-90       Olsen           - Empty log message -
 *	07-Jan-90       Olsen           - Empty log message -
 *	07-Jan-90       Olsen           Created this file!
 *
 ****************************************************************************
 *
 *	This Amiga shared library is based on example source code
 *	written by Gary Samad & Bill Hawes. It also employs basic
 *	library concepts introduced by Jimm Mackraz (ELib) and
 *	Edwin Hoogerbeets (MkLib). This library was generated using
 *	a customized version of the MkLib utility.
 *
 * $Revision Header ********************************************************/
 #define REVISION 6

#include <rexx/storage.h>
#include <rexx/rxslib.h>

#include "rexxhostbase.h"

	/* Forward declarations. */

extern struct MsgPort	*CreatePort();
extern struct MsgPort	*FindPort();
extern struct RexxMsg	*CreateRexxMsg();
extern STRPTR		 CreateArgstring();

	/* Global version identifier. */

LONG Version = REVISION;

	/* CreateRexxHost(HostName) :
	 *
	 *	Creates a MsgPort with a given name. Returns
	 *	NULL if port already exists.
	 */

struct MsgPort *
CreateRexxHost(HostName)
register STRPTR HostName;
{
		/* Already present? */

	if(FindPort(HostName))
		return(NULL);

		/* Create it. */

	return(CreatePort(HostName,0));
}

	/* DeleteRexxHost(MessagePort) :
	 *
	 *	Deletes a MsgPort as created by CreateRexxHost().
	 */

void
DeleteRexxHost(MessagePort)
struct MsgPort *MessagePort;
{
	if(MessagePort)
		DeletePort(MessagePort);
}

	/* SendRexxCommand(HostPort,CommandString,FileExtension,HostName) :
	 *
	 *	Sends a command to the rexx server, requires pointer
	 *	to the MsgPort of the calling Host, the command string;
	 *	file extension and host name are optional and may be
	 *	NULL.
	 */

LONG
SendRexxCommand(HostPort,CommandString,FileExtension,HostName)
register struct MsgPort *HostPort;
register STRPTR CommandString,FileExtension,HostName;
{
	register struct MsgPort	*RexxPort = (struct MsgPort *)FindPort(RXSDIR);
	register struct RexxMsg	*HostMessage;

		/* Valid pointers given? */

	if(!CommandString || !HostPort || !RexxPort)
		return(FALSE);

		/* No special host name given? Take the MsgPort name. */

	if(!HostName)
		HostName = (STRPTR)HostPort -> mp_Node . ln_Name;

		/* No file name extension? Take the default. */

	if(!FileExtension)
		FileExtension = (STRPTR)"rexx";

		/* Create the message. */

	if(!(HostMessage = (struct RexxMsg *)CreateRexxMsg(HostPort,FileExtension,HostName)))
		return(FALSE);

		/* Add the command. */

	if(!(HostMessage -> rm_Args[0] = (STRPTR)CreateArgstring(CommandString,strlen(CommandString))))
	{
		DeleteRexxMsg(HostMessage);
		return(FALSE);
	}

		/* This is a command, not a function. */

	HostMessage -> rm_Action = RXCOMM;

		/* Release it... */

	PutMsg(RexxPort,HostMessage);

	return(TRUE);
}

	/* FreeRexxCommand(RexxMessage) :
	 *
	 *	Frees the contents of a RexxMsg.
	 */

void
FreeRexxCommand(RexxMessage)
register struct RexxMsg *RexxMessage;
{
		/* Valid pointer given? */

	if(!RexxMessage)
		return;

		/* Remove argument. */

	if(RexxMessage -> rm_Args[0])
		DeleteArgstring(RexxMessage -> rm_Args[0]);

		/* Free the message. */

	DeleteRexxMsg(RexxMessage);
}

	/* ReplyRexxCommand(RexxMessage,Primary,Secondary,Result) :
	 *
	 *	Send a RexxMsg back to the rexx server, can include
	 *	result codes.
	 */

void
ReplyRexxCommand(RexxMessage,Primary,Secondary,Result)
register struct RexxMsg *RexxMessage;
register LONG Primary,Secondary;
register STRPTR Result;
{
		/* Valid pointer given? */

	if(!RexxMessage)
		return;

		/* No primary result and results wanted? */ 

	if(Primary == 0 && (RexxMessage -> rm_Action & 1 << RXFB_RESULT))
	{
		Secondary = NULL;

			/* Form result string... */

		if(Result)
			Secondary = (LONG)CreateArgstring(Result,strlen(Result));
	}

		/* Set both results... */

	RexxMessage -> rm_Result1 = Primary;
	RexxMessage -> rm_Result2 = Secondary;

		/* ...and reply the message. */

	ReplyMsg(RexxMessage);
}

	/* GetRexxCommand(RexxMessage) :
	 *
	 *	Returns a pointer to the command string if
	 *	the RexxMsg is a command request.
	 */

STRPTR
GetRexxCommand(RexxMessage)
register struct RexxMsg *RexxMessage;
{
	if(RexxMessage -> rm_Node . mn_Node . ln_Type == NT_REPLYMSG || !RexxMessage)
		return(NULL);

	return(RexxMessage -> rm_Args[0]);
}

	/* GetRexxArg(RexxMessage) :
	 *
	 *	Returns a pointer to the first RexxMsg argument.
	 */

STRPTR
GetRexxArg(RexxMessage)
register struct RexxMsg *RexxMessage;
{
	if(!RexxMessage)
		return(NULL);

	return(RexxMessage -> rm_Args[0]);
}

	/* GetRexxResult1(RexxMessage) :
	 *
	 *	Returns the 1st RexxMsg result.
	 */

LONG
GetRexxResult1(RexxMessage)
register struct RexxMsg *RexxMessage;
{
	if(!RexxMessage)
		return(NULL);

	return(RexxMessage -> rm_Result1);
}

	/* GetRexxResult2(RexxMessage) :
	 *
	 *	Returns the 2nd RexxMsg result.
	 */

LONG
GetRexxResult2(RexxMessage)
register struct RexxMsg *RexxMessage;
{
	if(!RexxMessage)
		return(NULL);

	return(RexxMessage -> rm_Result2);
}

	/* GetToken(String,StartChar,AuxBuff,MaxLength) :
	 *
	 *	Fills a string with the next given string
	 *	argument.
	 */

UBYTE *
GetToken(String,StartChar,AuxBuff,MaxLength)
UBYTE *String,*AuxBuff;
LONG *StartChar,MaxLength;
{
	LONG i,StrEnd = 0,MaxPos = strlen(String);

		/* Last counter position. */

	if(MaxPos >= MaxLength)
		MaxPos = MaxLength - 1;

		/* Already finished with argument string? */

	if(*StartChar > strlen(String) - 1 || !strlen(String) || !String || !AuxBuff || !MaxLength)
		return(NULL);

		/* Parse the argument string... */

	for(i = *StartChar ; i <= MaxPos ; i++)
	{
			/* Skip leading blanks... */

		if(!StrEnd && String[i] == ' ')
		{
			while(String[i] == ' ' && i < MaxPos)
			{
				i++;
				(*StartChar)++;
			}
		}

			/* Found an argument. */

		if(String[i] == ' ' || String[i] == 0)
		{
				/* Copy it to the auxiliary buffer. */

			strncpy(AuxBuff,String + *StartChar,StrEnd);
			AuxBuff[StrEnd] = 0;

				/* Change the position counter (since
				 * we can't use static data initialisation
				 * calling program has to supply a
				 * counter variable).
				 */

			(*StartChar) += StrEnd;

			return(AuxBuff);
		}

			/* Increment character counter. */

		StrEnd++;
	}

	return(NULL);
}

	/* GetStringValue(String) :
	 *
	 *	Returns the numeric value taken from given string
	 *	(just like atoi(), taken from example source code
	 *	by K&R).
	 */

LONG
GetStringValue(String)
register UBYTE *String;
{
	register LONG i,Value,Sign = 1;

	if(!String || !String[0])
		return(0);

	for(i = 0 ; String[i] == ' ' || String[i] == '\n' || String[i] == '\t' ; i++);

	if(String[i] == '+' || String[i] == '-')
		Sign = (String[i++] == '+') ? 1 : -1;

	for(Value = 0 ; String[i] >= '0' && String[i] <= '9' ; i++)
		Value = 10 * Value + String[i] - '0';

	return(Sign * Value);
}

	/* BuildValueString(Value,String) :
	 *
	 *	Puts a numeric value in decimal form into a
	 *	given string (similar to itoa(), taken from
	 *	example source code by K&R).
	 */

UBYTE *
BuildValueString(Value,String)
LONG Value;
UBYTE *String;
{
	LONG i = 0,j,c,Sign;

	if(!String)
		return(NULL);

	if((Sign = Value) < 0)
		Value = -Value;

	do
		String[i++] = Value % 10 + '0';
	while((Value /= 10) > 0);

	if(Sign < 0)
		String[i++] = '-';

	String[i] = 0;

	for(i = 0,j = strlen(String) - 1 ; i < j ; i++,j--)
	{
		c		= String[i];
		String[i]	= String[j];
		String[j]	= c;
	}

	return(String);
}
