From 1b9a8811f865d50d42c87dad995cf93bc52b31af Mon Sep 17 00:00:00 2001 From: mcolonna Date: Mon, 10 Jun 2024 17:47:23 +0200 Subject: [PATCH] fix: manage errors in parse_command --- dev/TODO | 1 - src/parse_command.c | 54 +++++++++++++++++++++++++++++++-------------- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/dev/TODO b/dev/TODO index c96d23e..ad810a6 100644 --- a/dev/TODO +++ b/dev/TODO @@ -17,7 +17,6 @@ - env (with no options or arguments) - exit (with no options) - fix - - `$ |` throws 2 errors - empty variables aren't freed - need to free value returned by readline - the builtins should get all arguments and check if they're good diff --git a/src/parse_command.c b/src/parse_command.c index a4af678..48002d0 100644 --- a/src/parse_command.c +++ b/src/parse_command.c @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/24 13:47:40 by mcolonna #+# #+# */ -/* Updated: 2024/06/06 15:58:38 by mcolonna ### ########.fr */ +/* Updated: 2024/06/10 17:51:31 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -60,7 +60,7 @@ static int heredoc(t_memclass mc, int *readfd, const char *eof) const t_const_string eof_line = str_join(fatal_error, mc_in, eof, "\n"); if (pipe(outpipe) == -1) - minishell_error("errno"); + return (minishell_error("errno"), errno); *readfd = outpipe[0]; while (true) { @@ -112,29 +112,28 @@ static void skip_blank(t_stream *stream) // Add 'c' at the end of 'str' and return the result. // Also mem_free() 'str'. -static char *str_addchar(t_err err, t_memclass mc, const char *str, char c) +static char *str_addchar(t_memclass mc, const char *str, char c) { char *s; char *r; s = str_dup(fatal_error, mc, "-"); s[0] = c; - r = str_join(err, mc, str, s); + r = str_join(fatal_error, mc, str, s); mem_free(s); mem_free((void *)str); return (r); } // Read until a character is in the charset or is '\0' -// and append the string to dest.. +// and append the string to dest. static void read_until(t_parsing_args *args, const char **dest, const char *stop_charset) { while (stream_read(&args->stream) && !char_isin(stream_read(&args->stream), stop_charset) ) - *dest = str_addchar(fatal_error, args->mc, *dest, - stream_pop(&args->stream)); + *dest = str_addchar(args->mc, *dest, stream_pop(&args->stream)); } // Read until a character isn't in the charset or is '\0' @@ -142,13 +141,12 @@ static void read_until(t_parsing_args *args, const char **dest, void read_only(t_parsing_args *args, const char **dest, const char *charset) { while (char_isin(stream_read(&args->stream), charset)) - *dest = str_addchar(fatal_error, args->mc, *dest, - stream_pop(&args->stream)); + *dest = str_addchar(args->mc, *dest, stream_pop(&args->stream)); } // Read the value of the variable and append it to dest. // The stream must point to the first char of the variable name. -// FIXME Manage error (no variable name) +// Write a parse error and change args->r.error if no variable name. static void read_variable_value(t_parsing_args *args, const char **dest) { const char *name; @@ -157,6 +155,11 @@ static void read_variable_value(t_parsing_args *args, const char **dest) name = str_dup(fatal_error, args->mc, ""); read_only(args, &name, SYMBOL_CHARS); + if (str_eq(name, "")) + { + args->r.error = parse_error("variable name expected"); + return ; + } value = variables_get(args->variables, name); mem_free((char *)name); tmp = *dest; @@ -166,6 +169,7 @@ static void read_variable_value(t_parsing_args *args, const char **dest) // Read a string without quotes. // Append it to dest. +// Change args->r.error if error. static void read_string_noquote(t_parsing_args *args, const char **dest, const char *stop_charset) { @@ -180,6 +184,8 @@ static void read_string_noquote(t_parsing_args *args, const char **dest, { stream_pop(&args->stream); read_variable_value(args, dest); + if (args->r.error) + return ; } } } @@ -219,6 +225,8 @@ static bool read_string_doublequote(t_parsing_args *args, const char **dest) { stream_pop(&args->stream); read_variable_value(args, dest); + if (args->r.error) + return (true); } } if (!stream_read(&args->stream)) @@ -235,12 +243,15 @@ static bool read_string_doublequote(t_parsing_args *args, const char **dest) // - /[^(stop_charset)]+/ // - /'.*'/ // - /".*"/ +// Change args->r.error and return NULL if error. static const char *read_string(t_parsing_args *args, const char *stop_charset) { const char *str; char *const real_stop_charset = str_join(fatal_error, args->mc, stop_charset, " \r\n\t"); + if (!stream_read(&args->stream)) + return (NULL); str = str_dup(fatal_error, args->mc, ""); while (!args->r.error && stream_read(&args->stream) @@ -251,6 +262,8 @@ static const char *read_string(t_parsing_args *args, const char *stop_charset) read_string_noquote(args, &str, real_stop_charset); } mem_free(real_stop_charset); + if (args->r.error) + return (NULL); return (str); } @@ -268,6 +281,8 @@ static int read_call(t_parsing_args *args, const char *stop_charset) && !char_isin(stream_read(&args->stream), stop_charset)) { str = read_string(args, stop_charset); + if (args->r.error) + return (args->r.error); if (!str) return (parse_error("EOF unexpected")); list_add(fatal_error, &arguments, @@ -303,6 +318,8 @@ static int read_inputfile(t_parsing_args *args, const char *stop_charset) stream_pop(&args->stream); skip_blank(&args->stream); str = read_string(args, stop_charset); + if (args->r.error) + return (args->r.error); if (!str) return (parse_error("EOF unexpected")); if (heredoc) @@ -336,6 +353,8 @@ static int read_outputfile(t_parsing_args *args, const char *stop_charset) } skip_blank(&args->stream); str = read_string(args, stop_charset); + if (args->r.error) + return (args->r.error); if (!str) return (parse_error("EOF unexpected")); args->r.output_fd = open( @@ -353,8 +372,9 @@ static void read_element2(t_parsing_args *args, int *error, char c) if (c == '|') { if (!args->got_first_call) - *error = parse_error("'|', '>' or '<' expected"); - *error = read_call(args, "<>|"); + *error = parse_error("pipe before any call to a program"); + else + *error = read_call(args, "<>|"); } else if (c == '>') *error = read_outputfile(args, "<>|"); @@ -390,7 +410,6 @@ static int read_element(t_parsing_args *args) // Check if the command is a variable definition. // If possible, change 'variables' accordingly and return true. // If not, return false. -// FIXME read_string not possible. static bool parse_variable_set_command( t_parsing_args *args, const char *command, t_list *variables) { @@ -403,6 +422,10 @@ static bool parse_variable_set_command( if (str_len(var.name) == 0 || stream_pop(&args->stream) != '=') return (false); var.value = read_string(args, "<>|/"); + if (args->r.error) + return (false); + if (!var.value) + var.value = ""; skip_blank(&args->stream); if (stream_read(&args->stream)) return (false); @@ -451,7 +474,6 @@ static t_parsing_args init_parsing_args(const t_memclass mc, // an "empty" t_command. // - If the command string is empty (or blank), return an "empty" t_command. // - If there is any error, return a t_command with .error != 0. -// FIXME error with heredoc and parse error t_command parse_command(const t_memclass mc, const char *command, t_list *variables) { @@ -471,7 +493,7 @@ t_command parse_command(const t_memclass mc, const char *command, return (args.r); } read_command(&args); - if (args.heredoc) - heredoc(mc, &args.r.input_fd, args.heredoc); + if (!args.r.error && args.heredoc) + args.r.error = heredoc(mc, &args.r.input_fd, args.heredoc); return (args.r); }