/*===========================================================================
 *
 * Command.H - Dave Humphrey (uesp@m0use.net), 11 November 2000
 *
 *=========================================================================*/
#ifndef __COMMAND_H
#define __COMMAND_H

	/* Required Includes */
#include "genutil.h"


/*===========================================================================
 *
 * Begin Defines
 *
 *=========================================================================*/

	/* Use to access to main command handler object */
  #define CommandHandler GetMainCommandHandler()

	/* Used to define a root function command array */
  #define BEGIN_COMMAND_ROOTFUNC()			static cmdfunc_record_t __CmdFuncArray[] = {
  #define DECLARE_COMMAND_ROOTFUNC(pName, pFunc, Type)		{ pName, (pVOIDFUNC_T) (pFunc),    NULL,             Type },
  #define DCRF(Name, Type)					{ #Name, (pVOIDFUNC_T) (Name),     NULL,   CMDFUNC_##Type },
  #define DCRF1(Name, Type)					{ #Name, (pVOIDFUNC_T) (CMD##Name),NULL,   CMDFUNC_##Type },
  #define END_COMMAND_ROOTFUNC()				{  NULL,	          NULL,  NULL, CMDFUNC_ENDARRAY } }; \
							static boolean __CmdResult = CommandHandler.AddFunctionArray(&__CmdFuncArray[0]);

	/* Used to define a function command array */
  #define DECLARE_COMMAND_FUNCMAP()			static  cmdfunc_record_t __CmdFuncArray[];  \
							virtual cmdfunc_record_t* GetCmdFuncArray (void);
  #define BEGIN_COMMAND_FUNCTION(ClassName)		cmdfunc_record_t* ClassName::GetCmdFuncArray() { return &(ClassName::__CmdFuncArray[0]); } \
							cmdfunc_record_t ClassName::__CmdFuncArray[] = {
  #define DECLARE_COMMAND_FUNCTION(pName, pFunc, Type)		{ pName, NULL, (pCMDFUNC_T) pFunc,             Type },
  #define END_COMMAND_FUNCTION()				{  NULL, NULL,	  	       NULL, CMDFUNC_ENDARRAY } };

  	/* Used to define a object command array */
  #define DECLARE_COMMAND_OBJECTMAP()			static  CCommandObject* __CmdObjArray[]; \
							virtual CCommandObject** GetCmdObjArray (void);
  #define BEGIN_COMMAND_OBJECT(ClassName)		CCommandObject** ClassName::GetCmdObjArray() { return &(ClassName::__CmdObjArray[0]); } \
							CCommandObject*  ClassName::__CmdObjArray[] = {
  #define DECLARE_COMMAND_OBJECT(pObject)			(CCommandObject *) (pObject),
  #define END_COMMAND_OBJECT()					NULL };

	/* Declare a root command object */
  #define DECLARE_COMMAND_ROOTOBJ(pName, Object)	static boolean __CmdResult##__LINE__ = CommandHandler.AddObject(pName, &(Object));

	/* Number of objects/functions the command handler can know of */
  #define CMD_MAX_OBJECTS    100
  #define CMD_MAX_FUNCTIONS  200
  #define CMD_MAX_PARAMETERS 20

	/* Maximum length of the function name */
  #define CMD_FUNCNAME_LENGTH 30

/*===========================================================================
 *		End of Defines
 *=========================================================================*/	


/*===========================================================================
 *
 * Begin Type and Structure Definitions
 *
 *=========================================================================*/

	/* Basic void-void type function */
  typedef void (*pVOIDFUNC_T) (void);

  class CCommandObject;
  typedef void (CCommandObject::*pCMDFUNC_T)(void);
  
/*===========================================================================
 *		End of Type Definitions
 *=========================================================================*/


/*===========================================================================
 *
 * Union cmdfunction_u Definition
 *
 * Holds a pointer to all the function types which can be called by the
 * command handler.  Idea developed from the MessageMapFunction union used
 * in MFC. Basic naming convention of the function pointers are as follows:
 *	pFunc_##...	: Regular function pointer
 *	pCmdFunc_##...	: A CCommandObject class method pointer
 *	##		: Represents the parameter types of the function.
 *
 * Function Parameters:
 *	The first letter in the parameter name after the '_' character 
 *	represents the return type.  The following characters are the
 *	one or more arguments the function takes.  The supported types
 *	are identified as follows:
 *		v = void
 *		c = signed char
 *		C = unsigned char
 *		i = signed int
 *		I = unsigned int
 *		l = signed long
 *		L = unsigned long
 *		f = float
 *		b = boolean
 *		pv = void *
 *		pc = char *
 * 
 *=========================================================================*/
typedef union {
  pVOIDFUNC_T pFunction;	/* Used by command handler to set function pointer */

  void (*pFunc_vv) (void);
  void (*pFunc_vc) (signed char);
  void (*pFunc_vC) (unsigned char);
  void (*pFunc_vi) (signed int);
  void (*pFunc_vI) (unsigned int);
  void (*pFunc_vl) (signed long);
  void (*pFunc_vL) (unsigned long);
  void (*pFunc_vf) (float);
  void (*pFunc_vb) (boolean);
  void (*pFunc_vpv) (void* );
  void (*pFunc_vpc) (char* );
  char* (*pFunc_pcv) (void);
  char* (*pFunc_pcc) (signed char);
  char* (*pFunc_pcC) (unsigned char);
  char* (*pFunc_pci) (signed int);
  char* (*pFunc_pcI) (unsigned int);
  char* (*pFunc_pcl) (signed long);
  char* (*pFunc_pcL) (unsigned long);
  char* (*pFunc_pcf) (float);
  char* (*pFunc_pcb) (boolean);
  char* (*pFunc_pcpv) (void* );
  char* (*pFunc_pcpc) (char* );
  boolean (*pFunc_bv) (void);
  boolean (*pFunc_bc) (signed char);
  boolean (*pFunc_bC) (unsigned char);
  boolean (*pFunc_bi) (signed int);
  boolean (*pFunc_bI) (unsigned int);
  boolean (*pFunc_bl) (signed long);
  boolean (*pFunc_bL) (unsigned long);
  boolean (*pFunc_bb) (boolean);
  boolean (*pFunc_bpv) (void* );
  boolean (*pFunc_bpc) (char* );
  boolean (*pFunc_bpcpc) (char*, char*);
  signed int (*pFunc_iv) (void);
  signed int (*pFunc_ii) (signed int);
  unsigned int (*pFunc_Ii) (signed int);
  signed long (*pFunc_lv) (void);
  signed long (*pFunc_lpc) (char *);
  unsigned long (*pFunc_Li) (signed int);
 } cmdfunction_u;

typedef union {
  pCMDFUNC_T pFunction;	/* Used by command handler to set function pointer */

  void (CCommandObject::*pFunc_vv) (void);
  void (CCommandObject::*pFunc_vc) (signed char);
  void (CCommandObject::*pFunc_vC) (unsigned char);
  void (CCommandObject::*pFunc_vi) (signed int);
  void (CCommandObject::*pFunc_vI) (unsigned int);
  void (CCommandObject::*pFunc_vl) (signed long);
  void (CCommandObject::*pFunc_vL) (unsigned long);
  void (CCommandObject::*pFunc_vf) (float);
  void (CCommandObject::*pFunc_vb) (boolean);
  void (CCommandObject::*pFunc_vpv) (void* );
  void (CCommandObject::*pFunc_vpc) (char* );
  char* (CCommandObject::*pFunc_pcv) (void);
  char* (CCommandObject::*pFunc_pcc) (signed char);
  char* (CCommandObject::*pFunc_pcC) (unsigned char);
  char* (CCommandObject::*pFunc_pci) (signed int);
  char* (CCommandObject::*pFunc_pcI) (unsigned int);
  char* (CCommandObject::*pFunc_pcl) (signed long);
  char* (CCommandObject::*pFunc_pcL) (unsigned long);
  char* (CCommandObject::*pFunc_pcf) (float);
  char* (CCommandObject::*pFunc_pcb) (boolean);
  char* (CCommandObject::*pFunc_pcpv) (void* );
  char* (CCommandObject::*pFunc_pcpc) (char* );
  boolean (CCommandObject::*pFunc_bv) (void);
  boolean (CCommandObject::*pFunc_bc) (signed char);
  boolean (CCommandObject::*pFunc_bC) (unsigned char);
  boolean (CCommandObject::*pFunc_bi) (signed int);
  boolean (CCommandObject::*pFunc_bI) (unsigned int);
  boolean (CCommandObject::*pFunc_bl) (signed long);
  boolean (CCommandObject::*pFunc_bL) (unsigned long);
  boolean (CCommandObject::*pFunc_bb) (boolean);
  boolean (CCommandObject::*pFunc_bpv) (void* );
  boolean (CCommandObject::*pFunc_bpc) (char* );
  boolean (CCommandObject::*pFunc_bpcpc) (char*, char*);
  signed int (CCommandObject::*pFunc_iv) (void);
  signed int (CCommandObject::*pFunc_ii) (signed int);
  unsigned int (CCommandObject::*pFunc_Ii) (signed int);
  signed long (CCommandObject::*pFunc_lv) (void);
  signed long (CCommandObject::*pFunc_lpc) (char *);
  unsigned long (CCommandObject::*pFunc_Li) (signed int);
 } cmdobjfunc_u;
/*===========================================================================
 *		End of cmdfunction_u Definition
 *=========================================================================*/


/*===========================================================================
 *
 * Enumeration cmdfunc_type_t Definition
 *
 * Type used to determine the type of function to call.  Same type of 
 * constant naming as in the cmdfunction_u union definition above except
 * there is no difference between root and command object functions.
 *
 *=========================================================================*/
typedef enum {
	CMDFUNC_ENDARRAY,	/* Special type to indicate the end of function arrays */

	CMDFUNC_vv,
	CMDFUNC_vc,
	CMDFUNC_vC,
	CMDFUNC_vi,
	CMDFUNC_vI,
	CMDFUNC_vl,
	CMDFUNC_vL,
	CMDFUNC_vf,
	CMDFUNC_vb,
	CMDFUNC_vpv,
	CMDFUNC_vpc,
	CMDFUNC_pcv,
	CMDFUNC_pcc,
	CMDFUNC_pcC,
	CMDFUNC_pci,
	CMDFUNC_pcI,
	CMDFUNC_pcl,
	CMDFUNC_pcL,
	CMDFUNC_pcf,
	CMDFUNC_pcb,
	CMDFUNC_pcpv,
	CMDFUNC_pcpc,
	CMDFUNC_bv,
	CMDFUNC_bc,
	CMDFUNC_bC,
	CMDFUNC_bi,
	CMDFUNC_bI,
	CMDFUNC_bl,
	CMDFUNC_bL,
	CMDFUNC_bf,
	CMDFUNC_bb,
	CMDFUNC_bpv,
	CMDFUNC_bpc,
	CMDFUNC_bpcpc,
	CMDFUNC_iv,
	CMDFUNC_ii,
	CMDFUNC_Ii,
	CMDFUNC_lv,
	CMDFUNC_lpc,
	CMDFUNC_Li
 } cmdfunc_type_t;
/*===========================================================================
 *		End of cmdfunc_type_t Definition
 *=========================================================================*/


/*===========================================================================
 *
 * Structure cmdfunc_record_t Definition
 *
 * Holds the information for one command object or root function.
 *
 *=========================================================================*/
typedef struct {
  char	         Name[CMD_FUNCNAME_LENGTH];	/* Identifies the function */
  pVOIDFUNC_T    pRootFunction;			/* A root function pointer */
  pCMDFUNC_T     pCmdFunction;			/* A command object function pointer */
  cmdfunc_type_t Type;				/* The type of function */
 } cmdfunc_record_t;
/*===========================================================================
 *		End of structure cmdfunc_record_t Definition
 *=========================================================================*/


/*===========================================================================
 *
 * Structure cmd_parameter_t Definition
 *
 * Used to hold parameter information when calling a command function.
 *
 *=========================================================================*/
typedef struct {
  int     NumParameters;	/* Number of parameter supplied */
  char*   pParameters[CMD_MAX_PARAMETERS];		/* Pointer to an array of string parameters */
  int     NumObjects;		/* Number of objects in the heirarchy */
  char*   pObjects[CMD_MAX_PARAMETERS];
  char*   pFunction;		/* The function name to call */
  char*   pReturnValue;		/* Filled with the return value of the command */
  boolean AllocateReturn;	/* Allocate a new return value or assume its a valid buffer */ 
  int     ReturnSize;		/* Size of the return buffer string */
 } cmd_parameter_t;
/*===========================================================================
 *		End of Structure cmd_parameter_t
 *=========================================================================*/


/*===========================================================================
 *
 * Class CCommandObject Definition
 *
 * The base class from which other classes can be derived to allow their
 * member functions to be command targets.
 *
 *=========================================================================*/
class CCommandObject {

  /*---------- Begin Protected Class Members ------------------------*/
protected:
  char*   pCommandName;		/* Name that identifies this object */
  boolean ValidCMDObject;	/* Used to determine the object validity */

	/* Declare the base object map */
  DECLARE_COMMAND_OBJECTMAP()
  DECLARE_COMMAND_FUNCMAP()

  /*---------- Begin Public Class Methods ---------------------------*/
public:

	/* Class constructor/destructor */
  CCommandObject() { pCommandName = NULL; ValidCMDObject = TRUE; }
  ~CCommandObject() { DestroyPointer(pCommandName); ValidCMDObject = FALSE; }

	/* Find a function in the object array */
  cmdfunc_record_t* FindFunction (cmd_parameter_t& Parameters);

	/* Find a sub-object in the object array */
  CCommandObject* FindObject (const int ObjectLevel, cmd_parameter_t& Parameters);

	/* Get class members */
  char* GetCommandName (void) { return (pCommandName); }

	/* Ensure a valid command object */
  boolean IsValidObject (void) { return (ValidCMDObject); }

	/* Set class members */
  void SetCommandName (const char* pString) { DestroyPointer(pCommandName); pCommandName = CreateString(pString); }

 };
/*===========================================================================
 *		End of Class CCommandObject Definition
 *=========================================================================*/


/*===========================================================================
 *
 * Class CCommandHandler Definition
 *
 * The class which handles all the command objects/functions in the 
 * application. 
 *
 *=========================================================================*/
class CCommandHandler {

  /*---------- Begin Protected Class Members ------------------------*/
protected:

	/* List of root objects */
  CCommandObject* pObjects[CMD_MAX_OBJECTS];
  int		  NumObjects;

	/* List of root function arrays */
  cmdfunc_record_t* pFunctionArrays[CMD_MAX_FUNCTIONS];
  int		    NumFunctionArrays;

	/* List of root functions */
  cmdfunc_record_t* pFunctions[CMD_MAX_FUNCTIONS];
  int		    NumFunctions;

	/* Variables used to TAB through commands */
//  char* pLastTabName;


  /*---------- Begin Protected Class Methods ------------------------*/
protected:

	/* Find an object in the class object heirarchy */
  CCommandObject* FindObject (cmd_parameter_t& Parameters);

	/* Find a command name in the function/array lists */
  cmdfunc_record_t* FindRootFunction (const char* pName);

  
  /*---------- Begin Public Class Methods ---------------------------*/
public:

	/* Class Constructor/Destructor */
  CCommandHandler();
  ~CCommandHandler() { Destroy(); }
  void Destroy (void);

	/* Adds a new root function array to the handler */
  boolean AddFunctionArray (cmdfunc_record_t* pArray);

  	/* Adds a new root function to the handler */
  boolean AddRootFunction (const char* pName, pVOIDFUNC_T pFunc, const cmdfunc_type_t Type);

	/* Add an object to the object array */
  boolean AddObject (const char* pName, CCommandObject* pObject);

	/* Main access function to run a command */
  boolean CallCommand (const char* pCommandName, cmd_parameter_t& Parameters);

	/* Get class members */
  int GetNumFunctions      (void) { return (NumFunctions); }
  int GetNumFunctionArrays (void) { return (NumFunctionArrays); }
  int GetNumObjects        (void) { return (NumObjects); }

	/* Parse a command/parameter string and execute it */
  char*   ParseCommand (char* pCommand);
  boolean ParseCommand (char* pCommand, cmd_parameter_t& Parameters);

 };
/*===========================================================================
 *		End of Class CCommandHandler Definition
 *=========================================================================*/


/*===========================================================================
 *
 * Begin Function Prototypes
 *
 *=========================================================================*/

	/* Accesses the static command handler object */
  CCommandHandler& GetMainCommandHandler (void);

	/* Parse a string into a command and parameters */
  char* ParseCommandString (char* pString, cmd_parameter_t& Parameters);

  	/* Parse out the command objects from the given command string */
  void ParseCommandObjects (char* pString, cmd_parameter_t& Parameters);

	  /* Preprocesses a command-parameter string */
  void PreprocessCommandString (char* pString);


/*===========================================================================
 *		End of Function Prototypes
 *=========================================================================*/


	/* Other include files */
#include "generr.h"
#include "fileutil.h"


#endif
/*===========================================================================
 *		End of File Command.H
 *=========================================================================*/