back to scratko.xyz
summaryrefslogtreecommitdiff
path: root/lexical_analysis.c
diff options
context:
space:
mode:
Diffstat (limited to 'lexical_analysis.c')
-rw-r--r--lexical_analysis.c152
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;