📄 shell.c
字号:
/*********************************************************************** * * shell.c * * Implementation of command shell with command line history and * command line editing. VT100 codes used. * * ###################################################################### * * mips_start_of_legal_notice * * Copyright (c) 2004 MIPS Technologies, Inc. All rights reserved. * * * Unpublished rights (if any) reserved under the copyright laws of the * United States of America and other countries. * * This code is proprietary to MIPS Technologies, Inc. ("MIPS * Technologies"). Any copying, reproducing, modifying or use of this code * (in whole or in part) that is not expressly permitted in writing by MIPS * Technologies or an authorized third party is strictly prohibited. At a * minimum, this code is protected under unfair competition and copyright * laws. Violations thereof may result in criminal penalties and fines. * * MIPS Technologies reserves the right to change this code to improve * function, design or otherwise. MIPS Technologies does not assume any * liability arising out of the application or use of this code, or of any * error or omission in such code. Any warranties, whether express, * statutory, implied or otherwise, including but not limited to the implied * warranties of merchantability or fitness for a particular purpose, are * excluded. Except as expressly provided in any written license agreement * from MIPS Technologies or an authorized third party, the furnishing of * this code does not give recipient any license to any intellectual * property rights, including any patent rights, that cover this code. * * This code shall not be exported, reexported, transferred, or released, * directly or indirectly, in violation of the law of any country or * international law, regulation, treaty, Executive Order, statute, * amendments or supplements thereto. Should a conflict arise regarding the * export, reexport, transfer, or release of this code, the laws of the * United States of America shall be the governing law. * * This code constitutes one or more of the following: commercial computer * software, commercial computer software documentation or other commercial * items. If the user of this code, 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 code, 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 code 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 code from MIPS Technologies or an authorized * third party. * * * * * mips_end_of_legal_notice * * ************************************************************************//************************************************************************ * 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>#include <excep_api.h>/************************************************************************ * Definitions ************************************************************************//* Maximum number of parsed tokens in a command */#define MAX_ARGC 15typedef 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;bool shell_dot = FALSE;/************************************************************************ * Static variables ************************************************************************/static t_gdb_regs shell_restart_context;static bool display_freeze;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 100static 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, * or unless environment variable "startdelay" exists with value 0. */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 400static char shell_error_msg[MAX_SHELL_ERR_MSG];/* Failing command */static t_cmd *failing_cmd;/************************************************************************ * Static function prototypes ************************************************************************/static voidreceive( char *ch );static voidmoveleft( UINT32 count );static voidmoveright( char *line, UINT32 cursor, UINT32 count );static voidprint_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 boolget_previous( t_shell_line_buf *buf, UINT32 *current_from_buf, char *line );static boolget_next( t_shell_line_buf *buf, UINT32 *current_from_buf, char *line );static void copybuf( char *dst, char *src, UINT32 pos, UINT32 bufsize );static booldecode_option( t_shell_option *decode, UINT32 *type, char *token );static booldecode_ip( t_shell_option *decode, UINT32 *type, char *token );static voidcommand_loop( t_shell_line_buf *buf );static voidinsert_char( char *line, UINT32 *cursor, UINT32 *eol, char ch );static voiddelete_char( char *line, UINT32 *cursor, UINT32 *eol );static voiddelete_from_cursor( UINT32 cursor, UINT32 *eol);static voiddelete_line( UINT32 *cursor, UINT32 *eol );static voidadd2buf( t_shell_line_buf *buf, char *line );static UINT32execute_line( char *line, bool first );static UINT32execute_command( t_cmd **cmd );static voidremove_space( char *line );static voidseparate( char *line, UINT32 *subcommand_count );static boolget_repeat( char *line, UINT32 *loop_count );static UINT32expand_line( char *line );static UINT32add_env( char *env_name, UINT32 env_len, char *expanded, UINT32 *len_expanded );static UINT32tokenize( char *line );static INT32 error_lookup( t_sys_error_string *param );static voidadd2error( 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; UINT32 i; UINT32 default_switch; bool ctrl_c; UINT32 delay; char *startdelay; t_sys_error_lookup_registration registration; UINT32 old_ie; /* 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" ); /* 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"); } /* Initialise buffer */ buf.first = BUFFER_NU; buf.free = 0; /* Check for "start" command" */ if( env_get( "start", &start, NULL, 0 ) && (*start != '\0') ) { if (env_get("startdelay",&startdelay,NULL,0) && (*startdelay != '\0')) { delay = (UINT32)strtoul( startdelay, &startdelay, 10 ); if( *startdelay != '\0' || delay > 0x100000 ) { delay = 2; } if (delay == 0) start = NULL; } else delay = 2; } else start = NULL; if (start) { printf( "Environment variable 'start' exists. After %d seconds\n" "it will be interpreted as a YAMON command and executed.\n" "Press Ctrl-C to bypass this.\n", delay ); for (delay *= 10; delay--;) { ctrl_c = GETCHAR_CTRLC( DEFAULT_PORT ); if( ctrl_c ) { start = NULL; printf( "\n" ); break; } else sys_wait_ms( 100 ); } } /**** Save YAMON shell context ****/ /* Store exception handler settings */ EXCEP_store_handlers( EXCEP_HANDLERS_SHELL ); old_ie = sys_disable_int(); /* Store context */ EXCEP_save_context(&shell_restart_context); /* This is where also shell_reenter() returns to ! */ /* Flush context to memory. Needed in case we reenter * shell in uncached mode (using shell_reenter()) * after a cache error exception. */ sys_dcache_flush_all(); if(old_ie) sys_enable_int(); command_loop( &buf );}/************************************************************************ * * shell_reenter * Description : * ------------- * Reenters shell() after exception register dump. * Any remaining counting and/or sub commands are aborted. * * Return values : * --------------- * None, function never returns * ************************************************************************/voidshell_reenter( bool go_uncached ){ if ( (shell_restart_context.cp0_status & M_StatusEXL) == 0) { /* shell has not been started yet, so loop forever */ while(1); } /* abort start command line should it still be active */ start = NULL; /* Freeze display until operator intervention occurs */ display_freeze = TRUE; /* After cacheerr exception shell is forced to run uncached */ if ( go_uncached ) { shell_restart_context.cp0_config &= ~M_ConfigK0; shell_restart_context.cp0_config |= K_CacheAttrU << S_ConfigK0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -