⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shell.c

📁 MIPS下的boottloader yamon 的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/************************************************************************
*                          get_next
************************************************************************/
static bool
get_next( 
		 t_shell_line_buf *buf, 
		 UINT32	     *current_from_buf, 
		 char	     *line )
{
    if( buf->first == BUFFER_NU )
        return FALSE;
	
    if( *current_from_buf == buf->free )
        return FALSE;
	
    /* Move forward */
    do
    {
        INCWRAP(*current_from_buf, BUFFERSIZE);
    }
    while( buf->data[*current_from_buf] != '\0' );
    INCWRAP(*current_from_buf, BUFFERSIZE);
	
    if( *current_from_buf == buf->free )
    {
        line[0] = '\0';
    }
    else
    {   
        /* Do the copy */
        copybuf( line, buf->data, *current_from_buf, BUFFERSIZE );
    }
	
    return TRUE;
}


/************************************************************************
*                          copy_buf
************************************************************************/
static void 
copybuf(
		char   *dst,
		char   *src,
		UINT32 pos,
		UINT32 bufsize )
{
    do
    {
        *dst = src[pos];
        INCWRAP(pos, bufsize );
    }
    while( *(dst++) != '\0' );
}


/************************************************************************
*                          decode_option
************************************************************************/
static bool
decode_option(
			  t_shell_option *decode,
			  UINT32	   *type,
			  char           *token )
{
    if( *token == '-' )
    {
        decode->option = &token[1];
		*type	       = SHELL_TOKEN_OPTION;
		return TRUE;
    }
    else
		return FALSE;    
}


/************************************************************************
*                          decode_ip
************************************************************************/
static bool
decode_ip(
		  t_shell_option *decode,
		  UINT32	   *type,
		  char           *token )
{
    if( env_ip_s2num( token, (void *)&decode->ip, sizeof(decode->ip)) )
    {
		*type      = SHELL_TOKEN_IP;
		return TRUE;
    }
    else
        return FALSE;
}


/************************************************************************
*                          insert_char
************************************************************************/
static void
insert_char( 
			char   *line, 
			UINT32 *cursor,
			UINT32 *eol,
			char   ch )
{
    UINT32 i;
	
    /* Move characters after cursor and insert new character */
    for( i = *eol; i > *cursor; i-- )
        line[i] = line[i-1];
    line[i] = ch;
	
    /* Increase line length and add new termination */
    (*eol)++;
    line[*eol] = '\0';    
	
    /* Print line from cursor  */
    printf( &line[*cursor] );
	
    /* Increase cursor */
    (*cursor)++;
	
    /* Move cursor back */
    moveleft(*eol - *cursor);
}


/************************************************************************
*                          delete_char
************************************************************************/
static void
delete_char( 
			char   *line, 
			UINT32 *cursor, 
			UINT32 *eol )
{
    UINT32 i;
	
    /* Move characters after cursor and insert new character */
    for( i = *cursor; i < *eol; i++ )
        line[i] = line[i+1];
	
    /* Print line from cursor, add space */
    printf( "%s ", &line[*cursor] );
	
    /* Move cursor back */
    moveleft( *eol - *cursor );
	
    /* Decrease line length */
    (*eol)--;
}


/************************************************************************
*                          delete_from_cursor
************************************************************************/
static void
delete_from_cursor(
				   UINT32 cursor, 
				   UINT32 *eol)
{
    char   spaces[SHELL_MAX_LINE_LEN + 1];
    UINT32 i;
	
    /* Replace characters to the right of cursor with spaces */    
    for(i=0; i < (*eol - cursor); i++)
        spaces[i] = ' ';
    spaces[i] = '\0';
    printf( spaces );
	
    /* Move cursor back */
    moveleft( *eol - cursor );
    
    /* Move eol to cursor location */
    *eol = cursor;
}


/************************************************************************
*                          delete_line
************************************************************************/
static void
delete_line(
			UINT32 *cursor,
			UINT32 *eol )
{
    moveleft( *cursor );
    *cursor = 0;
    delete_from_cursor(*cursor, eol );
}


/************************************************************************
*                          add2buf
************************************************************************/
static void
add2buf( 
		t_shell_line_buf *buf,
		char	     *line )
{
    UINT32 current_from_buf;
    char   previous_line[SHELL_MAX_COMMAND_LEN + 1];
    UINT32 len, i;
	
    current_from_buf = buf->free;
	
    /* Check for identical command on stack */
    if( get_previous( buf, &current_from_buf, previous_line ) &&
        strcmp( line, previous_line ) == 0 )
    {
        return;
    }
	
    /* Copy line to buffer */
    for( i=0, len = strlen(line); i<=len; i++ )
    {
	/* Before inserting character, we check if we are about
	* to overwrite an old line.
		*/
        if( buf->free == buf->first )
        {
		/* We are about to overwrite an old line,
		* so obsolete the old line
			*/
            while(buf->data[buf->first] != '\0')
            {
                INCWRAP(buf->first, BUFFERSIZE);
            }
            INCWRAP(buf->first, BUFFERSIZE);
        }
		
        /* Now we are ready to insert the character */
        buf->data[buf->free] = line[i];
        INCWRAP(buf->free, BUFFERSIZE);
		
        /* After moving the free pointer forward, we need to check
		* again if 'free' has caught up with 'first'.
		*/
        if( buf->free == buf->first )
        {
            /* free did catch up with first, so obsolete the old line. */
            while(buf->data[buf->first] != '\0')
            {
                INCWRAP(buf->first, BUFFERSIZE);
            }
            INCWRAP(buf->first, BUFFERSIZE);
        }
    }
	
    /* Buffer is no longer unused */
    if( buf->first == BUFFER_NU ) 
        buf->first = 0;
}


/************************************************************************
*                          command_loop
************************************************************************/
static void
command_loop(
			 t_shell_line_buf *buf )
{
    char line[SHELL_MAX_COMMAND_LEN + 1];
	
    while( TRUE )
    {
//        print_prompt( PROMPT_TARGET_DISPLAY, PROMPT_TEXT_ENV );
		
		if( !start )
            print_prompt( PROMPT_TARGET_TERMINAL, PROMPT_TEXT_ENV );
		
		if( !shell_get_line( line, SHELL_MAX_COMMAND_LEN, TRUE, TRUE, buf ) )
		{
			printf( "\n" );
		}
		else
		{
			/* Remove excess spaces */
			remove_space( line );
			
			if( strlen(line) == 0 )
				printf( "\n" );
			else
			{
				/* Add line to stack (only "single" lines) */
				if( !start && (strlen( line ) <= max_line_len) )
					add2buf( buf, line );
				
					/*  Recursively split line in ";" separated commands and expand
					*  environment variables.
					*  Execute command(s).
				*/
				newline_after_prompt = FALSE;
				execute_line( line, TRUE );
            }
        }
		
		start = NULL;
    }
}


/************************************************************************
*                          remove_space
************************************************************************/
static void
remove_space( 
			 char *line )
{
    char   clean[SHELL_MAX_COMMAND_LEN + 1];
    UINT32 len = 0;
    bool   skip;
    bool   found_char   = FALSE;
    char   *start       = line;
    bool   quote_double = FALSE;
    bool   quote_single = FALSE;
    bool   special	= FALSE;
	
    while( line[0] != '\0' )
    {
        skip = FALSE;
		
        /*  Remove excess whitespace, unless within single or
		*  double quotes.
		*/
        if( line[0] == ' ' )
		{
			if( !found_char        ||  /* Leading spaces  */
				(line[1] == ' ')   ||  /* Multiple spaces */
				(line[1] == '\0') )    /* Trailing spaces */
            {
				/* Keep spaces within quotes */
				if( !quote_double && !quote_single )
				{
					skip = TRUE;
				}
			}
        }
		else if( line[0] == '\\' )
		{
			special = !special;
		}
		else if( (line[0] == '\'') && !special )
		{
			if( !quote_double )
			{
				quote_single = !quote_single;
			}
		}
		else if( (line[0] == '"') && !special )
		{
			if( !quote_single )
			{
				quote_double = !quote_double;
			}
		}
		else
			special = FALSE;
		
		if( !skip )
		{
			clean[len++] = line[0];
			found_char   = TRUE;
        }
		
		line++;
    }
	
    clean[len] = '\0';
    strcpy( start, clean );
}


/************************************************************************
*                          separate
************************************************************************/
static void
separate(
		 char   *line,
		 UINT32 *subcommand_count )
{
    bool   quote_double = FALSE;
    bool   quote_single = FALSE;
    bool   special	= FALSE;
	
    *subcommand_count = 1;
	
    /*  Find ';' not within single or double quotes and substitute
	*  with '\0'
	*/
	
    while( line[0] != '\0' )
    {
        if( (*line == ';') && !quote_double && !quote_single )
		{
            *line = '\0';
			(*subcommand_count)++;
        }
		else if( *line == '\\' )
		{
			special = !special;
		}
		else if( (*line == '\'') && !special )
		{
			if( !quote_double )
			{
				quote_single = !quote_single;
			}
		}
		else if( (*line == '"') && !special )
		{
			if( !quote_single )
			{
				quote_double = !quote_double;
			}
		}
		else
			special = FALSE;
		
		line++;
    }
}


/************************************************************************
*                          get_repeat
************************************************************************/
static bool
get_repeat(
		   char   *line,
		   UINT32 *loop_count )
{
    t_shell_option decode;
    UINT32	   len;
	
    if( *line == '+' )
    {
        line++;
		
		/* Remove trailing spaces */
		len = strlen( line );
		
		while( len && line[len-1] == ' ' )
		{
			line[len-1] = '\0';
			len--;
		}
		
		/* Decode number */
        if( shell_decode_number(
			&decode, 
			NULL,
			line ) )
		{
			*loop_count = decode.number;
			return TRUE;
		}
    }
	
    return FALSE;
}


/************************************************************************
*                          expand_line
************************************************************************/
static UINT32
expand_line( 
			char *line )
{
    char            env_name[SHELL_MAX_ENV_LEN + 2];
    char            expanded[SHELL_MAX_COMMAND_LEN + 1];
    UINT32          len, env_len;
    t_expand_state  state;
    char	    *ch;
    UINT32	    rc;
		  
    state   = STATE_EXP_NORMAL;
    ch      = line;
    len	    = 0;
    env_len = 0;
    rc	    = OK;
	
    do
    {
        switch( state )
		{
		case STATE_EXP_NORMAL :
			switch( *ch )
			{
			case '\0' :
				expanded[len++] = *ch;
				state = STATE_EXP_DONE;
				break;
			case '$'  :
				env_len = 0;
				state = STATE_EXP_ENV;
				break;
			case '\\' :
				expanded[len++] = *ch;
				state = STATE_EXP_SPECIAL;
				break;
			case '\'' :
				expanded[len++] = *ch;
				state = STATE_EXP_QUOTE_SINGLE;
				break;
			case '"' :
				expanded[len++] = *ch;
				state = STATE_EXP_QUOTE_DOUBLE;
				break;
			case ' '  :
			default   :
				expanded[len++] = *ch;
				state = STATE_EXP_NORMAL;
				break;
			}
			break;
			case STATE_EXP_ENV :
				switch( *ch )
				{
				case '\0' :
					rc = add_env( env_name, env_len, expanded, &len );
					expanded[len++] = *ch;
					state = STATE_EXP_DONE;
					break;
				case '$'  :
					rc = add_env( env_name, env_len, expanded, &len );
					env_len = 0;
					state = STATE_EXP_ENV;
					break;
				case '\\' :
					rc = add_env( env_name, env_len, expanded, &len );
					expanded[len++] = *ch;
					state = STATE_EXP_SPECIAL;
					break;
				case '\'' :
					rc = add_env( env_name, env_len, expanded, &len );
					expanded[len++] = *ch;		
					state = STATE_EXP_QUOTE_SINGLE;
					break;
				case '"' :
					rc = add_env( env_name, env_len, expanded, &len );
					expanded[len++] = *ch;		
					state = STATE_EXP_QUOTE_DOUBLE;
					break;
				case ' ' :
					rc = add_env( env_name, env_len, expanded, &len );
					expanded[len++] = *ch;		
					state = STATE_EXP_NORMAL;
					break;
				default   :
					env_name[env_len++] = *ch;
					state = STATE_EXP_ENV;
					break;
				}
				break;
				case STATE_EXP_SPECIAL :
					switch( *ch )
					{
					case '\0' :
						expanded[len++] = *ch;
						state = STATE_EXP_DONE;
						break;
					case '$'  :
					case '\\' :
					case '\'' :
					case '"'  :
					case ' '  :
					default   :
						expanded[len++] = *ch;
						state = STATE_EXP_NORMAL;
						break;
					}
					break;
					case STATE_EXP_QUOTE_SINGLE :
						switch( *ch )
						{
						case '\0' :
							rc = SHELL_ERROR_PARSE_MISSING_QUOTE;
							break;
						case '\\' :
							expanded[len++] = *ch;
							state = STATE_EXP_QUOTE_SINGLE_SPECIAL;
							break;
						case '\'' :
							expanded[len++] = *ch;
							state = STATE_EXP_NORMAL;
							break;
						case '"' : 
						case '$' :
						case ' ' :
						default  :
							expanded[len++] = *ch;
							state = STATE_EXP_QUOTE_SINGLE;
							break;
						}
						break;
						case STATE_EXP_QUOTE_DOUBLE :
							switch( *ch )
							{
							case '\0' :
								rc = SHELL_ERROR_PARSE_MISSING_QUOTE;
								break;
							case '$'  :
								env_len = 0;
								state = STATE_EXP_QUOTE_DOUBLE_ENV;
								break;
							case '\\' :
								expanded[len++] = *ch;
								state = STATE_EXP_QUOTE_DOUBLE_SPECIAL;
								break;
							case '"' :
								expanded[len++] = *ch;
								state = STATE_EXP_NORMAL;
								break;
							case '\'' :
							case ' '  :
							default   :
								expanded[len++] = *ch;
								state = STATE_EXP_QUOTE_DOUBLE;
								break;
							}
							break;
							case STATE_EXP_QUOTE_SINGLE_SPECIAL :
								switch( *ch )
								{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -