📄 shell.c
字号:
/***********************************************************************
*
* shell.c
*
* Implementation of command shell with command line history and
* command line editing. VT100 codes used.
*
*
* ######################################################################
*
* Copyright (c) 1999-2000 MIPS Technologies, Inc. All rights reserved.
*
* Unpublished rights reserved under the Copyright Laws of the United States of
* America.
*
* This document contains information that is proprietary to MIPS Technologies,
* Inc. ("MIPS Technologies"). Any copying, modifying or use of this information
* (in whole or in part) which is not expressly permitted in writing by MIPS
* Technologies or a contractually-authorized third party is strictly
* prohibited. At a minimum, this information is protected under unfair
* competition laws and the expression of the information contained herein is
* protected under federal copyright laws. Violations thereof may result in
* criminal penalties and fines.
* MIPS Technologies or any contractually-authorized third party reserves the
* right to change the information contained in this document to improve
* function, design or otherwise. MIPS Technologies does not assume any
* liability arising out of the application or use of this information. Any
* license under patent rights or any other intellectual property rights owned
* by MIPS Technologies or third parties shall be conveyed by MIPS Technologies
* or any contractually-authorized third party in a separate license agreement
* between the parties.
* The information contained in this document constitutes one or more of the
* following: commercial computer software, commercial computer software
* documentation or other commercial items. If the user of this information, or
* any related documentation of any kind, including related technical data or
* manuals, is an agency, department, or other entity of the United States
* government ("Government"), the use, duplication, reproduction, release,
* modification, disclosure, or transfer of this information, or any related
* documentation of any kind, is restricted in accordance with Federal
* Acquisition Regulation 12.212 for civilian agencies and Defense Federal
* Acquisition Regulation Supplement 227.7202 for military agencies. The use of
* this information by the Government is further restricted in accordance with
* the terms of the license agreement(s) and/or applicable contract terms and
* conditions covering this information from MIPS Technologies or any
* contractually-authorized third party.
*
************************************************************************/
/************************************************************************
* Include files
************************************************************************/
#include <shell_api.h>
#include <sysdefs.h>
#include <syserror.h>
#include "shell.h"
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <mips.h>
#include <syscon_api.h>
#include <env_api.h>
#include <sys_api.h>
/************************************************************************
* Definitions
************************************************************************/
/* Maximum number of parsed tokens in a command */
#define MAX_ARGC 15
typedef struct
{
char *name;
UINT32 base;
}
t_sh_prefix;
/* States for state event machine used for receiving characters. */
typedef enum
{
STATE_RCV_START,
STATE_RCV_ESC,
STATE_RCV_CSI,
STATE_RCV_BRACKET,
STATE_RCV_DONE
}
t_rcv_state;
/* States for state event machine used to expand env. variables of
* command line.
*/
typedef enum
{
STATE_EXP_NORMAL,
STATE_EXP_SPECIAL,
STATE_EXP_QUOTE_SINGLE,
STATE_EXP_QUOTE_SINGLE_SPECIAL,
STATE_EXP_QUOTE_DOUBLE,
STATE_EXP_QUOTE_DOUBLE_SPECIAL,
STATE_EXP_QUOTE_DOUBLE_ENV,
STATE_EXP_ENV,
STATE_EXP_DONE
}
t_expand_state;
/* States for state event machine used tokenize command line. */
typedef enum
{
STATE_TOKENIZE_SEARCH,
STATE_TOKENIZE_SPECIAL,
STATE_TOKENIZE_QUOTE_DOUBLE,
STATE_TOKENIZE_QUOTE_SINGLE,
STATE_TOKENIZE_DONE,
STATE_TOKENIZE_WORD,
STATE_TOKENIZE_QUOTE_DOUBLE_SPECIAL,
STATE_TOKENIZE_QUOTE_SINGLE_SPECIAL,
STATE_TOKENIZE_WORD_SPECIAL
}
t_tokenize_state;
/************************************************************************
* Public variables
************************************************************************/
char *shell_msg_ctrl_c = "Press Ctrl-C to break";
char *shell_error_data = NULL;
char *shell_error_hint = NULL;
/************************************************************************
* Static variables
************************************************************************/
static char continue_msg[] = "Press any key "
"(Ctrl-C to break, Enter to singlestep)";
/* Stored parameters to shell() */
static t_cmd **command_list;
static UINT32 command_count;
/* Number prefixes */
static t_sh_prefix sh_prefix[] =
{
{ "0x", 16 },
{ "0X", 16 },
{ "16/", 16 },
{ "10/", 10 },
{ "8/", 8 }
};
#define SHELL_PREFIX_NUMBER_COUNT (sizeof(sh_prefix)/sizeof(t_sh_prefix))
/* Max line length after prompt */
static UINT32 max_line_len;
/* Shell error messages */
static char *(shell_err[]) = SHELL_ERR_MSG;
#define SHELL_ERROR_MSG_COUNT (sizeof(shell_err)/sizeof(char *))
/* Array for error strings */
#define MAX_NUMBER_OF_ERROR_STRINGS 100
static UINT8* err_strings[MAX_NUMBER_OF_ERROR_STRINGS];
/* Line parsing */
static UINT32 argc;
static char *(argv[MAX_ARGC]);
static char arg_buf[MAX_ARGC][SHELL_MAX_TOKEN_LEN+1];
/* Display data */
static UINT32 linenum;
static bool more = FALSE;
static UINT32 indent_prev;
/* String containing value of environment variable "start", which
* is automatically executed after a reset unless cancelled by user.
*/
static char *start;
/* Flag for monitoring whether CTRL-C is pressed during command
* execution.
*/
static bool ctrl_c_flag;
/* Flag for monitoring whether a '\n' has been issued after
* the command prompt.
*/
static bool newline_after_prompt;
/* Error message */
#define MAX_SHELL_ERR_MSG 200
static char shell_error_msg[MAX_SHELL_ERR_MSG];
/* Failing command */
static t_cmd *failing_cmd;
/************************************************************************
* Static function prototypes
************************************************************************/
static void
receive(
char *ch );
static void
moveleft(
UINT32 count );
static void
moveright(
char *line,
UINT32 cursor,
UINT32 count );
static void
print_prompt(
#define PROMPT_TARGET_TERMINAL 0
#define PROMPT_TARGET_DISPLAY 1
UINT32 target,
#define PROMPT_TEXT_ENV 0
#define PROMPT_TEXT_CONT 1
UINT32 text );
static bool
get_previous(
t_shell_line_buf *buf,
UINT32 *current_from_buf,
char *line );
static bool
get_next(
t_shell_line_buf *buf,
UINT32 *current_from_buf,
char *line );
static void
copybuf(
char *dst,
char *src,
UINT32 pos,
UINT32 bufsize );
static bool
decode_option(
t_shell_option *decode,
UINT32 *type,
char *token );
static bool
decode_ip(
t_shell_option *decode,
UINT32 *type,
char *token );
static void
command_loop(
t_shell_line_buf *buf );
static void
insert_char(
char *line,
UINT32 *cursor,
UINT32 *eol,
char ch );
static void
delete_char(
char *line,
UINT32 *cursor,
UINT32 *eol );
static void
delete_from_cursor(
UINT32 cursor,
UINT32 *eol);
static void
delete_line(
UINT32 *cursor,
UINT32 *eol );
static void
add2buf(
t_shell_line_buf *buf,
char *line );
static UINT32
execute_line(
char *line,
bool first );
static UINT32
execute_command(
t_cmd **cmd );
static void
remove_space(
char *line );
static void
separate(
char *line,
UINT32 *subcommand_count );
static bool
get_repeat(
char *line,
UINT32 *loop_count );
static UINT32
expand_line(
char *line );
static UINT32
add_env(
char *env_name,
UINT32 env_len,
char *expanded,
UINT32 *len_expanded );
static UINT32
tokenize(
char *line );
static INT32
error_lookup(
t_sys_error_string *param );
static void
add2error(
char *s );
/************************************************************************
* Implementation : Public functions
************************************************************************/
/************************************************************************
*
* shell
* Description :
* -------------
*
* Implements the shell
*
* Return values :
* ---------------
*
* None, function never returns
*
************************************************************************/
void
shell(
t_cmd **cmd_list, /* Array of pointers to shell commands */
UINT32 cmd_count ) /* Number of shell commands */
{
t_shell_line_buf buf;
t_cmd *cmd;
bool ambivalent;
UINT32 i;
UINT32 default_switch;
bool ctrl_c;
UINT32 rc;
t_sys_error_lookup_registration registration;
/* Store parameters */
command_list = cmd_list;
command_count = cmd_count;
/* register error lookup function */
registration.prefix = SYSERROR_DOMAIN( ERROR_SHELL );
registration.lookup = error_lookup;
SYSCON_write( SYSCON_ERROR_REGISTER_LOOKUP_ID,
®istration,
sizeof( registration ) );
/* Print prompt on display */
print_prompt( PROMPT_TARGET_DISPLAY, PROMPT_TEXT_ENV );
printf( "\n" );
DEBUG( "Shell Init\n" );
/* Init */
for(i=0; i<MAX_ARGC; i++)
argv[i] = arg_buf[i];
/* Display info */
printf( "\n" );
shell_disp_info( "boot" );
#if 0
/* Check default switch */
SYSCON_read( SYSCON_BOARD_USE_DEFAULT_ID,
(void *)&default_switch,
sizeof(UINT32) );
if( default_switch )
{
printf(
"Environment default switch is in the 'on' position. The environment\n"
"has been set to default values. If the switch is not set to 'off',\n"
"the environment will be cleared at every reset.\n"
"\n"
"Please set the switch to the 'off' position or type Ctrl-C to continue.\n" );
do
{
SYSCON_read( SYSCON_BOARD_USE_DEFAULT_ID,
(void *)&default_switch,
sizeof(UINT32) );
ctrl_c = GETCHAR_CTRLC( DEFAULT_PORT );
}
while( default_switch && (!ctrl_c) );
printf("\n");
}
#endif
/* Initialise buffer */
buf.first = BUFFER_NU;
buf.free = 0;
/* Check for "start" command" */
if( env_get( "start", &start, NULL, 0 ) && (*start != '\0') )
{
printf( "Environment variable 'start' exists. After 2 seconds\n"
"it will be interpreted as a YAMON command and executed.\n"
"Press Ctrl-C to bypass this.\n" );
for(i=0;i<20;i++)
{
ctrl_c = GETCHAR_CTRLC( DEFAULT_PORT );
if( ctrl_c )
{
start = NULL;
printf( "\n" );
break;
}
else
sys_wait_ms( 100 );
}
}
else
start = NULL;
command_loop( &buf );
}
/************************************************************************
* shell_command_error
************************************************************************/
void
shell_command_error(
t_cmd *cmd, /* Command definition or NULL */
UINT32 err ) /* Error code */
{
int i;
t_sys_error_string error_string;
failing_cmd = cmd;
/* lookup syserror */
error_string.syserror = err;
error_string.count = MAX_NUMBER_OF_ERROR_STRINGS;
error_string.strings = err_strings;
for (i=0; i<3; i++)
{
error_string.strings[i] = NULL;
}
SYSCON_read( SYSCON_ERROR_LOOKUP_ID,
&error_string,
sizeof( error_string ) );
/* CTRL-C is not an error */
if( err != SHELL_ERROR_CONTROL_C_DETECTED )
printf( "Error : " );
/* Check for user defined error message */
if( error_string.strings[SYSCON_ERRORMSG_IDX] )
{
printf( "%s\n", error_string.strings[SYSCON_ERRORMSG_IDX] );
}
/* Check for user defined diagnose message */
if( error_string.strings[SYSCON_DIAGMSG_IDX] )
{
printf( "Diag : %s\n",
error_string.strings[SYSCON_DIAGMSG_IDX] );
}
/* Check for user defined hint message */
if( error_string.strings[SYSCON_HINTMSG_IDX] )
{
printf( "Hint : %s\n",
error_string.strings[SYSCON_HINTMSG_IDX] );
}
}
/************************************************************************
*
* shell_decode_token
* Description :
* -------------
*
* Decode token
*
* Return values :
* ---------------
*
* TRUE -> OK, FALSE -> Failed (never happens)
*
************************************************************************/
bool
shell_decode_token(
char *token, /* Token to be decoded */
UINT32 *type, /* Type of token */
t_shell_option *decode ) /* Decoded value */
{
if( !decode_option( decode, type, token) )
if( !shell_decode_number( decode, type, token) )
if( !decode_ip( decode, type, token) )
{
/* String */
decode->string = token;
*type = SHELL_TOKEN_STRING;
}
return TRUE;
}
/************************************************************************
* shell_decode_number
************************************************************************/
bool
shell_decode_number(
t_shell_option *decode,
UINT32 *type,
char *token )
{
UINT32 len, base;
UINT32 len_temp;
char *endp;
UINT32 i;
/* Lets see if it is a number */
len = 0; /* In case of no radix prefix */
base = SHELL_RADIX_DEFAULT;
for( i=0; i < SHELL_PREFIX_NUMBER_COUNT; i++ )
{
len_temp = strlen( sh_prefix[i].name );
if( strncmp( token, sh_prefix[i].name, len_temp ) == 0 )
{
base = sh_prefix[i].base;
len = len_temp;
break;
}
}
errno = 0;
decode->number = (UINT32)strtoul( &token[len], &endp, base );
if( (*endp == '\0') && (errno == 0) )
{
if( type )
*type = SHELL_TOKEN_NUMBER;
return TRUE;
}
else
return FALSE;
}
/************************************************************************
*
* shell_lookup_cmd
* Description :
* -------------
*
* Search command line for (possibly partial) match in command array.
* Also to be used for command completion.
*
* Return values :
* ---------------
*
* Pointer to command found, if any (else NULL)
*
************************************************************************/
t_cmd *
shell_lookup_cmd(
char *name, /* Command name */
bool *ambivalent, /* TRUE -> match is not unique */
UINT32 *len, /* Number of valid chars */
t_cmd **cmd_list, /* array of ptr to commands */
UINT32 cmd_count ) /* Number of commands */
{
t_cmd *cmd, *cmd_found;
UINT32 i;
char ch;
cmd_found = NULL;
if(ambivalent)
*ambivalent = FALSE;
/* Hack in order to handle case insensitivity of
* Microsoft SDB commands.
*/
if( strlen( name ) == 1 )
{
ch = *name;
*name = tolower(*name);
}
/* Try to find a match */
for( i=0; i < cmd_count; i++ )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -