diff options
author | scratko <m@scratko.xyz> | 2024-11-23 01:24:26 +0300 |
---|---|---|
committer | scratko <m@scratko.xyz> | 2024-11-23 01:24:26 +0300 |
commit | 3920a406c4161f6874d14ca8a78eca3c2b9fd9db (patch) | |
tree | ae4245f18ecd71c779c7d4cfbaec97db37725e61 /lexical_analysis.c | |
parent | 821b146c54330cecba3ed2cc03a0f71ad83e540f (diff) | |
download | shell-3920a406c4161f6874d14ca8a78eca3c2b9fd9db.tar.gz shell-3920a406c4161f6874d14ca8a78eca3c2b9fd9db.tar.bz2 shell-3920a406c4161f6874d14ca8a78eca3c2b9fd9db.zip |
Shell-VII release
Diffstat (limited to 'lexical_analysis.c')
-rw-r--r-- | lexical_analysis.c | 152 |
1 files changed, 113 insertions, 39 deletions
diff --git a/lexical_analysis.c b/lexical_analysis.c index 5db57cb..eab4390 100644 --- a/lexical_analysis.c +++ b/lexical_analysis.c @@ -46,11 +46,39 @@ int is_empty_word(int ch, struct param_type params) params.empty_word_flag; } -int command_execution_condition(struct param_type *params) +static int find_end_subshell_before_cur_pos(struct readline_type *readline) { + int i; + for(i = readline->considered_index-1; i >= 0; --i) { + if(readline->arr[i] == ' ') + continue; + break; + } + return i >= 0 && readline->arr[i] == ')'; +} + +int command_execution_condition(struct param_type *params, + struct readline_type *readline) +{ + if(params->tokens == and || params->tokens == or) { + if(find_end_subshell_before_cur_pos(readline)) + return 0; + } + if(params->tokens == next_command) { + if(find_end_subshell_before_cur_pos(readline)) + return 0; + } + if(params->tokens == '&') { + if(find_end_subshell_before_cur_pos(readline)) + return 0; + } + if(params->tokens == '(' && params->pipeline) + return 1; + return (params->tokens != '<' && params->tokens != '>' && - params->tokens != append && !params->pipeline) || + params->tokens != append && !params->pipeline && + params->tokens != start_subshell) || (params->pipeline && params->tokens == '&'); } @@ -59,24 +87,24 @@ int is_first_special_token_character(int ch) return ch == '<' || ch == '>' || ch == '&' || ch == '|' || ch == ';'; } -int excessive_words(int ch, struct param_type *params) +int excessive_words(int ch, struct param_type *params, + struct readline_type *readline) { - int next_ch; - if(filename_waiting(params)) { if(ch == new_line) return 0; - while((next_ch = getchar()) != new_line) { - if(next_ch == ' ') - continue; - if(!is_first_special_token_character(next_ch)) { + int i; + for(i = readline->considered_index+1; i <= readline->last_element_index; + ++i) + { + if(readline->arr[i] == ' ') + continue; + if(!is_first_special_token_character(readline->arr[i])) { params->wrong_command = err_extra_chars_after_filename; return 1; - } - else + } else break; } - ungetc(next_ch, stdin); } return 0; } @@ -101,16 +129,10 @@ int validate_redirections(int ch, int next_ch, struct param_type *params) params->streams.output_stream_to_append == NULL); } -int is_double_token(struct param_type *params) -{ - return params->tokens == and || params->tokens == or || - params->tokens == append; -} - int is_special_token(int ch, int next_ch) { - return (ch == '&' && next_ch == '&') || (ch == '|' && ch == '|') || - ch == '&' || ch == ';' || ch == '|'; + return (ch == '&' && next_ch == '&') || (ch == '|' && next_ch == '|') || + ch == '&' || ch == ';' || ch == '|' || ch == '(' || ch == ')'; } int is_redirect_token(int ch, int next_ch) @@ -139,8 +161,8 @@ int stream_redirect_tokens(struct w_queue *word_chain, if(validate_redirections(ch, next_ch, params)) { params->tokens = (ch == '>' && next_ch == '>') ? append : ch; - if(is_double_token(params)) - ++readline->considered_index; + if(params->tokens == append) + readline->considered_index += 2; return 1; } else params->wrong_command = err_redirect_stream_again; @@ -167,12 +189,20 @@ int pipeline_token_processing(struct w_queue *word_chain, struct dynamic_array *tmp_word, struct param_type *params) { + /* pipeline after subshell */ + if(tmp_word->last_element_index == -1 && params->tokens == start_subshell) { + params->tokens = '|'; + params->pipeline = 1; + return 1; + } + char **cmdline = NULL; if(is_stream_redirection_set(params) && wrong_streams_redirection(params)) { params->wrong_command = err_redirect_stream_in_pipeline; return 0; } + params->tokens = '|'; params->pipeline = 1; cmdline = @@ -184,44 +214,88 @@ int pipeline_token_processing(struct w_queue *word_chain, return 1; } +static void stop_by_previous_effect_tokens(struct param_type *params) +{ + if((params->tokens == and && last_execution_status == 1) || + (params->tokens == or && last_execution_status == 0)) + params->wrong_command = err_set_failure; +} + +static int find_repeated_background_symbol(struct readline_type *readline) +{ + int i; + for(i = readline->considered_index + 1; i <= readline->last_element_index; + ++i) + { + if(readline->arr[i] == '&') + return 1; + } + return 0; +} + /* * verification of special tokens (|, &, &&, ||), except redirection tokens */ int special_tokens(struct w_queue *word_chain, struct c_queue *cmdlines, - struct dynamic_array *tmp_word, int ch, + struct dynamic_array *tmp_word, int *ch, struct param_type *params, struct readline_type *readline) { int next_ch, i; - - if(ch == '|' || ch == '&') + if(*ch == '|' || *ch == '&') next_ch = readline->arr[readline->considered_index + 1]; - if(is_special_token(ch, next_ch)) { + if(is_special_token(*ch, next_ch)) { add_word_or_filename(word_chain, tmp_word, params); + stop_by_previous_effect_tokens(params); if(params->wrong_command) return 0; - if(ch == '|' && next_ch == '|') + if(*ch == '|' && next_ch == '|') { params->tokens = or; - else if(ch == '|') { - if(!pipeline_token_processing(word_chain, cmdlines, tmp_word, - params)) - return 0; - } else if(ch == '&' && next_ch == '&') + readline->considered_index += 2; + return 1; + } + if(*ch == '|') + return pipeline_token_processing(word_chain, cmdlines, tmp_word, + params); + if(*ch == '&' && next_ch == '&') { params->tokens = and; - else if(ch == '&') { + readline->considered_index += 2; + return 1; + } + if(*ch == '&') { + /* repeated & */ + if(find_repeated_background_symbol(readline)) { + params->wrong_command = err_repeated_background_ch; + return 0; + } + for(i = readline->considered_index+1; readline->arr[i] != new_line; ++i) { - if(readline->arr[i] != whitespace && readline->arr[i] != tab) { - params->wrong_command = err_bg_process; - return 0; - } + if(readline->arr[i] == ' ') + continue; + else + break; } + if(readline->arr[i] == new_line) + *ch = new_line; params->tokens = '&'; + return 1; + } + if(*ch == start_subshell) { + params->tokens = start_subshell; + return 1; + } + if(*ch == end_subshell) { + params->tokens = end_subshell; + return 1; } - if(is_double_token(params)) - ++readline->considered_index; + if(*ch == next_command) { + params->tokens = next_command; + return 1; + } + return 1; } return 0; |