/****************************************************************************
**
**  Name:  addrcli.c
**
**  Description:
**     This is the addr server cli interface code of the Thunderbird.
**
**  Status:  PRELIMINARY
**
**  $Log:   S:/tbird/mt2_186/addr/addrcli.c_v  $
** 
**    Rev 1.0   16 Dec 1996 16:15:50   Judy
** Initial revision.
** 
**    Rev 1.23   13 Oct 1994 10:31:16   marilyn
** Moved local buffer from stack area to the local heap.
** 
**    Rev 1.22   10 Aug 1994 10:45:56   marilyn
** Added AdrCliAddrDump for debugging purposes.
** 
**    Rev 1.21   16 Jun 1994 14:49:32   nghia
** Merged 1.19.1.0 to trunk
** 
**    Rev 1.20   16 Jun 1994 14:07:22   nghia
** Merged 1.19.1.0 (HC16 Support index register for pointer).
** 
**    Rev 1.19.1.0   31 May 1994 17:03:02   nghia
** Added AdrCliCpu16VarIndex() to support HC16 var index reg.
** 
**    Rev 1.19   22 Mar 1994 10:30:02   marilyn
** Update with x86 addressing support.  Added additional shell commands.
** 
**    Rev 1.18   28 Feb 1994 17:10:56   marilyn
** Stubbed out interface for new shell command: xlt.
** 
**    Rev 1.17   28 Jun 1993 07:23:28   doug
** use general syntax error message
**
**    Rev 1.16   27 Aug 1992 14:51:48   doug
** add display of create/destroy (debug_addr on)
** 
**    Rev 1.15   20 Aug 1992 20:28:08   brucea
** Fixed bug in SendMessageToCli
** 
**    Rev 1.14   18 Aug 1992 18:13:54   brucea
** Changed: AddrCliDebug to AdrCliDebug
** 
**    Rev 1.13   14 Aug 1992 15:21:56   doug
** added debug command
** 
**    Rev 1.12   13 Aug 1992 11:39:26   brucea
** Removed compiler warnings
** 
**    Rev 1.11   08 Aug 1992 10:57:42   tom
** New CLI registration changes.
** 
**    Rev 1.10   27 Jul 1992 22:40:20   brucea
** Removed: checking for error from SendMessage
** 
**    Rev 1.9   23 Jul 1992 09:28:38   brucea
** Removed: vars no longer used
** 
**    Rev 1.8   20 May 1992 10:41:04   mindy
** initcserver needs to return GOOD if no errors!
** 
**    Rev 1.7   15 May 1992 15:59:34   brucea
** Removed: include of addrerrs.h (merged with addr.h)
** 
**    Rev 1.6   15 May 1992 15:49:46   brucea
** Removed: local memory macros
** Cleaned up: SendMesageToCli including error reporting
**           : InitCServer memory allocation and error reporting
** Removed: AddrGetPhysical, AddrTranslateMode
** 
**    Rev 1.5   31 Jan 1992 13:42:26   brucea
** Copied SendMessageToCli into module from CLIPRINT.CPP; removed SendCliMessage
** 
**    Rev 1.4   30 Jan 1992 18:48:58   brucea
** Added #include of addrerrs.h and cliprint.h
** Changed AddrCliPhysical to AddrGetPhysical; still not implemented
** Created AddrTranslateMode
** Removed AddrCliHelp (now embedded in .RES file)
** 
**    Rev 1.3   21 Jan 1992 15:29:16   doug
** Addr* routines for CLI support now exported.
** 
**    Rev 1.2   21 Jan 1992 13:13:36   doug
** removed EXPORT where not needed
** 
**    Rev 1.1   14 Jan 1992 12:07:28   tom
** New revisions from Hsinchu.
**
**  $Header:   S:/tbird/mt2_186/addr/addrcli.c_v   1.0   16 Dec 1996 16:15:50   Judy  $
**
**  Copyright (C) 1991 Microtek International.  All rights reserved.
**
*****************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "ctype.h"

#ifndef _ADDR_
#include "addr.h"
#endif

#ifndef _BASEWIND_
#include "basewind.h"
#endif

#ifndef _CLISRV_
#include "clisrv.h"
#endif

#ifndef _HEAP_
#include "heap.h"
#endif

#ifndef _CPU_
#include "cpu.h"
#endif

#ifndef __ADDRINI__
#include "addrini.h"
#endif
                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/

HANDLE cliServerHandle = (HANDLE)NULL;  /* force definition here */

CHAR outbuf[500];   /* local buffer used for output to shell */

                        /****************************
                         *                          *
                         *    EXTERNAL VARIABLES    *
                         *                          *
                         ****************************/

extern U32 numAddrCreated;
extern U32 numAddrDestroyed;
extern U16 defaultRadix;
extern BOOLEAN addrDebug;
extern PROCESSOR_FAMILY procFamily;
extern PROC_CPU procCpu;

extern const LPSTR toolChainSection;
extern const LPSTR indexRegKey;
extern BOOLEAN usedIndexExtReg;
extern CHAR extRegName[];
extern REG_ID extRegId;
                        /****************************
                         *                          *
                         *     LOCAL PROTOTYPES     *
                         *                          *
                         ****************************/

RETCODE SendMessageToCli(S8 FAR *msgPtr, HANDLE cliHandle);


/**************************************************************************
** SendMessageToCli
**
** Description: Sends a local string to the CLI Server.
**
** Parameters:
**    input:
**       msgPtr:  long pointer to string to be sent
**       cliHandle:  DLL Handle.
**
**    output: none
**
***************************************************************************/
RETCODE SendMessageToCli(S8 FAR *msgPtr,
                         HANDLE cliHandle) {
   HANDLE msgBufHandle;
   CSERVER_RESULTS FAR *cpPtr;
   LPSTR tmpPtr;
   U32 i;
   U16 size;

   size = strlen((CHAR *)msgPtr);
   // allocate enough memory for the string passed in and the size ;
   // of the CSERVER_RESULTS packet, and then subtract out the extra ;
   // space allocated to the messageText field. ;
   if ((msgBufHandle = GlobalAlloc(GMEM_MOVEABLE,
      (size + sizeof(CSERVER_RESULTS) + 2))) == (HANDLE)NULL) {
      return(ER_OUT_OF_MEMORY);              
   }
   else if ((cpPtr = (CSERVER_RESULTS *)GlobalLock(msgBufHandle)) == NULL) {
      GlobalFree(msgBufHandle);
      return(ER_WINDOWS_MEMLOCK);
   }
   cpPtr->target           = 0;  // address to the cli server;
   cpPtr->variantCode      = CLI_SERVER_RESULTS;
   cpPtr->resultTextLength = size; // size of message;

   /* reassign pointer to beginning of message text */
   (LPSTR)tmpPtr = cpPtr->messageText;

   /* copy the data from msgPtr to the global memory space */
   for(i = 0; i < size; i++) {
      *tmpPtr++ = *msgPtr++;
   }
   SendMessage(cliHandle, CLI_SERVER_RESULTS, msgBufHandle,
               (CLI_SERVER_RESULTS | 0x0L));
   return(GOOD);
}


/**************************************************************************
**
** InitCServer
**
** Description: Initialize the commands for the Cpu Server.
**
** Parameters:
**    input:
**       cliHandle:  CLI Server Handle
**       dllHandle:  DLL Handle.
**
**    output: None
**
***************************************************************************/
RETCODE EXPORT InitCServer(HANDLE cliHandle, HANDLE dllHandle) {

   CSERVER_NEW_REGISTRATION FAR * msgBufPtr;

   cliServerHandle = cliHandle;
   msgBufPtr =
      (CSERVER_NEW_REGISTRATION FAR *)TMalloc(sizeof(CSERVER_VARIABLE_VALUE));
   if (msgBufPtr == NULL) {
      return(ER_OUT_OF_MEMORY);
   }

   msgBufPtr->stringResourceHandle = dllHandle;

   msgBufPtr->serverNameIndex = 30;
   msgBufPtr->dllNameIndex = 31;
   msgBufPtr->numberOfCommandsIndex = 32;
   msgBufPtr->commandStartIndex = 33;
   SendMessage(cliHandle, CLI_NEW_SVR_REGISTRATION, CLI_NEW_SVR_REGISTRATION,
      (DWORD)msgBufPtr);
   return(GOOD);
}

/***************************************************************************
**
**  AddrCliDebug
**
**  Status:  TESTED
**
**  description:
**     addr_debug to display debug information
**
**  input:
**     cmdString:  input text
**     argc:  argument count
**     argv:  offsets into cmdString where arguments start
**
**  output:
**     information sent to the CLI
**
*****************************************************************************/
#pragma argsused
RETCODE EXPORT AdrCliDebug(LPSTR cmdString, U32 argc, U32 argv[]) {
   S8 buff[80];

   if(argc>2) return(ER_CLI_SYNTAX);
   if(argc==2) {
      /* set */
      if(strncmpi(&cmdString[(int)argv[1]], "on",
            strlen(&cmdString[(int)argv[1]]))==0) {
         addrDebug = TRUE;
      } else if(strncmpi(&cmdString[(int)argv[1]], "off",
            strlen(&cmdString[(int)argv[1]]))==0) {
         addrDebug = FALSE;
      } else return(ER_CLI_SYNTAX);
   }
   wsprintf(buff, "# address descriptors created:   %-8ld", numAddrCreated);
   SendMessageToCli(buff, cliServerHandle);
   wsprintf(buff, "# address descriptors destroyed: %-8ld", numAddrDestroyed);
   SendMessageToCli(buff, cliServerHandle);
   wsprintf(buff, "# address descriptors active:    %-8ld", 
      numAddrCreated-numAddrDestroyed);
   SendMessageToCli(buff, cliServerHandle);
   SendMessageToCli(addrDebug?(LPSTR)"address debug is on":
                              (LPSTR)"address debug is off",
                    cliServerHandle);
   return(GOOD);
}

/**************************************************************************
**
** AdrCliXlt
**
**  Description:
**     xlt <address> to display equivalent address formats for intel
**     addresses
**
**  input:
**     cmdString:  input text
**     argc:  argument count
**     argv:  offsets into cmdString where arguments start
**
**  output:
**     information sent to the CLI
**
**
**************************************************************************/
RETCODE EXPORT AdrCliXlt(LPSTR cmdString, U32 argc, U32 argv[]) {

   DESCRIPTOR addr;
   ADDR_TYPE type;
   CHAR buff[80];
   CHAR outbuf[80];
   RETCODE err;
   BOOLEAN rangeCovered;

   if (procFamily != FAMILY_X86)
      return ER_ADR_SHELL_NOT_SUPPORTED;
   if (argc != 2) return(ER_CLI_SYNTAX);
   *outbuf = '\0';
   *buff = '\0';
   if ((err = AdrCreateAddressFromText(&cmdString[(int)argv[1]],NULL,
         &addr)) != GOOD)
      return err;
   if ((err = AdrGetAddrType(addr,&type)) != GOOD)
      return err;
   switch (type) {
      case ADDR_VIRTUAL:
         if ((err = AdrConvAddressToText(addr,buff)) != GOOD) {
            AdrDestroyAddress(addr);
            return err;
         }
         strcat(outbuf, buff);
         strcat(outbuf," = ");
         if ((err = AdrConvertAddress(addr,ADDR_LINEAR,
               &rangeCovered)) != GOOD) {
            AdrDestroyAddress(addr);
            return err;
         }
         /* fall thru ... */
      case ADDR_LINEAR:
         if ((err = AdrConvAddressToText(addr,buff)) != GOOD) {
            AdrDestroyAddress(addr);
            return err;
         }
         strcat(outbuf,buff);
         strcat(outbuf," = ");
         if ((err = AdrConvertAddress(addr,ADDR_PHYSICAL,
               &rangeCovered)) != GOOD) {
            AdrDestroyAddress(addr);
            return err;
         }
         /* fall thru ... */
      case ADDR_PHYSICAL:
         if ((err = AdrConvAddressToText(addr,buff)) != GOOD) {
            AdrDestroyAddress(addr);
            return err;
         }
         strcat(outbuf,buff);
         break;
   }
   SendMessageToCli(outbuf, cliServerHandle);
   if ((err = AdrDestroyAddress(addr)) != GOOD)
      return err;

   return GOOD;
}

/**************************************************************************
**
** AdrCliPmode
**
**  Description:
**     pmode :  to display processor mode at last BKPT_HALTED event
**
**  input:
**     cmdString:  input text
**     argc:  argument count
**     argv:  offsets into cmdString where arguments start
**
**  output:
**     information sent to the CLI

**************************************************************************/
#pragma argsused
RETCODE EXPORT AdrCliPmode(LPSTR cmdString, U32 argc, U32 argv[]) {

   PMODE pmode;
   S8 buff[80];
   RETCODE err;

   if (procFamily != FAMILY_X86)
      return ER_ADR_SHELL_NOT_SUPPORTED;
   if(argc != 1) return(ER_CLI_SYNTAX);
   strcpy(buff,"Processor mode = ");
   if ((err = AdrGetPmode(&pmode,buff+strlen(buff))) != GOOD) return err;
   SendMessageToCli(buff, cliServerHandle);

   return GOOD;
}

/**************************************************************************
**
** AdrCliInit
**
**  Description:
**     _addrinit :  force the address server to reinitialize its globals
**
**  input:
**     cmdString:  input text
**     argc:  argument count
**     argv:  offsets into cmdString where arguments start
**
**  output:
**     information sent to the CLI

**************************************************************************/
#pragma argsused
RETCODE EXPORT AdrCliInit(LPSTR cmdString, U32 argc, U32 argv[]) {
   return(AdrInitAddressServer());
}

/**************************************************************************
**
** AdrCliCpu16VarIndex
**  Description:
**     Set index register to be used in accessing short pointer variable.
**
**  Syntax: 
**     68HC16VarIndexReg [none | XK:IX | YK:IY | ZK:IZ ]
**
**  input:
**     cmdString:  input text
**     argc:  argument count
**     argv:  offsets into cmdString where arguments start
**
**  output:
**     information sent to the CLI

**************************************************************************/
#pragma argsused
RETCODE EXPORT AdrCliCpu16VarIndex(LPSTR cmdString,
                                   U32 argc, U32 argv[]) {
   RETCODE err;
   S8 buff[80];
   
   if (procCpu != PROC_CPU_CPU16)
      return ER_ADR_SHELL_NOT_SUPPORTED;
   
   if (argc < 2) {
      if ((err = GetCpu16IndexRegUsed()) != GOOD)  return err;
      // format the output command
      sprintf(buff, "%s = %s", indexRegKey, (LPSTR)extRegName);
      SendMessageToCli(buff, cliServerHandle);
      return GOOD;    
   }
   // chcek for maximum token allow in command
   if (argc > 2)  return(ER_CLI_SYNTAX);
   
   // get the new Index register
   usedIndexExtReg = FALSE;
   if (!lstrcpy((LPSTR)extRegName, (LPSTR) &cmdString[(int)argv[1]]))
      return ER_FAILED_STRCPY;
   // validate the register name
   if (strcmpi(extRegName, "none") != 0) {
      if ((err = CpuFindRegisterId((U8 FAR*)extRegName,
                                   (REG_ID FAR*)&extRegId)) != GOOD)
         return err;
      usedIndexExtReg = TRUE;
   }
   // Write the user input back to INI file
   return IniSetString(toolChainSection, indexRegKey, NULL, (LPSTR)extRegName);
} /* AdrCliCpu16VarIndex */


/**************************************************************************
**
** AdrCliAddrDump
**
**  Description:
**     _addrdump <address> will dump all the internal fields of the
**     address descriptor of the given address.
**
**  input:
**     cmdString:  input text
**     argc:  argument count
**     argv:  offsets into cmdString where arguments start
**
**  output:
**     information sent to the CLI
**
**
**************************************************************************/
RETCODE EXPORT AdrCliAddrDump(LPSTR cmdString, U32 argc, U32 argv[]) {

   DESCRIPTOR addr;
   CHAR *endPtr;
   RETCODE err;

   if (argc != 2) return(ER_CLI_SYNTAX);
   *outbuf = '\0';
   /* the input is the descriptor id - DESCRIPTOR 
   ** we don't want to create a new descriptor but access the
   **  existing one with the same id.  So use strtoul to 
   **  get the address descriptor id.
   */
   addr = strtoul(&cmdString[(int)argv[1]],&endPtr,defaultRadix);
   if (*endPtr != '\0')
      return ER_ADR_INVALID_DESCRIPTOR;
   if ((err = AdrGetAddrDescToText(addr,outbuf)) != GOOD)
      return err;
   SendMessageToCli(outbuf, cliServerHandle);

   return GOOD;
}
/******************************** E O F ***********************************/
