📄 shell.c
字号:
* add2buf ************************************************************************/static voidadd2buf( 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, ¤t_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 voidcommand_loop( t_shell_line_buf *buf ){ char line[SHELL_MAX_COMMAND_LEN + 1]; UINT32 current_from_buf; bool execute; 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 { execute = TRUE; if( strcmp( line, "." ) == 0 ) { shell_dot = TRUE; current_from_buf = buf->free; if(!get_previous( buf, ¤t_from_buf, line )) { execute = FALSE; printf( "\n" ); } } else { shell_dot = FALSE; /* Add line to stack (only "single" lines) */ if( !start && (strlen( line ) <= max_line_len) ) add2buf( buf, line ); } if( execute ) { /* 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 voidremove_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 voidseparate( 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 boolget_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 UINT32expand_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 ) { case '\0' : rc = SHELL_ERROR_PARSE_MISSING_QUOTE; break; case '$' : case '\\': case '\'': case '"' : case ' ' : default : expanded[len++] = *ch; state = STATE_EXP_QUOTE_SINGLE; break; } break; case STATE_EXP_QUOTE_DOUBLE_SPECIAL : switch( *ch ) { case '\0' : rc = SHELL_ERROR_PARSE_MISSING_QUOTE; break; case '$' : case '\\': case '\'': case '"' : case ' ' : default : expanded[len++] = *ch; state = STATE_EXP_QUOTE_DOUBLE; break; } break; case STATE_EXP_QUOTE_DOUBLE_ENV : switch( *ch ) { case '\0' : rc = SHELL_ERROR_PARSE_MISSING_QUOTE; break; case '$' : rc = add_env( env_name, env_len, expanded, &len ); env_len = 0; state = STATE_EXP_QUOTE_DOUBLE_ENV; break; case '\\' : rc = add_env( env_name, env_len, expanded, &len ); expanded[len++] = *ch; state = STATE_EXP_QUOTE_DOUBLE_SPECIAL; break; case '"' : rc = add_env( env_name, env_len, expanded, &len ); expanded[len++] = *ch; state = STATE_EXP_NORMAL; break; case '\'' : case ' ' : case ';' : rc = add_env( env_name, env_len, expanded, &len ); expanded[len++] = *ch; state = STATE_EXP_QUOTE_DOUBLE; break; default : env_name[env_len++] = *ch; state = STATE_EXP_QUOTE_DOUBLE_ENV; break; } break; default : /* Should not happen */ rc = SHELL_ERROR_STRUCTURE; break; } if( (len == SHELL_MAX_COMMAND_LEN + 1) && (state != STATE_EXP_DONE) ) rc = SHELL_ERROR_PARSE_LONG_LINE; if( env_len == SHELL_MAX_ENV_LEN + 1 ) rc = SHELL_ERROR_PARSE_LONG_ENV; ch++; } while( (rc == OK) && (state != STATE_EXP_DONE) ); if( rc != OK ) return rc; else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -