fix: manage errors in parse_command

This commit is contained in:
mcolonna 2024-06-10 17:47:23 +02:00
parent 44daaaf097
commit 1b9a8811f8
2 changed files with 38 additions and 17 deletions

View file

@ -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

View file

@ -6,7 +6,7 @@
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);
}