/****************************************************************************
**
**  Name:  brkexcli.c
**
**  Description:
**     This is the CLI supporting of breakpoint & execution control server 
**
**  Status:  PRELIMINARY
**
**  $Log:   S:/tbird/mt2_186/bkptexec/brkexcli.c_v  $
** 
**    Rev 1.2   26 Aug 1997 10:49:26   Judy
 * 
 *    Rev 1.0   26 Aug 1997 09:56:30   unknown
 * Initial revision.
** 
**    Rev 1.1   04 Feb 1997 18:20:58   Judy
** 
**    Rev 1.0   16 Dec 1996 14:51:40   Judy
** Initial revision.
** 
**    Rev 1.46   21 Oct 1994 18:35:02   nghia
** Use the staticProcFamily instead of the local procFamily to reduce the 
** overhead of calling for unchanged information.
** Revise the DisplayBkpt() to print the moduleName in place of the
** module reference when there isn't one.
** 
**    Rev 1.45   28 Jul 1994 12:00:52   nghia
** Added check for bkpt function is a NULL_SYMBOL to avoid dereference a null 
** pointer in DisplayBkpt().
** 
**    Rev 1.44   17 Jun 1994 15:33:10   dennis
** Added code to check to make sure that the user did not enter in a physical
** address for a breakpoint in the shell window.
** 
**    Rev 1.43   11 May 1994 09:58:16   ernie
** Added 2 break causes for Intel.
** 
**    Rev 1.42   06 Apr 1994 16:55:48   nghia
** Fixed bug in breakpoint address:
** - Replace the AdrCreateAddress() with CpuGetPC() to create breakpoint
** address descriptor.  This will ensure that breakpoint address is at least
** compatible with the current processor address space.
** - Use AdrComparePhysicalAddresses() for portability.
** 
**    Rev 1.41   07 Oct 1993 12:39:00   ernie
** Added support for stepMask shell command
** 
**    Rev 1.40   28 Jun 1993 07:24:48   doug
** use general syntax error message
** 
**    Rev 1.39   13 May 1993 15:01:46   nghia
** Added AddressHasNoBkpt() to detect setting multiple breakpoints at the same
** location. - Breakpoint Server PIP for ver. 2.0
** Added clear breakpoint using address.  New syntax: BkptClear @id|all<address>
** 
**    Rev 1.38   22 Mar 1993 07:56:16   ernie
** Added cause ROM breakpoint step failure for PowerScope
** 
**    Rev 1.37   12 Feb 1993 17:46:34   brucea
** Put return error statements on separate line
** 
**    Rev 1.36   06 Jan 1993 17:35:16   brucea
** Changed order of starting emulation and sending message to CLI; now it sends
**    message first.
** 
**    Rev 1.35   16 Dec 1992 07:19:28   brucea
** made cliServerHandle available to bkptexec so that SendMessage works to
**   CLI with system var info
** 
**    Rev 1.34   10 Dec 1992 07:54:52   ernie
** Added external break request break cause support for PowerScope
** 
**    Rev 1.33   08 Dec 1992 06:47:32   brucea
** Added: runaccess event notification
** 
**    Rev 1.32   03 Dec 1992 08:01:10   brucea
** Added: extern globalEscPushed
** Changed: DisplayBkpt; removed #, substituted commas
** Changed using strcat to using stpcpy which is more efficient
** Added: checks for globalEscPushed to contain error code from bkptexec.c
**    module indicating user pushed ESC after emulator started running
**    Used to pass message to cli which is lost with a callback
** 
**    Rev 1.31   06 Nov 1992 07:19:24   brucea
** Fixed: local string buffer size bug in DisplayBkpt
** 
**    Rev 1.30   15 Oct 1992 18:25:20   brucea
** Changed: CLI stmt to statement; naming of causes to match status display
** 
** 
**    Rev 1.29   14 Sep 1992 17:35:18   brucea
** Added: BxCliResetAndGo
** 
**    Rev 1.28   29 Aug 1992 22:02:52   brucea
** Fixed: deletion of addr descriptor for SymGetAddrFromName call in BxCliSetBkpt
** 
**    Rev 1.27   28 Aug 1992 21:10:24   brucea
** Removed: substitute string for source line; cannot get source line from Actor
** 
**    Rev 1.26   27 Aug 1992 14:45:44   brucea
** Changed: BX_EMULATION_STATE and BX_CAUSE to use those defined in sdtempl.h
** 
**    Rev 1.25   20 Aug 1992 20:34:50   brucea
** Removed: addr creation before calling SymGetAddrFromName
** Removed: processor dependency when setting SPACE_SP
** 
**    Rev 1.24   18 Aug 1992 19:25:32   brucea
** Changed: AdrConvAdressToText to ..WithParams
** 
**    Rev 1.23   18 Aug 1992 18:42:26   brucea
** Changed: wording and implementation of output messages for BxCliCause
** 
**    Rev 1.22   12 Aug 1992 09:53:36   brucea
** Removed: test for return value of SendMessage
** Removed: compiler warnings
** 
**    Rev 1.21   10 Aug 1992 09:27:22   tom
** New CLI registration.
** 
**    Rev 1.20   10 Aug 1992 08:53:02   brucea
** Changed: BxCliStep to hold static info on type of step - into or over - and
**    now call BxAsmStepIntoOrOver
** 
**    Rev 1.19   31 Jul 1992 18:37:22   brucea
** Removed: output text when giving halt command
** 
**    Rev 1.18   30 Jul 1992 18:14:56   brucea
** Changed looping initializations to 0
** Put bkpt output on one line and removed code to display source line
** 
**    Rev 1.17   28 Jul 1992 21:26:32   brucea
** Removed unused vars and cast vars that generated possible-loss-of-
**    significance
** Changed: All SendCliMessage calls to BxSendCliMessage without handle param
** 
**    Rev 1.16   23 Jun 1992 18:55:00   brucea
** Changed: Bx... to Bk... for those functions moved to BkRoot
** 
**    Rev 1.15   15 Jun 1992 10:00:20   brucea
** Added: BxCliIsEmuHalted to test for emu halted from CLI
**        BxCliRunAccess to allow or prohibit access to emu while it is running
** 
**    Rev 1.14   20 May 1992 11:34:16   mindy
** initCServer needs to return GOOD if no errors
** 
**    Rev 1.13   15 May 1992 16:09:32   brucea
** Removed: local memory macros
** Cleaned up: SendMessageToCli code
**           : InitCServer code
** 
**    Rev 1.12   01 May 1992 17:34:20   brucea
** Added: setting of address space prior to setting bkpt
** Changed: starting index for accessing bkpts; 1 points to HW bkpt, 2 points to
**    beginning of SW bkpts
** 
**    Rev 1.11   20 Apr 1992 10:07:14   brucea
** Removed: forever keyword
** Added: check for no valid cliHandle before sending text to CLI in function
**    SendCliMessage
** Changed: low level parse of address using strtoul to call to 
**    AdrConvTextToAddress
** Removed: call to BxInit int InitCServer (put into Actor code) so that the
**    CLI server doesn't have to called up for the bkpt server to be used
** 
**    Rev 1.10   03 Apr 1992 18:50:42   brucea
** Changed: name BxCliRunning to BxCliEmuStatus
** Misc. code changes and bug fixes
** 
**    Rev 1.9   26 Mar 1992 18:20:08   brucea
** Added: #ifndef __CTYPE_H
** Added: PRIVATE vars for state info for go parameters
** Added: BxSendCliMessage, BxCliStepSrc, BxCliGoUntil, BxCliGoInto
** Changed: numCommands to 10
** 
**    Rev 1.8   16 Mar 1992 13:33:18   brucea
** Added: ALL choice for BxCliDeleteBkpt
** Added: check for adding bkpt - check for a new bkpt with state or life input
**    and no address; this is an error
** Fixed: display of $ around text when column start and end are equal
** 
**    Rev 1.7   12 Mar 1992 23:13:14   brucea
** Major changes to many functions.
** Added: registration of event notification for symbols deleted and
**    initial load of symbols
** 
**    Rev 1.6   03 Mar 1992 07:36:42   jim
** address buffer size is now in the address header file
** 
**    Rev 1.5   28 Feb 1992 07:41:16   doug
** bugs found during testing
** 
**    Rev 1.4   17 Feb 1992 07:54:20   doug
** completed low level CLI for breakpoint and execution control
** 
**    Rev 1.3   05 Feb 1992 15:43:08   doug
** cleaned up error message and compiler problems.  Does not support
** Source Level yet.
** 
**    Rev 1.2   04 Feb 1992 14:17:32   doug
** Cheerson's latest changes
** 
**  $Header:   S:/tbird/mt2_186/bkptexec/brkexcli.c_v   1.2   26 Aug 1997 10:49:26   Judy  $
**
**  Copyright (C) 1991 Microtek International.  All rights reserved.
**
*****************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/

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

#ifndef _BASETYPE_
#include "basetype.h"
#endif

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

#ifndef _BKPTEXEC_
#include "bkptexec.h"
#endif

#ifndef _BKROOT_
#include "bkroot.h"
#endif

#ifndef _BX_
#include "bx.h"
#endif

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

#ifndef __CTYPE_H
#include <ctype.h>
#endif

#ifndef _ENLIB_
#include "enlib.h"
#endif

#ifndef _EVENTS_
#include "events.h"
#endif

#ifndef _SDPROBE_
#include "sdprobe.h"
#endif

#ifndef _SSHARED_
#include "sshared.h"
#endif

#ifndef __STDLIB_H
#include <stdlib.h>
#endif

#ifndef __STRING_H
#include <string.h>
#endif

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

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

                       /****************************
                        *                          *
                        *     GLOBAL DEFINITIONS   *
                        *                          *
                        ****************************/

HANDLE cliServerHandle = 0; /* return address for CLI results */

                        /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/


/* state variables used in BxCliStepSrc, BxCliGoUntil, BxCliGoInto */
PRIVATE BX_STEP_TYPE stepIntoOverState = BX_STEP_OVER;
PRIVATE BX_GRANULARITY granState = BX_STATEMENT_GRAN;
PRIVATE BX_CALL_RETURN_TYPE callReturnState = BX_CALL_RETURN;
PRIVATE BX_STEP_TYPE asmStepIntoOverState = BX_STEP_INTO;


#define ENABLE_TEXT "enable"
#define DISABLE_TEXT "disable"
#define PERMANENT_TEXT "permanent"
#define TEMPORARY_TEXT "temporary"
#define DELETEALL_TEXT "all"

/* text for StepSrc parameters */
#define INTO_TEXT "into"
#define OVER_TEXT "over"
#define LINE_TEXT "line"
#define STATEMENT_TEXT "statement"
#define CALL_TEXT "call"
#define RETURN_TEXT "return"


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

extern BX_BREAKPOINT bkptTable[];
extern RETCODE       globalEscPushed; /* returns ESC error if it happened
                                         while in call-back */
extern PROCESSOR_FAMILY staticProcFamily;

                        /****************************
                         *                          *
                         *     LOCAL PROTOTYPES     *
                         *                          *
                         ****************************/

RETCODE PRIVATE SendCliMessage(HANDLE cliHandle, LPSTR msgPtr);
RETCODE PRIVATE DisplayAllBkpts(VOID);
RETCODE PRIVATE DisplayBkpt(BKPT_INDEX index);
RETCODE PRIVATE ChangeAllBkptState(BX_BPSTATE state);
RETCODE PRIVATE ChangeAllBkptLife(BX_BPLIFE life);
BOOLEAN PRIVATE BkptActive(U16 cliNumber, BKPT_INDEX *index);

                        /****************************
                         *                          *
                         *      EXECUTABLE CODE     *
                         *                          *
                         ****************************/

/*---------------------------------------------------------------------------
**  BxSendCliMessage
**
**  Description:
**     Send a text string to CLI
----------------------------------------------------------------------------*/
RETCODE BxSendCliMessage(LPSTR msgPtr) {
   return SendCliMessage(cliServerHandle, msgPtr);
}


/*---------------------------------------------------------------------------
**  SendCliMessage
**
**  Description:
**     Send a text string to CLI
**
**  Input parameters:
**        cliHandle:  handle to cli window
**        msgPtr:     message pointer
----------------------------------------------------------------------------*/
RETCODE PRIVATE SendCliMessage(HANDLE cliHandle, LPSTR msgPtr) {

   HANDLE msgBufHandle;
   CSERVER_RESULTS FAR  *msgBufPtr;
   U16         msgTextSize, loop ;

   if (!cliHandle)  /* don't do anything if not a valid cli handle */
      return GOOD;
   msgTextSize = lstrlen(msgPtr);
   msgBufHandle = GlobalAlloc(GMEM_MOVEABLE,
                              (sizeof(CSERVER_RESULTS) + msgTextSize + 2));
   if (msgBufHandle == (HANDLE)NULL) {
      return(ER_OUT_OF_MEMORY); /* FAILED */
   }
   else if((msgBufPtr=(CSERVER_RESULTS *)GlobalLock(msgBufHandle)) == NULL) {
      return(ER_WINDOWS_MEMLOCK) ; /* FAILED */
   }
   msgBufPtr->target               = 0;        /* CLI: not yet def'ed */
   msgBufPtr->variantCode          = CLI_SERVER_RESULTS;
   msgBufPtr->resultTextLength     = msgTextSize; /* message string length */
   for (loop = 0; loop < msgTextSize; loop++ ) {
      msgBufPtr->messageText[loop]  =  *msgPtr++;
   }
   msgBufPtr->messageText[msgTextSize+1] = 0 ;

   /* output message to memBufPtr->messageText[] */
   GlobalUnlock(msgBufHandle);

   SendMessage(cliHandle, CLI_SERVER_RESULTS,
               msgBufHandle, CLI_SERVER_RESULTS);
   return GOOD;
}

/*
**
** Breakpoints
**
*/

/*---------------------------------------------------------------------------
**  BxCliSetBkpt
----------------------------------------------------------------------------*/
#pragma argsused
#pragma warn -aus
RETCODE EXPORT BxCliSetBkpt(LPSTR cmdString, U32 argc, U32 argv[]) {

   RETCODE err, err1;
   U16 arg;
   BOOLEAN idSpec=FALSE, stateSpec=FALSE, lifeSpec=FALSE, addrSpec=FALSE,
           symSpec = FALSE;

#define paramSpec (stateSpec || lifeSpec || addrSpec || symSpec)

   LPSTR             lpParam;
   BX_BPSTATE        state = BX_ENABLED;
   BX_BPLIFE         life = BX_PERMANENT;
   DESCRIPTOR        addrDesc;
   U16               id;
   SYM_DESCRIPTOR    moduleDesc;
   LINENUM_TYPE      actualLinenum;
   COLUMN_RANGE_TYPE actualColumnRange;
   BKPT_INDEX        index;
   ADDR_TYPE         addrType;
   SYM_TYPE_TYPE     symType;

   for(arg=1; arg<argc; arg++) {
      lpParam = &(cmdString[(U16)argv[arg]]);
      if(lpParam[0]=='#') {
         /* parse symbolic address */
         if (addrSpec)
            return ER_CLI_SYNTAX;
         if (GOOD !=
            (err = SymGetAddrFromName(lpParam,
                                      SYM_CODE_ADDR,
                                      &moduleDesc,
                                      &addrDesc, /* allocs addr */
                                      &actualLinenum,
				      &actualColumnRange,
				      &symType))) {
            return err;
         }
         /* set space to SP */
         if (FAMILY_68K == staticProcFamily) {
            if(GOOD != (err = AdrSetAddrSpace(addrDesc, SPACE_SP)))
               return err;
         }
         symSpec = TRUE;
         
      } else if(lpParam[0]=='@') {
         /* id specified */
         char *endptr;
         U32 localId;
         if (strlen(lpParam) < 2)
            return ER_CLI_SYNTAX;
         localId = strtoul(&lpParam[1], &endptr, 0);
         if(*endptr!='\0')
            return ER_CLI_SYNTAX;
         if (localId > MAX_CLI_BKPT_NUMBER)
            return ER_BX_ID_TOO_BIG;
         id = (U16)localId;
         idSpec = TRUE;

      } else if(strncmpi(lpParam, ENABLE_TEXT, strlen(lpParam))==0) {
         state = BX_ENABLED;
         stateSpec = TRUE;
      } else if(strncmpi(lpParam, DISABLE_TEXT, strlen(lpParam))==0) {
         state = BX_DISABLED;
         stateSpec = TRUE;
      } else if(strncmpi(lpParam, PERMANENT_TEXT, strlen(lpParam))==0) {
         life = BX_PERMANENT;
         lifeSpec = TRUE;
      } else if(strncmpi(lpParam, TEMPORARY_TEXT, strlen(lpParam))==0) {
         life = BX_TEMPORARY;
         lifeSpec = TRUE;
      } else {

         /* must be an address */
         if (symSpec)
            return ER_CLI_SYNTAX;
         /* use the current PC instead of the default address descriptor */ 
         if ((err = CpuGetPC(&addrDesc))!=GOOD) return(err);

         if (FAMILY_68K == staticProcFamily) {
            if(GOOD != (err = AdrSetAddrSpace(addrDesc, SPACE_SP)))
               return err;
         }
         /* fills out the address descriptor */
         if((err = AdrConvTextToAddress(addrDesc, lpParam)) != GOOD) {
            err1 = AdrDestroyAddress(addrDesc);
            return err;
         }
         addrSpec = TRUE;
         /* Now check to make sure the address type is not physical. The */
         /* user can not enter a physical address for a breakpoint.      */
         if ((err = AdrGetAddrType(addrDesc, (ADDR_TYPE FAR *)&addrType))
            != GOOD) return err;
         if (addrType == ADDR_PHYSICAL || addrType == ADDR_LINEAR)
            return ER_ADR_TYPE_NOT_SUPPORTED;
      }
   } /* end of for */

   if(!idSpec && !paramSpec) {  /* no params */
      if((err = DisplayAllBkpts())!=GOOD) return(err);

   } else if(idSpec && !paramSpec) { /* id and no other params */
      if(BkptActive(id, &index)) {
         if((err = DisplayBkpt(index))!=GOOD) return(err);
      } else {
         return(ER_BX_INACTIVE_BKPT);
      }
   } else if(!idSpec) { /* no id but params */

      if(addrSpec||symSpec) {
         if (GOOD != (err = CreateCliBkptNum(&id)))
            return err;
         goto INSERT_ADDR;
      }
      if(stateSpec)
         ChangeAllBkptState(state);
      if(lifeSpec)
         ChangeAllBkptLife(life);

   } else { /* id valid: create a new bkpt or change an existing one */
      DESCRIPTOR desc;

INSERT_ADDR:

      if(BkptActive(id, &index)) {  /* existing bkpt; modifying */
         if(stateSpec) {
            bkptTable[index].state = state;
         } else {
            state = bkptTable[index].state;  /* save for use below */
         }
         if(lifeSpec) {
            bkptTable[index].life = life;
         } else {
            life = bkptTable[index].life;
         }
         if(addrSpec)  { /* change existing address; no symbolic */
            if (GOOD != (err =
               BxSetBkptWithIndex(index, state, life, addrDesc, id, &desc)))
               return err;
         }
         if(symSpec) { /* change existing breakpoint; symbolic entry */
            if (GOOD != (err =
               BxSetSrcBkptFromCli(index,
                                   state,
                                   life,
                                   moduleDesc,
                                   actualLinenum,
                                   actualColumnRange.columnStart,
                                   actualColumnRange.columnEnd,
                                   (LPSTR)'\0', /* no source available */
                                   addrDesc,
                                   id,
                                   &desc)))
               return err;
         }
         if ((stateSpec || lifeSpec) && (!(addrSpec || symSpec))) {
            /* if addrSpec or symSpec, their BxSetBkpt... calls will program
               the bkpt */
            if((err = BkptProgramBkpt(index))!=GOOD) return(err);
         }
      } else {  /* new bkpt */
         DESCRIPTOR desc;

/* NOTE: addrDesc is consumed by BxSetBkpt..., even if it produces an err */

         if(addrSpec) {
            if ((err = AddrHasNoBkpt(addrDesc, life)) != GOOD) {
               AdrDestroyAddress(addrDesc);
               /* Exit, report warning handled by AddrHasNoBkpt() */
               return(err == ER_BX_ALREADY_HAS_BKPT ? GOOD : err);
            }
            if ((err = GetAvailableBkpt(&index)) != GOOD) {
               AdrDestroyAddress(addrDesc);
               return(err);
            }
            if ((err = BxSetBkptWithIndex(index, state, life, addrDesc,
                                         id, &desc))!=GOOD)
               return(err);
         }
         if(symSpec) {
            /* both addrSpec and SymSpec should never be simultaneous TRUE */
            /* set symbolic breakpoint */
            if ((err = AddrHasNoBkpt(addrDesc, life)) != GOOD) {
               AdrDestroyAddress(addrDesc);
               /* Exit, report warning handled by AddrHasNoBkpt() */
               return(err == ER_BX_ALREADY_HAS_BKPT ? GOOD : err);
            }
            if ((err = GetAvailableBkpt(&index)) != GOOD) {
               AdrDestroyAddress(addrDesc);
               return(err);
            }
            if (GOOD != (err =
               BxSetSrcBkptFromCli(index,
                                   state,
                                   life,
                                   moduleDesc,
                                   actualLinenum,
                                   actualColumnRange.columnStart,
                                   actualColumnRange.columnEnd,
                                   (LPSTR)"",/* no source line at this time */
                                   addrDesc,
                                   id,
                                   &desc)))
               return err;
         }
         /* new id, state or life params but no address (an error) */
         if ((stateSpec || lifeSpec) && (!(addrSpec || symSpec))) {
            return ER_CLI_SYNTAX;
         }

         bkptTable[(BKPT_INDEX)desc].type = BX_SET_FROM_CLI;
         bkptTable[(BKPT_INDEX)desc].cliBkptNumber = id;
      }
   }
   return(GOOD);
}  /* end of BxCliSetBkpt */


/*---------------------------------------------------------------------------
**  DisplayAllBkpts
----------------------------------------------------------------------------*/
RETCODE PRIVATE DisplayAllBkpts(VOID) {

   RETCODE err;
   BKPT_INDEX i;
   BOOLEAN    isBkpt = FALSE;

   for(i=0; i<MAX_NUM_BKPT; i++) {
      if (bkptTable[i].type != BX_NOT_BEING_USED) {
         if((err = DisplayBkpt(i))!=GOOD)
            return(err);
         isBkpt = TRUE;
      }
   }
   if (!isBkpt) {
      BxSendCliMessage("No breakpoints set");
   }
   return(GOOD);
}


/*---------------------------------------------------------------------------
**  DisplayBkpt
----------------------------------------------------------------------------*/
RETCODE PRIVATE DisplayBkpt(BKPT_INDEX index) {

   RETCODE err;
   S8 buf[MAX_SYMNAME_LENGTH + ADDR_BUFF_SZ + 3];
                           /* the 2 is for $'s surrounding statement */
   S8 tempBuf[MAX_STMT_TEXT + 1];
   S8 *bufPtr;
   
   bufPtr = &buf[0];   /* start out pointing to beginning of buffer */
   switch(bkptTable[index].type) {
      case BX_NOT_BEING_USED:
         return(ER_BX_INACTIVE_BKPT);
      case BX_SET_FROM_ASM:
         bufPtr = stpcpy(bufPtr, "ASM bkpt: ");
         break;
      case BX_SET_FROM_CLI:
         bufPtr = stpcpy(bufPtr, "CLI bkpt: ");
         break;
      case BX_SET_FROM_SRC:
         bufPtr = stpcpy(bufPtr, "SRC bkpt: ");
         break;
      case BX_SET_INTERNAL:
         bufPtr = stpcpy(bufPtr, "INT bkpt: ");
         break;
      default:
         bufPtr = stpcpy(bufPtr, "internal err: ");
         break;
         
   }
   switch(bkptTable[index].state) {
      case BX_ENABLED:
         bufPtr = stpcpy(bufPtr, "Ena ");
         break;
      case BX_DISABLED:
	 bufPtr = stpcpy(bufPtr, "Dis ");
         break;
      default:
         bufPtr = stpcpy(bufPtr, "Unkn ");
         break;
   }
   switch(bkptTable[index].life) {
      case BX_PERMANENT:
         bufPtr = stpcpy(bufPtr, "Perm ");
         break;
      case BX_DISABLED:
         bufPtr = stpcpy(bufPtr, "Temp ");
	 break;
      default:
         bufPtr = stpcpy(bufPtr, "Unkn ");
         break;
   }
   /* display the address */
   {
      S8 addrBuf[ADDR_BUFF_SZ];
      if((err = AdrConvAddressToTextWithParams(bkptTable[index].addr,
                                               TRUE,
                                               FALSE,
                                               (LPSTR)addrBuf))
         !=GOOD) return(err);
      bufPtr = stpcpy(bufPtr, addrBuf);
   }
   /* display the breakpoint number assigned (regardless of source */
   sprintf(tempBuf, " (@%u)", bkptTable[index].cliBkptNumber);
   bufPtr = stpcpy(bufPtr, tempBuf);

   //---------------------------------------------------------------
   // symbolic display - module ref, function name, linenum, columns
   //---------------------------------------------------------------
   /* check for legit symbol */
   if (NULL_SYMBOL != bkptTable[index].module) { 
      bufPtr = stpcpy(bufPtr, " ");

      /* first copy the module path (ref) and name */
      /* if there is module reference, else use the module name */
      if ((bkptTable[index].modRefName != NULL) &&
          (strlen((LPSTR)(bkptTable[index].modRefName)) > 0))
         bufPtr = stpcpy(bufPtr, (LPSTR)(bkptTable[index].modRefName));
      else {
         if (bkptTable[index].modName != NULL)
            bufPtr = stpcpy(bufPtr, (LPSTR)(bkptTable[index].modName));
      }
      if (bkptTable[index].functionName != NULL) {
         bufPtr = stpcpy(bufPtr, ",");
         bufPtr = stpcpy(bufPtr, (LPSTR)(bkptTable[index].functionName));
      }
      /* insert line and column # */
      if (bkptTable[index].lineNumber) { /* only if not 0 */
         sprintf(tempBuf, ",Line%u", bkptTable[index].lineNumber);
         bufPtr = stpcpy(bufPtr, tempBuf);
      }
      if (bkptTable[index].columnRange.columnStart) { /* only if not 0 */
         sprintf(tempBuf, ",Col%hu-%hu",
                  bkptTable[index].columnRange.columnStart,
                  bkptTable[index].columnRange.columnEnd);
         bufPtr = stpcpy(bufPtr, tempBuf);
      }

#if 0   /* cannot display source line yet until source file handling code
           is written in C or C++ */
      /* display source line */
      if ((LPSTR)(bkptTable[index].statementTextPtr) != '\0') {
         /* modify the statement text with $ marks where the column start and
            end points are, then output */
         LPSTR srcPtr, destPtr;
         U8    count;
         COLUMN_TYPE start, end;

         start = bkptTable[index].columnRange.columnStart;
         end   = bkptTable[index].columnRange.columnEnd;

         srcPtr = (LPSTR)bkptTable[index].statementTextPtr;
         destPtr = &tempBuf[0];

         /* compensate for equal start-end columns if end is not max'ed out */
         if ((start == end) && (end != SYM_MAX_COLUMN)) {
            end++;
         }
         count = start;

         /* copy text prior to column start */
         if (count) count--;     /* column 1 is first char in statementText */
         while ((count--) && (*srcPtr))  {
            *destPtr++ = *srcPtr++;
         }
         if (*srcPtr) {
            *destPtr++ = '$';       /* insert column start marker */
            /* copy text between start and end */
            count = end - start;
            if (*srcPtr) {
               while ((count--) && (*srcPtr)) {
                  *destPtr++ = *srcPtr++;
               }
               *destPtr++ = '$';       /* insert column end marker */
               /* copy text after column end; will exit if already at end */
               while (*srcPtr) {
                  *destPtr++ = *srcPtr++;
               }
            }
         }
         *destPtr = '\0';  /* null terminate */
         sprintf(buf, "  #%u:%s", bkptTable[index].lineNumber, tempBuf);
      }
#endif
      
   }  /* end of if */   
   BxSendCliMessage(buf);
   return(GOOD);
}  /* end of DisplayBkpt */

/*---------------------------------------------------------------------------
**  ChangeAllBkptState
----------------------------------------------------------------------------*/
RETCODE PRIVATE ChangeAllBkptState(BX_BPSTATE state) {

   if (state==BX_ENABLED) return(BxEnableAllBkpts());
   return(BxDisableAllBkpts());
}

/*---------------------------------------------------------------------------
**  ChangeAllBkptLife
----------------------------------------------------------------------------*/
RETCODE PRIVATE ChangeAllBkptLife(BX_BPLIFE life) {

   BKPT_INDEX i;

   for(i=0; (i<MAX_NUM_BKPT) && (bkptTable[i].type!=BX_NOT_BEING_USED); i++)
      bkptTable[i].life = life;
   return(GOOD);
}

/*---------------------------------------------------------------------------
**  BkptActive
**
**  Purpose: return TRUE if the cliNumber is found in the list of active
**           breakpoints
**
**  Input Parameter:
**    cliNumber: cli id to match on active bkpt
**
**  Output Parameters:
**    index: location where bkpt matched the cliNumber
**    return: returns TRUE if found; FALSE otherwise
----------------------------------------------------------------------------*/
BOOLEAN PRIVATE BkptActive(U16 cliNumber, BKPT_INDEX *index) {

   for ((*index) = 0; (*index) < MAX_NUM_BKPT; (*index)++) {
                
      if ((bkptTable[*index].type != BX_NOT_BEING_USED) &&
          (bkptTable[*index].cliBkptNumber == cliNumber))
         return(TRUE);
   }
   return(FALSE);
}


/*---------------------------------------------------------------------------
**  CreateCliBkptNum
**
**  Description:
**     create a new "@cliBkptNumber"
**
**  Parameters:
**     input:
**        none
**     output:
**        num: a new cliBkptNumber
----------------------------------------------------------------------------*/
RETCODE CreateCliBkptNum(U16 *num) {

   RETCODE    err;
   BKPT_INDEX index, dummyIndex;
   U16        i;

   if ((err = GetAvailableBkpt(&index)) != GOOD)
      return(err);
   /* go a little beyond largest bkpt number to find an unused number */
   for (i = 0; i <= (MAX_NUM_BKPT); i++) {
      if (!BkptActive(i, &dummyIndex))  {
         *num = i;
         return GOOD;
      }
   }
   return ER_BX_NO_BKPT_AVAILABLE;  /* only if loop completes */
}  /* end of CreateCliBkptNum */


/*---------------------------------------------------------------------------
**  BxCliDeleteBkpt
----------------------------------------------------------------------------*/
RETCODE EXPORT BxCliDeleteBkpt(LPSTR cmdString, U32 argc, U32 argv[]) {
   U16        id;
   U32        localId;
   S8         *endptr;
   BKPT_INDEX index;
   RETCODE    err;
   
   if (argc == 2) {
      if (cmdString[(U16)argv[1]] == '@') {
         /* skip over @ and convert number to binary */
         localId = strtoul(&(cmdString[(U16)argv[1]+1]), &endptr, 0);
         if(*endptr!='\0')
            return(ER_CLI_SYNTAX);
         if (localId > MAX_CLI_BKPT_NUMBER)
            return ER_BX_ID_TOO_BIG;
            id = (U16)localId;

         if (!BkptActive(id, &index))
            return ER_BX_INACTIVE_BKPT;
         return BxRemoveBkpt((DESCRIPTOR)index);

      } else if (strncmpi(&cmdString[(U16)argv[1]], DELETEALL_TEXT,
                          strlen(&cmdString[(U16)argv[1]]))==0) {

         /* matches "all" choice */
         return BxRemoveAllBkpts();
      } else {
         LPSTR             lpParam;
         DESCRIPTOR        addrDesc;
         SYM_DESCRIPTOR    moduleDesc;
         LINENUM_TYPE      actualLinenum;
         COLUMN_RANGE_TYPE actualColumnRange;
	 ADDR_COMPARE      result;
         SYM_TYPE_TYPE     symType;

         lpParam = &(cmdString[(U16)argv[1]]);
         /* Symbolic address start with '#' */
         if (lpParam[0] == '#') {
            /* parse symbolic address */
            if (GOOD !=
               (err = SymGetAddrFromName(lpParam, SYM_CODE_ADDR, &moduleDesc,
                      &addrDesc, /* allocs addr - Must clean up when done */
		      &actualLinenum, &actualColumnRange, &symType))) {
               return err;
            }
            /* set space to SP */
            if (FAMILY_68K == staticProcFamily) {
               if(GOOD != (err = AdrSetAddrSpace(addrDesc, SPACE_SP)))
                  goto CLEANUP;
            }
         } else  {
            /* Numeric address - use the current PC */
            if ((err = CpuGetPC(&addrDesc))!=GOOD)
               return(err);
            if (FAMILY_68K == staticProcFamily) {
               if(GOOD != (err = AdrSetAddrSpace(addrDesc, SPACE_SP)))
                  goto CLEANUP;
            }
            /* fills out the address descriptor */
            if((err = AdrConvTextToAddress(addrDesc, lpParam)) != GOOD) {
               goto CLEANUP;
            }
         }
         /* Check for breakpoints have the same address then remove      */
         /* NOTES: do not use bkptCount, dued to no checking on          */
         /* re-entrance (e.g. While the Shell remove bkpt, other callers */
         /* can set bkpt, which causes the bkptCount to changes.         */
         for (index = 0; index < MAX_NUM_BKPT; index++) {
            if ((bkptTable[index].type != BX_NOT_BEING_USED) &&
               (bkptTable[index].life != BX_TEMPORARY_INTERNAL) &&
               (AdrComparePhysicalAddresses(bkptTable[index].addr, addrDesc,
                                (ADDR_COMPARE FAR *) &result) == GOOD)) {
               if (result == EQUAL_ADDRS) {
                  // Remove breakpoint
                  err = BxRemoveBkpt((DESCRIPTOR)index);
                  goto CLEANUP; // get out of for loop and cleanup
               }
            }
         } // for
         err = ER_BX_NO_BKPT_MATCH_ADDR;
CLEANUP:
         // Get rid of the unused address descriptor
         AdrDestroyAddress(addrDesc);
         return(err);
      } /* fall thru to syntax error */
   } /* end of if (argc == 2) */
   return(ER_CLI_SYNTAX);
} /* end of BxCliDeleteBkpt */

/*---------------------------------------------------------------------------
**
** Execution Control
**
----------------------------------------------------------------------------*/

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

   RETCODE err;

   if(argc!= 1)
      return(ER_CLI_SYNTAX);

   err = globalEscPushed;
   globalEscPushed = GOOD;
   if (GOOD != err)
      return err;
   /* changing order: outputting message before starting emu because when
      a bkpt is set, the resulting stop point is output to the CLI before
      the "emulation started" message
   */
   if (GOOD != (err = BxSendCliMessage((LPSTR) "Emulation started")))
      return err;
   return BxStartEmulation();
}  /* end of BxCliGo */


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

   RETCODE err;

   if(argc!= 1)
      return(ER_CLI_SYNTAX);

   err = globalEscPushed;
   globalEscPushed = GOOD;
   if (GOOD != err)
      return err;
   if((err = BxResetAndStartEmulation())!= GOOD)
      return(err);
   return BxSendCliMessage((LPSTR) "Target reset, emulation started");
}  /* end of BxCliResetAndGo */


/*---------------------------------------------------------------------------
**  BxCliStep
**
**  Syntax:
**    Step [ASM | SRC] [<count>]
**
**    The initial mode is ASM.  If the second param is not entered, the step
**    operates using the last step type (ASM or SRC).
**
**  Design Notes:
**     Have to display the relative fields of the shared data template
----------------------------------------------------------------------------*/
#pragma argsused
RETCODE EXPORT BxCliStep(LPSTR cmdString, U32 argc, U32 argv[]) {

   LPSTR   lpParam;
   U32     stepCount;
   U16     arg;
   BOOLEAN countSpec=FALSE;
   RETCODE err;
   
   stepCount = 1;

   err = globalEscPushed;
   globalEscPushed = GOOD;
   if (GOOD != err)
      return err;

   for(arg=1; arg<argc; arg++) {
      lpParam = &(cmdString[(U16)argv[arg]]);

      if(isdigit((S16) lpParam[0])) { /* isdigit returns nonzero if 0-9 */
         /* count specified */
         char *endptr;

         if (countSpec) return ER_CLI_SYNTAX;  /* too many number params */
         stepCount = strtoul(&lpParam[0], &endptr, 0);
         if(*endptr!='\0') return(ER_CLI_SYNTAX);
         countSpec = TRUE;

      } else if(strncmpi(lpParam, INTO_TEXT, strlen(lpParam))==0) {
         asmStepIntoOverState = BX_STEP_INTO;

      } else if(strncmpi(lpParam, OVER_TEXT, strlen(lpParam))==0) {
         asmStepIntoOverState = BX_STEP_OVER;
      } else {
      return ER_CLI_SYNTAX;
      }
   } /* end of for */
   return BxAsmStepIntoOrOver(stepCount, asmStepIntoOverState);
} /* end of BxCliStep */

/*---------------------------------------------------------------------------
**  BxCliStepRange
**
**  Syntax:
**    StepRange <addr1> <addr2>
**
**  Design Notes:
**     Have to display the relative fields of the shared data template
----------------------------------------------------------------------------*/
#pragma argsused
RETCODE EXPORT BxCliStepRange(LPSTR cmdString, U32 argc, U32 argv[]) {

   LPSTR   lpParam;
   U16     arg;
   U32 addr1, addr2;
   DESCRIPTOR  desc;
   RETCODE err;
   
   err = globalEscPushed;
   globalEscPushed = GOOD;
   if (GOOD != err)
      return err;

   if (argc != 3) return ER_CLI_SYNTAX;
   AdrCreateAddress(&desc);
   AdrSetAddrSegmentSelector(desc,ADDR_USE_CS,NULL);
   if ((err = AdrConvTextToAddress(desc,&cmdString[(U16)argv[1]])) != GOOD) {
      AdrDestroyAddress(desc);
      return(err);
   }
   AdrGetAddrPhysicalOffset(desc, &addr1);
   if ((err = AdrConvTextToAddress(desc,&cmdString[(U16)argv[2]])) != GOOD) {
      AdrDestroyAddress(desc);
      return(err);
   }
   AdrGetAddrPhysicalOffset(desc, &addr2);
   AdrDestroyAddress(desc);

   return BxAsmStepRange(addr1, addr2);
} /* end of BxCliStep */


/*---------------------------------------------------------------------------
**  BxCliStepSrc
**
**  Syntax:
**    SrcStep [INTO | OVER] [LINE | STMT] [<count>]
**
**    If parameters are missing, the function uses the last set value (or
**    default value) as the parameter.
**
----------------------------------------------------------------------------*/
#pragma argsused
RETCODE EXPORT BxCliStepSrc(LPSTR cmdString, U32 argc, U32 argv[]) {

   LPSTR   lpParam;
   U32     stepCount;
   U16     arg;
   BOOLEAN countSpec=FALSE;
   RETCODE err;
   
   stepCount = 1;

   err = globalEscPushed;
   globalEscPushed = GOOD;
   if (GOOD != err)
      return err;

   for(arg=1; arg<argc; arg++) {
      lpParam = &(cmdString[(U16)argv[arg]]);

      if(isdigit((S16) lpParam[0])) { /* isdigit returns nonzero if 0-9 */
         /* count specified */
         char *endptr;

         if (countSpec) return ER_CLI_SYNTAX;  /* too many number params */
         stepCount = strtoul(&lpParam[0], &endptr, 0);
         if(*endptr!='\0') return(ER_CLI_SYNTAX);
         countSpec = TRUE;

      } else if(strncmpi(lpParam, INTO_TEXT, strlen(lpParam))==0) {
         stepIntoOverState = BX_STEP_INTO;

      } else if(strncmpi(lpParam, OVER_TEXT, strlen(lpParam))==0) {
         stepIntoOverState = BX_STEP_OVER;

      } else if(strncmpi(lpParam, LINE_TEXT, strlen(lpParam))==0) {
         granState = BX_LINE_GRAN;

      } else if(strncmpi(lpParam, STATEMENT_TEXT, strlen(lpParam))==0) {
         granState = BX_STATEMENT_GRAN;
      } else {
      return ER_CLI_SYNTAX;
      }
   } /* end of for */
   return BxSrcStep(stepIntoOverState,
                    granState,
                    stepCount);
}  /* end of BxCliStepSrc */


/*---------------------------------------------------------------------------
**  BxCliGoUntil
**
**  Syntax:
**    goUntil [CALL | RETURN] [LINE | STMT]
**
----------------------------------------------------------------------------*/
#pragma argsused
RETCODE EXPORT BxCliGoUntil(LPSTR cmdString, U32 argc, U32 argv[]) {

   RETCODE err;
   LPSTR   lpParam;
   U16     arg;

   err = globalEscPushed;
   globalEscPushed = GOOD;
   if (GOOD != err)
      return err;

   for(arg=1; arg<argc; arg++) {
      lpParam = &(cmdString[(U16)argv[arg]]);

      if(strncmpi(lpParam, CALL_TEXT, strlen(lpParam))==0) {
         callReturnState = BX_CALL_RETURN;

      } else if(strncmpi(lpParam, RETURN_TEXT, strlen(lpParam))==0) {
         callReturnState = BX_RETURN_ONLY;

      } else if(strncmpi(lpParam, LINE_TEXT, strlen(lpParam))==0) {
         granState = BX_LINE_GRAN;

      } else if(strncmpi(lpParam, STATEMENT_TEXT, strlen(lpParam))==0) {
         granState = BX_STATEMENT_GRAN;
      } else {
      return ER_CLI_SYNTAX;
      }
   } /* end of for */
   err = BxGoUntilCallReturn(granState,
                              callReturnState);
   if (err == ER_SYM_NO_FUNCTION_MATCH) {
      BxSendCliMessage((LPSTR) "No function range match to address");

   }
   return err;
}  /* end of BxCliGoUntil */


/*---------------------------------------------------------------------------
** BxCliGoInto 
**
** Syntax:
**   goInto [CALL | RETURN] [LINE | STMT]
**
----------------------------------------------------------------------------*/
#pragma argsused
RETCODE EXPORT BxCliGoInto(LPSTR cmdString, U32 argc, U32 argv[]) {

   RETCODE err;
   LPSTR   lpParam;
   U16     arg;

   err = globalEscPushed;
   globalEscPushed = GOOD;
   if (GOOD != err)
      return err;

   for(arg=1; arg<argc; arg++) {
      lpParam = &(cmdString[(U16)argv[arg]]);

      if(strncmpi(lpParam, CALL_TEXT, strlen(lpParam))==0) {
         callReturnState = BX_CALL_RETURN;

      } else if(strncmpi(lpParam, RETURN_TEXT, strlen(lpParam))==0) {
         callReturnState = BX_RETURN_ONLY;

      } else if(strncmpi(lpParam, LINE_TEXT, strlen(lpParam))==0) {
         granState = BX_LINE_GRAN;

      } else if(strncmpi(lpParam, STATEMENT_TEXT, strlen(lpParam))==0) {
         granState = BX_STATEMENT_GRAN;
      } else {
      return ER_CLI_SYNTAX;
      }
   } /* end of for */
   err = BxGoIntoCallReturn(granState,
                             callReturnState);
   if (err == ER_SYM_NO_FUNCTION_MATCH) {
      BxSendCliMessage((LPSTR) "No function range match to address");

   }
   return err;
}  /* end of BxCliGoInto */


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

   RETCODE err;

   if(argc!= 1)
      return(ER_CLI_SYNTAX);

   err = globalEscPushed;
   globalEscPushed = GOOD;
   if (GOOD != err)
      return err;
   if((err  = BxHaltEmulation()) != GOOD)
      return(err);
   return GOOD;
}  /* end of BxCliHalt */


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

   RETCODE err;
   EMULATION_STATE emulState;

   if(argc!= 1) return(ER_CLI_SYNTAX);
   if((err = BkGetEmulationStatus(&emulState)) != GOOD) return(err);
   switch (emulState) {
      case EM_RUNNING :
      case EM_STEPPING :
         return GOOD;

      case EM_HALTED :
      case EM_HUNG :
         return ER_BX_EMU_IS_HALTED;

      default:
         break;
   }
   return(GOOD);
}  /* end of BxCliIsEmuHalted */


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

   RETCODE err;
   EMULATION_STATE emulState;


   if(argc!= 1)
      return(ER_CLI_SYNTAX);
   if((err = BkGetEmulationStatus(&emulState)) != GOOD) return(err);
   switch (emulState) {
      case EM_RUNNING :
         BxSendCliMessage((LPSTR)"Processor is running.") ;
         break;
      case EM_STEPPING :
         BxSendCliMessage((LPSTR)"Processor is stepping.") ;
         break;
      case EM_HALTED :
         BxSendCliMessage((LPSTR)"Processor is halted.") ;
         break;
      case EM_HUNG :
         BxSendCliMessage((LPSTR)
                          "Processor is hung (target cpu must be reset).") ;
         break;
      default :
         BxSendCliMessage((LPSTR)"Processor status is unknown.") ;
         break;
   }
   return(GOOD);
}


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

   RETCODE     err;
   BREAK_CAUSE cause;
   S8          strBuf[40];

   const S8 *causeNameTable[] = {
      "No cause",
      "Target processor was reset",
      "Emulator was halted",
      "Trigger caused a break",
      "Processor single step",
      "Execution breakpoint reached",
      "Overlay access violation",
      "Processor received a double bus fault",
      "External break request",
      "ROM breakpoint step failure",
      "Program accessed debug registers",
      "Task switch breakpoint",
      "Unknown break cause"
   };

   if(argc!= 1)
      return(ER_CLI_SYNTAX);

   if (GOOD != (err = BxGetCauseOfLastBreak(&cause)))
      return err;

   if (cause > CAUSE_TASK_BKPT)
      cause = CAUSE_TASK_BKPT + 1;
   strcpy(strBuf, causeNameTable[cause]);
   
   return BxSendCliMessage((LPSTR)&strBuf[0]);
}  /* end of BxCliCause */

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

   RETCODE err;
   U8      len;
   BOOLEAN runAccess;
   S8      strBuf[15];

   if (argc == 1)  {
      if (GOOD != (err = BkGetRunAccess(&runAccess)))
         return err;
      strBuf[0] = '\0';
      strcat(strBuf, "run access ");
      if (runAccess) {
         strcat(strBuf, "ON");
      } else {
         strcat(strBuf, "OFF");
      }
      BxSendCliMessage((LPSTR)&strBuf[0]);
      return GOOD;
   }
   if (argc != 2)
      return ER_CLI_SYNTAX;
   len = strlen(&(cmdString[(U16)argv[1]]));
   if ((strncmpi(&(cmdString[(U16)argv[1]]), "ON", max(len, 2))) == 0) {
      if (GOOD != (err = BkSetRunAccess()))
         return err;
      if (GOOD != (err = EnlEventNotify(EVENT_BKROOT_RUNACCESS_ON)))
         return err;
   } else if
      ((strncmpi(&(cmdString[(U16)argv[1]]), "OFF", max(len, 3))) == 0) {
      if (GOOD != (err = BkClearRunAccess()))
         return err;
      if (GOOD != (err = EnlEventNotify(EVENT_BKROOT_RUNACCESS_OFF)))
         return err;
   } else {
      return ER_CLI_SYNTAX;
   }
   return GOOD;
}  /* end of BxCliRunAccess */
   
/*---------------------------------------------------------------------------
**  BxCliStepMask
----------------------------------------------------------------------------*/
RETCODE EXPORT BxCliStepMask(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE err;
   BOOLEAN stepMask;
   U8      len;
   S8      strBuf[32];
   if (argc == 1)  {
      if ((err = BxGetStepMask(&stepMask)) != GOOD) return(err);
      strcpy(strBuf, "stepMask is ");
      strcat(strBuf, stepMask ? "ON" : "OFF");
      BxSendCliMessage(strBuf);
      return(GOOD);
   }
   if (argc != 2) return(ER_CLI_SYNTAX);
   len = strlen(&(cmdString[(U16)argv[1]]));
   if ((strncmpi(&(cmdString[(U16)argv[1]]), "ON", max(len, 2))) == 0) {
      if ((err = BxSetStepMask(TRUE)) != GOOD) return(err);
   } else if ((strncmpi(&(cmdString[(U16)argv[1]]), "OFF", max(len, 3))) == 0){
      if ((err = BxSetStepMask(FALSE)) != GOOD) return(err);
   } else {
      return(ER_CLI_SYNTAX);
   }
   return(GOOD);
}
   
/*
**
** Initialization
**
*/

/*---------------------------------------------------------------------------
** InitCServer
**
** Description: Initialize the commands for the breakpoint/exec Server.
**
** Parameters:
**    input:
**       cliHandle:  CLI Server Handle
**       dllHandle:  DLL Handle.
**
**    output:
**       return a 1 to indicate success
----------------------------------------------------------------------------*/
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);
}
/******************************** E O F ***********************************/
