/****************************************************************************
**
**  Name:  cpucli.c
**
**  Description:
**     Routines to support the Cpu Server cli interface.
**
**  Status: TESTED
**
**  $Log:   S:/tbird/mt2_186/cpu/cpucli.c_v  $
** 
**    Rev 1.1   26 Feb 1997 11:45:26   Judy
** 
**    Rev 1.0   16 Dec 1996 16:01:58   Judy
** Initial revision.
** 
**    Rev 1.31   26 Sep 1994 14:38:56   ernie
** Added config command Shell interface
** 
**    Rev 1.30   11 Aug 1994 15:32:02   dennis
** Fixed register display in shell window so all registers line up properly.
** 
**    Rev 1.29   28 Jul 1994 11:14:32   dennis
** Added "signal all [enable/disable]" command.
** 
**    Rev 1.28   13 Jul 1994 15:10:18   dennis
** Fixes a bug where "invalid command line arguments." error was displayed
** after a "reg" command. Modified CpuCliRegister routine to not return an
** error if displaying registers and ER_INVALID_ARG is returned from
** ShowRegisterValue routine.
** 
**    Rev 1.27   24 Jun 1994 08:23:38   dennis
** Added support for registers AX, AH, AL, BX, BH, BL, CX, CH, CL, DX, DH,
** DL, DI, SI, IP, SP, BP.
** 
**    Rev 1.26   17 Jun 1994 16:26:26   dennis
** Modified reg command so that it does not display any registers that are
** invisible (don't show up in the CPU window).
** 
**    Rev 1.25   02 Jun 1994 14:09:16   dennis
** Added code to check global variable cpuFatalError and not perform any
** operation if set to TRUE. This flag indicates that the cpu.cfg file could
** not be found.
** 
**    Rev 1.24   19 May 1994 16:32:08   dennis
** Added two parameters to CpuGetRegisterInfo call. These two parameters
** are for the fields added to the cpu.cfg file (register index and visible).
** 
**    Rev 1.23   18 May 1994 08:37:34   dennis
** Added routine CpuConvTextToValue. This was necessary to deal with 386
** register editing. The code used to call the address server to handle the
** conversion of text to value, but because the 386 deals with addresses
** differently than the motorola processors, this would not work. For the 386
** if you specify a value (without appending a P or L) then it assumes it is
** an offset and offsets can only be 16 bits, however the 386 registers can be
** 32 bits. The address server would flag an error, so I had to change the cpu
** code.
** 
**    Rev 1.22   07 Apr 1994 12:30:28   john
** Fixed bug in the signal names
** 
**    Rev 1.21   13 Jul 1993 19:28:18   doug
** Use generic syntax error.
** 
**    Rev 1.20   08 Apr 1993 14:39:20   doug
** signal command gives error if PowerScope in use
** 
**    Rev 1.19   30 Mar 1993 08:25:04   ernie
** 1. Changed interface to CpuFindRegisterName().
** 2. Changed _regname command handler to use new CpuGetRegisterInfo()
**    and CpuGetRegisterValueText() calls.
** 3. Changed reg display to include both numeric and symbolic display
**    of flag-type registers.
** 
**    Rev 1.18   05 Jan 1993 15:51:40   courtney
** Removed MemAlloc and related macros (no longer used).
** 
**    Rev 1.17   09 Oct 1992 14:55:04   doug
** a) add reset of cpu only
** b) one syntax error
** 
**    Rev 1.16   17 Sep 1992 10:57:58   doug
** show all registers as 8 digits
** 
**    Rev 1.15   15 Sep 1992 09:06:50   courtney
** Revised error return to standard format.
** 
**    Rev 1.14   08 Sep 1992 09:27:22   doug
** remove event stuff that is commented out
** 
**    Rev 1.13   02 Sep 1992 11:38:32   doug
** a) allow symbolic entry of register values
** b) radix routine not used
** 
**    Rev 1.12   02 Sep 1992 10:31:46   doug
** improve error message
** 
**    Rev 1.11   14 Aug 1992 08:25:44   doug
** removed all warnings except for STRING problem, which is a problem in
** basictyp.h (I wrote a PPR on this).
** 
**    Rev 1.10   08 Aug 1992 08:48:58   tom
** server registration change
** 
**    Rev 1.9   22 Jul 1992 16:05:00   doug
** a) calling from cli is unnessary (bug)
** 
**    Rev 1.8   21 Jul 1992 08:09:26   doug
** a) generic, no more 68030
** b) no aliases anymore
** c) only run-time config supported
** d) no floating point support
** e) SendMessage does not return error; return code is meaningless
** 
**    Rev 1.7   14 Jul 1992 11:26:18   courtney
** CPU Server is now table-driven (reads in processor-specific table
** at runtime).  Changes to reflect architecture change.
** 
**    Rev 1.6   13 May 1992 09:03:28   nghia
** Revised SendMessageToCli() to be a global routine.
** 
**    Rev 1.5   23 Apr 1992 12:11:50   nghia
** Fixed PPR 5390.
** Cleaned up error message return. Added format for CLI results.
** Fixed PPR 5278 - convert an 80bit value.
** Added new EVENT_REGISTERS_CHANGED_HALTED for cpu presenter.
** 
**    Rev 1.4   17 Apr 1992 16:18:48   nghia
** Added CLI command to find register Name.
** 
**    Rev 1.3   08 Apr 1992 10:49:58   nghia
** Fixed PPR #5277 - CLI command to dump registers content and value.
** 
**    Rev 1.2   10 Mar 1992 12:52:40   nghia
** Changed sscanf() to strtoul() for consistency with other CLI commands.
** 
**    Rev 1.1   02 Mar 1992 09:03:36   nghia
** Added floating-point support for the CPU CLI commands.
** 
**    Rev 1.0   28 Feb 1992 11:55:58   nghia
** Initial revision.
**
**  $Header:   S:/tbird/mt2_186/cpu/cpucli.c_v   1.1   26 Feb 1997 11:45:26   Judy  $
**
**
**  Copyright (C) 1991 Microtek International.  All rights reserved.
**
*****************************************************************************/

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

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

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

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

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

#ifndef _CPUCLI_
#include "cpucli.h"
#endif

#ifndef _CPUERR_
#include "cpuerr.h"
#endif

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

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

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

#ifndef _HOSTERRS_
#include "hosterrs.h"
#endif
                        /***************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/

#define MAX_NAME     25 /* Maximum number of characters in a name */
#define MAX_U32SIZE  8
#define MAX_U64SIZE  16
#define MAX_U32WIDTH 32
#define MAX_U64WIDTH 64
#define MAX_FPREG_STRSIZE 20

/* Local buffers */
S8    strBuf[80];
LPSTR status[2] = {"DISABLE", "ENABLE"};
typedef enum { DECIMAL_TYPE, OCTAL_TYPE, HEXADECIMAL_TYPE} RADIX_TYPE;

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

                        /****************************
                         *                          *
                         *    EXTERNAL VARIABLES    *
                         *                          *
			 ****************************/
/* CPU Server data elements Table - defined in CPU.C */
extern REGISTER_ENTRY *regTable;
extern SIGNAL_ENTRY *signalTable;
extern U16 nRegisters;
extern U16 nSignals;
extern U16 cpuFatalError;

                        /****************************
                         *                          *
                         *     LOCAL PROTOTYPES     *
                         *                          *
                         ****************************/
RETCODE PRIVATE CheckCliToken(S8 *buf, U16  *token_no) ;
RETCODE PRIVATE ShowRegisterValue(U16 regId, BOOLEAN showMultiplexed);
RETCODE PRIVATE displaySignalCmdResult(REG_ID sigId, U8 sigValue,
   S8 *sigName, RETCODE cmdErr);
RETCODE PRIVATE FindSignalId(S8 *sigNameStr, REG_ID *sigId);

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

/**************************************************************************
**
** InitCServer
**
***************************************************************************/
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);
}

/* note that all cli entry points must verify that the init table
   routine has been read!!
*/
/***************************************************************************
**
**  CpuCliSignals
**
**  Status:  PRELIMINARY
**
**  description:
**     Cli interface to the signals display
**
**  input:
**     <none>
**
**  output:
**     message:
**        signals value(get signals).
**     <none> : signals modify
**
*****************************************************************************/
RETCODE EXPORT CpuCliSignal(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE     ret ;
   REG_ID      sigId;
   U8          sigValue;
   U16         sigToken;
   PROC_SYSTEM_TYPE systemType;

   /* Don't do anything if the cpu.cfg file was not found. */
   if (cpuFatalError != 0)
      return(ER_BADGET);

   if((ret = ProcReturnSystemType(&systemType))!=GOOD) return(ret);
   if(systemType==PROC_POWERSCOPE) return(ER_SIG_NOT_AVAIL_IN_POWERSCOPE);
   switch(argc) {
	  case 1: /* signal <cr> */
         /* display all signals state */
         for (sigId = 0; sigId<nSignals; sigId++) {
             ret = CpuGetSignal(sigId, (U8 FAR *) &sigValue);
             displaySignalCmdResult(sigId, sigValue, NULL, ret);
         }
         break;

      case 2: /* signal signal_name <cr> */
         if ((ret = FindSignalId(&(cmdString[(int)argv[1]]), &sigId))!=GOOD) {
            displaySignalCmdResult(0, 0, &(cmdString[(int)argv[1]]), ret);
            return(ret);
         }
         ret = CpuGetSignal(sigId, (U8 FAR *) &sigValue);
         displaySignalCmdResult(sigId, sigValue, NULL,ret);
         break;

      case 3:  /* signal signame [enable/disable] */
               /* or  signal all [enable/disable] */
 
         if ((ret = CheckCliToken(&(cmdString[(int)argv[2]]), &sigToken))
            != GOOD) return(ret);

         /* Enable = 1, Disable = 2 according to cliToken_tbl[] index */
         if (sigToken == 1) sigValue = TRUE;
         else if (sigToken == 2) sigValue = FALSE;
         else return(ER_INVALID_ARG);

         if (!strcmpi(&(cmdString[(int)argv[1]]), "all")) {
            for (sigId = 0; sigId<nSignals; sigId++) {
                ret = CpuSetSignal((REG_ID) sigId, sigValue);;
                displaySignalCmdResult(sigId, sigValue, NULL, ret);
            }
         }
         else {
            if ((ret = FindSignalId(&(cmdString[(int)argv[1]]), &sigId))!=GOOD) {
               /* signal name found! */
               displaySignalCmdResult(0, 0, &(cmdString[(int)argv[1]]), ret);
               return(ret);
            }
            /* Set new state for the signal */
            ret = CpuSetSignal((REG_ID) sigId, sigValue);
            displaySignalCmdResult(sigId, sigValue, NULL, ret);
        } /* else */

         break ;

      default:
         return(ER_CLI_SYNTAX) ;
   }  /* end of switch */
   return(GOOD) ;
}

/************************************************************************
**
**  strtoulDefRadix
**
**************************************************************************/
U32 PRIVATE strtoulDefRadix(const CHAR *s, CHAR** endPtr) {

   CHAR *firstChar;
   CHAR *secondChar;
   CHAR *stringPtr;

   firstChar = (CHAR *)s;
   secondChar = (CHAR *)(s + sizeof(CHAR));
   if ((*firstChar == '0') &&
         ((*secondChar == 'x') || (*secondChar == 'X'))) {
      stringPtr = (CHAR *)(s + (2*sizeof(CHAR)));
      return (strtoul(stringPtr,endPtr,16));
   }
   return (strtoul(s,endPtr,16));

}

/***************************************************************************
**
**  CpuConvTextToValue
**
*****************************************************************************/
RETCODE EXPORT CpuConvTextToValue(LPSTR regString, REG_ID regId) {
  RETCODE       ret, err;
  U32           regValue;
  S8            *endPtr;

  /* Don't do anything if the cpu.cfg file was not found. */
  if (cpuFatalError != 0)
     return(ER_BADGET);

  while (isspace((S16)*regString)) {  /* skip over spaces; requires int */
      regString++;
  }

  if (strncmp(regString,"#",1) == GOOD) {  /* symbolic input */
     DESCRIPTOR addrDesc;

     if((ret = AdrCreateAddress(&addrDesc))!=GOOD) return(ret);
     if((ret = AdrConvTextToAddress(addrDesc, regString))!=GOOD)
        return(ret);
     if((ret = AdrGetAddrOffset(addrDesc, &regValue))!=GOOD)
        return(ret);
     if((ret = AdrDestroyAddress(addrDesc))!=GOOD) return(ret);
  }
  else {
     regValue = strtoulDefRadix(regString, &endPtr);
     if (*endPtr != '\0')
        return ER_ADR_INVALID_ADDRESS_STR;
  }
  if ((ret = CpuSetRegister(regId, regValue)) != GOOD)
     return(ret);

   return(GOOD);

}
/***************************************************************************
**
**  CpuCliRegister
**
*****************************************************************************/
RETCODE EXPORT CpuCliRegister(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE       ret;
   BOOLEAN       isWriteData ;
   REG_ID        regId, tempId;
   U16           i;
   S8            regName[MAX_NAME];
   S8            *ptr, lpnext[MAX_NAME]; /* lookahead buffer */
   BOOLEAN       pushBack = FALSE;

/* this syntax is obsolete!  only single register display/update is handled
    (in addition to full dump) */
   /*
   *** SYNTAX SUPPORTED:
   ***    CPU_REGISTER
   ***    CPU_REGISTER A0 1234 D0      (assign A0=1234, display D0)
   ***    CPU_REGISTER A0 D0           (display A0, D0)
   ***    CPU_REGISTER A0 0xffff D0 3  (assign A0=0xffff, assign D0=3)
   ***  (requires single-token lookahead)
   */

   /* Don't do anything if the cpu.cfg file was not found. */
   if (cpuFatalError != 0)
      return(ER_BADGET);

   if (argc == 1) {
      /* Dump all registers and their value */
      for (i = 0; i<nRegisters; i++) {
         /* ShowRegisterValue will return ER_INVALID_ARG if the visible */
         /* flag for a register is not 1 (since the second parameter in */
         /* the ShowRegisterValue call is FALSE). This is really not an */
         /* error. The requested register should just be ignored.       */
         if (((ret = ShowRegisterValue(i,FALSE)) != GOOD) &&
            (ret != ER_INVALID_ARG)) return(ret);
      }
      return(GOOD);
   }

   /*
   *** Parsing Algorithm:
   *** while (number of processed arg < number of arg + 1)
   ***   if (pushbacked is true) then arg = pushbacked arg
   ***   else arg is a new token
   ***   set writeData flag = false
   ***   if (arg is a register id) then get its name
   ***   else error invalid syntax
   ***   if ()
   ***   look ahead for the next arg. -> increment number of process argument
   ***      if (look-ahead is a reg_id) then set pushbacked = true
   ***      else look-ahead is a data assignment
   ***         set writeData flag = true
   ***         if (data is valid) then set the previous reg_id with the data
   ***         else error invalid data format
   ***   if (writeData = false) then
   ***      get data of the reg_id to display
   ***      if (pushbacked is true) then
   ***         continue (number of processed arg already counted)
   ***   else
   ***      increment the number of processed arg.
   *** end of loop.
   ***
    */

   /* Do the command one by one - "register <reg_name list><cr>"  */
   i = 1;
   while ( i < argc ) {
      if (pushBack) {  /* we've already got it */
         ptr = lpnext;
         pushBack = FALSE;
      }
      else
         ptr = &(cmdString[(int)argv[i]]);

      isWriteData = FALSE; /* display one register */
      /* isWriteData is set TRUE if we want to modify register,
       * else FALSE for display only
       */

      /* look thru all register to see if this matches a register name */
      if (CpuFindRegisterId((U8 *FAR)ptr, &regId) == GOOD)
         lstrcpy((LPSTR)regName, (LPSTR)ptr);
      else
         return (ER_INVALID_ARG);

      /* peek at next argument to see if it's a data or register id */
      if (i < argc-1) {
         lstrcpy((S8 FAR *)lpnext, (S8 FAR *)&cmdString[(int)argv[++i]]);

         /* If the next argument is a register then display the previous one */
         if (CpuFindRegisterId((U8 FAR *)lpnext, &tempId) == GOOD)
            pushBack = TRUE;
         else {  /* Found register data assignment */
            isWriteData = TRUE;
		    if ((ret = CpuConvTextToValue(lpnext, regId)) != GOOD) return(ret);
         }
      } /* if argc-1 */

      if (!isWriteData) {
         /* just display previous reg, push this one back */
         if ((ret = ShowRegisterValue(regId,TRUE)) != GOOD) return(ret);
         if (pushBack)
            continue;  /* don't increment i - look-ahead already did */
      }
      i++;   /* next argument */
   } /* end of while */

   return(GOOD);

}

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

   /* Don't do anything if the cpu.cfg file was not found. */
   if (cpuFatalError != 0)
      return(ER_BADGET);

   if(argc==1) return(CpuResetCPU());
   if((argc==2) && (!strcmpi(&(cmdString[(int)argv[1]]), "cpuonly")))
      return(CpuResetCPUOnly());
   return(ER_CLI_SYNTAX);
}

/***************************************************************************
**
**  CpuCliFindRegName
**
*****************************************************************************/
#pragma argsused
RETCODE EXPORT CpuCliFindRegName(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE ret;
   S8 *endPtr, lpId[MAX_NAME];
   REG_ID regId;
   S8 regName[MAX_NAME];
   S8 regValue[MAX_NAME];
   U16 sortIndex;
   U16 type;

   /* Don't do anything if the cpu.cfg file was not found. */
   if (cpuFatalError != 0)
      return(ER_BADGET);

   if (argc != 2) return(ER_CLI_SYNTAX);
   lstrcpy((LPSTR)lpId, (LPSTR) &(cmdString[(int)argv[1]]));
   regId = (REG_ID) strtoul(lpId, &endPtr, 0);
   if (*endPtr != '\0')  /* Syntax error */
      return(ER_INVALID_ARG);
   if ((ret = CpuGetRegisterInfo(regId, regName, &sortIndex, &type, NULL,
              NULL, NULL))
        != GOOD) return(ret);
   /* Put it in the buffer and return */
   if ((ret = CpuGetRegisterValueText(regId, type, regValue))
        != GOOD) return(ret);
   sprintf(strBuf, "Id: %02d = register %6s; Sort %d; Type %d; Value = %s",
      regId, regName, sortIndex, type, regValue);
   SendMessageToCli((LPSTR) strBuf) ;
   return(ret) ;
}

/****************************************************************************
**
**  SendMessageToCli.
**
*****************************************************************************/
RETCODE SendMessageToCli(LPSTR msgPtr) {
   GLOBALHANDLE msgBufHandle;
   CSERVER_RESULTS FAR  *msgBufPtr;
   U16 msgTextSize;
   LOOP_VAR loop;

   msgTextSize = lstrlen(msgPtr);
   msgBufHandle = GlobalAlloc(GMEM_MOVEABLE, (sizeof(CSERVER_RESULTS) +
     msgTextSize + 2));
   if (msgBufHandle == (HANDLE)NULL) {
	  return(ER_OUT_OF_MEMORY);
   }
   else if((msgBufPtr=(CSERVER_RESULTS FAR *)GlobalLock(msgBufHandle)) == NULL) {
	  return(ER_WINDOWS_MEMLOCK);
   }
   /* Initialize message buffer */
   msgBufPtr->target               = 0;
   msgBufPtr->variantCode          = CLI_SERVER_RESULTS;
   msgBufPtr->resultTextLength     = msgTextSize; /* message string length */
   for (loop = 0; loop < msgTextSize; loop++ ) {
      msgBufPtr->messageText[loop]  =  *msgPtr++;
   }
   msgBufPtr->messageText[loop]  =  '\0' ;

   /* output message to memBufPtr->messageText[] */
   /*
   *** CLI Server will consume the handle when it done.
    */
   SendMessage(cliServerHandle, CLI_SERVER_RESULTS, msgBufHandle,
         (DWORD)CLI_SERVER_RESULTS );
   return (GOOD);
}
						/****************************
						 *                          *
						 *       LOCAL ROUTINES     *
						 *                          *
						 ****************************/

/* does anyone still use this routine?? really? */
/****************************************************************************
**
**  CheckCliToken
**
**  Status:  PRELIMINARY
**
**  Description:
**     Find cli token from input buffer
**
**  Parameters:
**     input:
**        *cmdBuf:  the input buffer.
**     output:
**        *token_no:  the token find at this line.
**
*****************************************************************************/
RETCODE PRIVATE CheckCliToken(S8 *cmdBuf, U16  *clitoken_no) {
   S16       i, j ;
   STATIC S8 *clitoken_tbl[] = {"enable", "disable", "all",
                                   "*"} ; /* end mark is '*' */

   i = *clitoken_no = 0 ;
   j = strlen(cmdBuf) ;
   do {
      if((j == strlen(clitoken_tbl[i])) && (!strcmpi(clitoken_tbl[i],cmdBuf)))
         *clitoken_no = i+1 ; /* from 1 to 3 */
   } while ((clitoken_tbl[++i][0] != '*') && !(*clitoken_no)) ; /* 1 to 3 */

   if (*clitoken_no == 0)
      return(ER_KEY_TOKEN_NOT_FOUND) ; /* no match for keyword token */
   else
      return(GOOD) ;
}

RETCODE PRIVATE ShowRegisterValue(U16 regId, BOOLEAN showMultiplexed) {
   RETCODE err;
   S8 valueText[32];
   U16 type;
   U16 visible;

   if ((err = CpuGetRegisterInfo(regId,NULL,NULL,&type,NULL,NULL,&visible)) != GOOD)
       return(err);

   /*              Modified by Dennis Lamb, June 23, 1994.                */
   /* Modified this code to check for two things. One, if the register is */
   /* visible in the CPU window, then display it. Two, if the register is */
   /* not visible in the CPU window, but is a multiplexed register (AX,AH,*/
   /* AL are multiplexed with EAX) and the showMultiplexed variable is set*/
   /* to TRUE, then display it. The first case is when the user types the */
   /* "reg" command in the shell. The second case is when the user types  */
   /* the "reg AX" command for example.                                   */ 
   if ((visible == 1) || ((visible == 2) && (showMultiplexed == TRUE))) {
      strcpy(valueText,"0x");
      if ((err = CpuGetRegisterValueText(regId, 0, &valueText[2])) != GOOD)
         return(err);
      sprintf(strBuf, "%8s = %10s",regTable[regId].regName, valueText);
      SendMessageToCli((LPSTR) strBuf);
      if (type != 0) {
         if ((err = CpuGetRegisterValueText(regId, type, valueText)) != GOOD)
            return(err);
         sprintf(strBuf, "         = %s",valueText);
         SendMessageToCli((LPSTR) strBuf);
     }
   }
   else return ER_INVALID_ARG;
   return(GOOD);
}

/****************************************************************************
**
**  displaySignalCmdResult
**
**  Status:  PRELIMINARY
**
**  Description:
**     Generate command result string message according to the cmdErr input.
**
**  Parameters:
**     input:
**        sigId     Signal id.
**        sigValue  Current state of signal.
**        sigName   Name string of signal
**        cmdErr    Command result error code to generate message.
**     output:
**        none.
**
*****************************************************************************/
RETCODE PRIVATE displaySignalCmdResult(REG_ID sigId, U8 sigValue,
                                       S8 *sigName, RETCODE cmdErr) {
    U8 statusId;
    S8 signalName[MAX_NAME];
    S8 *strPtr1, *strPtr2;

    switch(cmdErr) {
       case GOOD :
          /* Current  signal state is enable,
             set its correspond status string */
          if (!sigValue) statusId = 0;
          else statusId = 1;

          /* clobber the first & character found.  these are put in
             to allow windows to properly underline characters */
          strcpy(signalName, signalTable[sigId].signalName);
          strPtr2 = strPtr1 = strchr(signalName, '&');
          if (strPtr1)
             strcpy(strPtr1, ++strPtr2);

          /* Generate message to display */
          sprintf(strBuf, "%s  %s",
                 signalName, status[statusId]);
          break;
       case ER_SIGNAL_NOT_FOUND :
          sprintf(strBuf, "Signal name %s not found!", sigName) ;
          break;
       default:   /* an error occurred, so report it */
          sprintf(strBuf, "Get %s signal error = %8.8lX",
                       signalTable[sigId].signalName, cmdErr);
    }
    /* Send message to CLI server */
    return(SendMessageToCli((LPSTR) strBuf));
}

/****************************************************************************
**
**  FindSignalId
**
**  Status:  TESTED
**
**  Description:
**     Find the id of a signal name.
**
**  Parameters:
**     input:
**        sigNameStr    string name of signal.
**
**     output:
**        sigId         id of signal.
**
*****************************************************************************/
RETCODE PRIVATE FindSignalId(S8 *sigNameStr, REG_ID *sigId) {
   U16 i;
   S8 signalName[MAX_NAME];
   S8 *strPtr1, *strPtr2;
   /* Compare sigNameStr against the signalTable */
   for (i = 0; i<nSignals; i++) {
      /* strip the first & out of the signal name.  Windows uses the
         & to do underlining */
      strcpy(signalName, signalTable[i].signalName);
      strPtr1 = strPtr2 = strchr(signalName, '&');
      if (strPtr1)
         strcpy(strPtr1, ++strPtr2);
      
      if (!strcmpi(sigNameStr, signalName)) {
         *sigId = i;
         return(GOOD);
      }
   }
   return(ER_SIGNAL_NOT_FOUND);
}

RETCODE EXPORT CpuCliConfig(LPSTR cmdString, U32 argc, U32 argv[]) {
   RETCODE err;
   if (argc < 2) return(ER_CLI_SYNTAX);
   if (stricmp(&cmdString[(U16)argv[1]],"ignorehlda")==0) {
      char buf[32];
      BOOLEAN value;
      if (argc >= 3) {
         if (stricmp(&cmdString[(U16)argv[2]],"off")==0) {
            if ((err = CpuSetIgnoreHLDA(FALSE)) != GOOD) return(err);
         } else if (stricmp(&cmdString[(U16)argv[2]],"on")==0) {
            if ((err = CpuSetIgnoreHLDA(TRUE)) != GOOD) return(err);
         } else return(ER_CLI_SYNTAX);
      }
      if ((err = CpuGetIgnoreHLDA(&value)) != GOOD) return(err);
      sprintf(buf,"ignoreHLDA is %s",(value)?"on":"off");
      return(SendMessageToCli((LPSTR)buf));
   }
   return(ER_CLI_SYNTAX);
}

//**Hera 12/09/96**/
RETCODE EXPORT CliPause(LPSTR cmdString, U32 argc, U32 argv[])
{
  S8 *ptr;

  if(argc == 1)
     MessageBox(NULL,"","Pause",MB_OK);
  else
  {
     ptr = &(cmdString[(int)argv[1]]);
     MessageBox(NULL,ptr,"Pause",MB_OK);
   }
  return 0;
}

/******************
* End of CPUCLI.C *
*******************/
