Commit 6ef731df authored by Seblu's avatar Seblu

parser minimum d'option sur argv

reorganisation des structs de l'ast

parent f8bcc9ae
......@@ -89,7 +89,7 @@ AC_ARG_WITH([debug],
[AS_HELP_STRING([--with-debug], [use -g and don't use -DNDEBUG -O3])],
[dnl action-if-given: --with-debug => -g || --without-debug => -DNDEBUG
if test x$withval = xyes; then
CFLAGS="$CFLAGS -g"
CFLAGS="$CFLAGS -g -DDEBUG42"
else
CFLAGS="$CFLAGS -DNDEBUG -O3"
fi
......
......@@ -4,15 +4,20 @@ bin_PROGRAMS=42sh
#42sh_LDADD = parser/libparse.a ../check/leaktrack/libmem.a evalexpr/libevalexpr.a
42sh_SOURCES= shell/shell.h \
42sh_SOURCES= ast/ast.h \
common/common.h \
common/macro.h \
common/strmerge.c \
common/strvmerge.c \
lexer/lexer.h \
shell/shell.h \
shell/shell_entry.c \
shell/shell_init.c \
shell/shell_destroy.c
# EXTRA_DIST= \
# parser/parse42.y \
# parser/scan42.l \
# evalexpr/evalexpr.y \
# evalexpr/evalexpr.l
shell/shell_destroy.c \
shell/shell_prompt.c \
opt/opt.h \
opt/opt.c \
opt/opt_init.c \
opt/opt_parser.c
CLEANFILES= *~ '\#*'
/*
** ast.h for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sun Jul 30 04:40:03 2006 Seblu
** Last update Sun Jul 30 05:35:28 2006 Seblu
*/
#ifndef AST_H_
# define AST_H_
# include <sys/types.h>
# include <errno.h>
# include <stdlib.h>
# include <assert.h>
/*
** If ast node
*/
typedef struct
{
ts_ast_node *cond;
ts_ast_node *cond_true;
ts_ast_node *cond_false;
} ts_if_node;
/*
** For ast node
*/
typedef struct
{
char *name;
ts_ast_node *values;
ts_ast_node *exec;
} ts_for_node;
/*
** Case ast node
*/
typedef struct
{
char *word;
//FIXME
struct s_case_item **items;
} ts_case_node;
/*
** While ast node
*/
typedef struct
{
ts_ast_node *cond;
ts_ast_node *exec;
} ts_while_node;
/*
** Enumerate different type of redirection
*/
typedef enum
{
R_LESS, /* < */
R_LESSAND, /* <& */
R_GREAT, /* > */
R_GREATAND, /* >& */
R_DGREAT, /* >> */
R_LESSGREAT, /* <> */
R_CLOBBER, /* >| */
R_DLESS, /* << */
R_DLESSDASH /* <<- */
} te_redir_type;
/*
** Redirection ast node
*/
typedef struct
{
te_redir_type type;
int fd;
char *string;
} ts_redir_node;
/*
** Command ast node
*/
typedef struct
{
char **argv;
ts_redir **redirs;
char **prefix;
} ts_cmd_node;
/*
** Binary ast node
** Generic type, it's a contener !
** T_PIPE, T_SEP_* , T_AND, T_OR : binary operator
** T_BANG : unary operator but ts_bin_op with right pointer is always NULL
*/
typedef struct
{
ts_ast_node *left;
ts_ast_node *right;
} ts_bin_node;
/*
** Subshell ast node
*/
typedef struct
{
ts_ast_node *head;
} ts_subshell_node;
/*
** Funcdec node
*/
struct
{
char *name;
ts_ast_node *body;
} ts_funcdec_node;
/*
** Enumerate all node type
*/
typedef enum
{
T_IF,
T_FOR,
T_WHILE,
T_UNTIL,
T_CMD,
T_AND,
T_OR,
T_SUBSHELL,
T_FUNCDEC,
T_BANG,
T_PIPE,
T_SEP_AND,
T_SEP_SEMICOMMA,
T_CASE,
T_CASE_LIST,
T_LIST,
T_CL,
T_CASE_ITEM,
T_ITEM,
T_LINE,
T_WL,
T_END
} te_node_type;
/*
** This is a type for a node item
*/
typedef union
{
ts_if_node node_if;
ts_for_node node_for;
ts_case_node node_case;
ts_while_node node_while;
ts_while_node node_until;
ts_cmd_node node_cmd;
ts_op_node node_and;
ts_op_node node_or;
ts_subshell_node node_subshell;
ts_funcdec_node node_funcdec;
ts_op_node node_bang;
ts_op_node node_pipe;
ts_op_node node_sep_semicomma;
ts_op_node node_sep_and;
/* ts_case_item node_case_item; */
/* ts_wordlist node_wl; */
/* ts_case_list node_case_list; */
} tu_node_item;
/*
** Generic ast node type
*/
typedef struct
{
te_node_type type;
tu_node_item node;
} ts_ast_node;
/**
** structure wordlist ex : for var in wordlist do
** word : word
** next : next word finally Sexy NULL
*/
struct s_wordlist
{
char *word;
struct s_wordlist *next;
};
struct s_case_item
{
char **patterns;
int allocated;
int pos;
};
struct s_item
{
struct s_wordlist *pl;
struct s_ast *cmd_list;
};
/**
** temporary structure
** which contains prefix and
** suffix command informations
** argv word or assigment words terminated by NULL
** redirs redirection pointer
** pos position in argv array
** nb_arg_alloc positions allocated
*/
struct s_cmd_opt
{
char **argv;
struct s_redir *redirs;
int pos;
int nb_arg_alloc;
};
/**
** create temporary structure
** in order to get prefix and
** suffix informations
*/
struct s_cmd_opt *tmp_create_cmdopt(struct s_cmd_opt *opt,
struct s_redir *redir,
char *arg);
/**
** add redirection to temporary
** structure s_redir
*/
struct s_redir *tmp_add_redir(struct s_redir *base, struct s_redir *nelt);
/**
** create temporary structure s_redir
*/
struct s_redir *tmp_create_redir(enum e_redir type,
char *filename,
int fd,
struct s_redir *redir);
/*
** PLEASE NOTE
** Every time, any argument given so this functions must be on the heap,
** they are not copied. Don't forget to dup string, for function create_cmd,
** function add_redir and function create_for
*/
/*!
** Create an and node
**
** @param lhs left hand side
** @param rhs right hand side
**
** @return new ast node
*/
struct s_ast *ast_create_and(struct s_ast *lhs, struct s_ast *rhs);
/*!
** Create an or node
**
** @param lhs left hand side
** @param rhs right hand side
**
** @return new ast node
*/
struct s_ast *ast_create_or(struct s_ast *lhs, struct s_ast *rhs);
struct s_ast *ast_create_case_clause(char *word,
struct s_ast *case_list);
struct s_ast *ast_create_if(struct s_ast *cond,
struct s_ast *positive,
struct s_ast *negative);
struct s_ast *ast_create_funcdec(char *name, struct s_ast *body);
struct s_ast *ast_create_subshell(struct s_ast *cmd);
struct s_ast *ast_create_for(char *varname,
struct s_ast *value,
struct s_ast *exec);
/**
** create cmd node
*/
struct s_ast *ast_create_cmd(struct s_cmd_opt *prefix,
char *cmd,
struct s_cmd_opt *suffix);
/* struct s_ast *ast_create_list(struct s_ast **item); */
struct s_ast *ast_create_until(struct s_ast *cond,
struct s_ast *exec);
struct s_ast *ast_create_while(struct s_ast *cond,
struct s_ast *exec);
/**
** create pipe node
*/
struct s_ast *ast_create_pipe(struct s_ast *cmd1,
struct s_ast *cmd2);
/**
** create shell structure
*/
struct s_42sh *ast_create_ast(struct s_42sh *shell,
struct s_ast *ast);
struct s_ast *ast_create_patterns(char *word, struct s_ast *case_item);
struct s_ast *ast_create_case_list(struct s_ast *item,
struct s_ast *case_list);
struct s_ast *ast_create_wordlist(struct s_ast *wl,
char *w);
/**
** change ast type : PIPE -> BANG_PIPE and CMD -> BANG_CMD
*/
struct s_ast *ast_create_bang(struct s_ast *ast);
struct s_ast *ast_create_sep_op(struct s_ast *cmd1,
enum e_type sep_op,
struct s_ast *cmd2);
/* void ast_destruct_list(struct s_ast *node); */
void ast_destruct_cmd(struct s_ast *node);
void ast_destruct_pipe(struct s_ast *node);
void ast_destruct_redir(struct s_redir *red);
/* void ast_print(struct s_ast *ast); */
void ast_destruct_sep_op(struct s_ast *node);
void ast_destruct_for(struct s_ast *node);
void ast_destruct_until(struct s_ast *node);
void ast_destruct_while(struct s_ast *node);
void ast_destruct_if(struct s_ast *node);
void ast_destruct(struct s_ast *node);
void ast_destruct_bang(struct s_ast *node);
void ast_destruct_wordlist(struct s_ast *node);
void ast_destruct_case(struct s_ast *node);
/*!
** Destruct an and node
**
** @param node head of node to destruct
*/
void ast_destruct_and(struct s_ast *node);
/*!
** Destruct an or node
**
** @param node head of node to destruct
*/
void ast_destruct_or(struct s_ast *node);
void ast_destruct_subshell(struct s_ast *node);
#endif /* !AST_H_ */
/*
** common.h for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sun Jul 30 03:59:48 2006 Seblu
** Last update Sun Jul 30 04:33:18 2006 Seblu
*/
#ifndef COMMON_H_
# define COMMON_H_
char *strmerge(int n, const char *s1, ...);
char *strvmerge(const char * const *vtable);
#endif
/*
** mem.h for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sun Jul 30 03:35:39 2006 Seblu
** Last update Sun Jul 30 03:42:49 2006 Seblu
*/
#ifndef MACRO_H_
# define MACRO_H_
#include <stdlib.h>
static const int MEM_ERROR = 42;
# define secmalloc(name, size) if (!(name = malloc(size))) exit(MEM_ERROR)
# define secrealloc(ret, name, size) if (!(ret = realloc(name, size))) exit(MEM_ERROR)
# define secstrdup(ret, str) if (!(ret = strdup(str))) exit(MEM_ERROR)
#endif
/*
** strmerges.c for 42sh in /home/seblu/devel/c/42sh
** strmerge.c for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Tue May 16 21:23:02 2006 Seblu
** Last update Tue May 16 21:27:30 2006 Seblu
** Last update Sun Jul 30 04:15:36 2006 Seblu
*/
#include <stdarg.h>
#include <string.h>
#include "42sh.h"
#include "macro.h"
/*!
** Merge strings
......@@ -21,7 +21,7 @@
** @return malloced string merged
** @warning the returned string must be freed by the caller
*/
char *strmerges(int n, const char *s1, ...)
char *strmerge(int n, const char *s1, ...)
{
va_list param;
char *new = NULL;
......
/*
** strvmerge.c for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sun Jul 30 04:03:35 2006 Seblu
** Last update Sun Jul 30 04:36:05 2006 Seblu
*/
#include <string.h>
#include "macro.h"
/*!
** Merge a vector of string
**
** @param vtable strings to merge
**
** @return a string merged from @arg vtable
*/
char *strvmerge(const char *const *vtable)
{
size_t string_sz = 0;
const char *const *elem;
char *new;
for (elem = vtable; *elem; ++elem)
string_sz += strlen(*elem);
secmalloc(new, ++string_sz * sizeof (char));
string_sz = 0;
for (elem = vtable; *elem; ++elem)
{
strcpy(new + string_sz, *elem);
string_sz += strlen(*elem);
}
return new;
}
/*
** lexer.h for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sun Jul 30 04:36:53 2006 Seblu
** Last update Sun Jul 30 04:37:57 2006 Seblu
*/
#ifndef LEXER_H_
# define LEXER_H_
#endif
/*
** opt_shopt.c for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Tue Mar 21 19:00:38 2006 Seblu
** Last update Sun Jul 30 03:41:36 2006 Seblu
*/
#include <string.h>
#include "../shell/shell.h"
#include "opt.h"
static const char *opts_table[NBR_OPT] =
{
"xpg_echo",
"dotglob",
"extglob",
"nocaseglob",
"nullglob",
"expand_aliases",
};
/*!
** Set a shell option
**
** @param name name of the option to set
** @param shopt structure to apply
**
** @return 0 on failure, else 1
*/
int opt_set(const char *name, ts_opt *shopt)
{
register int i;
for (i = 0; opts_table[i]; ++i)
if (!strcmp(name, opts_table[i]))
{
shopt->item[i] = 1;
return 1;
}
return 0;
}
/*!
** Unset a shell option
**
** @param name name of the option to unset
** @param shopt structure to apply
**
** @return 0 on failure, else 1
*/
int opt_unset(const char *name, ts_opt *shopt)
{
register int i;
for (i = 0; opts_table[i]; ++i)
if (!strcmp(name, opts_table[i]))
{
shopt->item[i] = 0;
return 1;
}
return 0;
}
/*!
** Tell if an option is set. if option nane is not set return -1
**
** @param name name to find
** @param shopt structure where find
**
** @return 0 if unset, 1 if set and -1 if not exist
*/
int opt_isset(const char *name, const ts_opt *shopt)
{
register int i;
for (i = 0; opts_table[i]; ++i)
if (!strcmp(name, opts_table[i]))
return shopt->item[i];
return -1;
}
/*!
** Return a list of know opt
**
** @return list of opt
*/
const char **opt_get()
{
return opts_table;
}
/*
** opt.h for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Tue Mar 21 18:50:03 2006 Seblu
** Last update Sun Jul 30 03:51:48 2006 Seblu
*/
#ifndef OPT_H_
# define OPT_H_
#define NBR_OPT 8
typedef struct
{
signed char item[NBR_OPT];
char *command;
} ts_opt;
ts_opt *opt_init(void);
void opt_parser(int argc, char *argv[], ts_opt *opt);
int opt_set(const char *name, ts_opt *shopt);
int opt_unset(const char *name, ts_opt *shopt);
int opt_isset(const char *name, const ts_opt *shopt);
const char **opt_get(void);
#endif /* ! OPT_H_ */
/*
** opt_init.c for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sun Jul 30 03:33:09 2006 Seblu
** Last update Sun Jul 30 03:57:27 2006 Seblu
*/
#include "opt.h"
#include "../common/macro.h"
/*!
** Create a new option structure
**
** @return A new option structure
*/
ts_opt *opt_init(void)
{
ts_opt *new;
secmalloc(new, sizeof (ts_opt));
new->command = NULL;
return new;
}
/*
** opt_parser.c for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sun Jul 30 03:28:26 2006 Seblu
** Last update Sun Jul 30 04:37:35 2006 Seblu
*/
#include <stdio.h>
#include "opt.h"
#include "../common/common.h"
/*!
** Parse the command line
**
** @param argc program argc
** @param argv program argv
** @param opt shell opt structure to set with options
*/
void opt_parser(int argc, char **argv, ts_opt *opt)
{
#ifdef DEBUG42
printf("* Option Parser\n");
#endif
if (argc == 1)
return;
for (int i = 1; i < argc; ++i)
{
#ifdef DEBUG42
printf("argv[%d]=%s\n", i, argv[i]);
#endif
const char *copt = argv[i];
if (*copt == '-')
{
if (copt[1] == 'c')
{
opt->command = strvmerge((const char**)argv + i + 1);
#ifdef DEBUG42
printf("option c: %s\n", opt->command);
#endif
break;
}
}
}
}
......@@ -5,7 +5,7 @@
** Login <seblu@epita.fr>
**
** Started on Sun Jul 16 20:03:53 2006 Seblu
** Last update Sun Jul 16 20:18:23 2006 Seblu
** Last update Sun Jul 30 03:42:43 2006 Seblu
*/
#ifndef SHELL_H_
......@@ -13,31 +13,27 @@
# include <errno.h>
# include <stdlib.h>
# include "../opt/opt.h"
# define SCAN_ERROR 1
# define PARSE_ERROR 2
# define MEM_ERROR 42
# define FORK_ERROR 128
# define RED_ERROR 1
static const int SCAN_ERROR = 1;
static const int PARSE_ERROR = 2;
static const int FORK_ERROR = 128;
static const int RED_ERROR = 1;
# define secmalloc(name, size) if (!(name = malloc(size))) exit(MEM_ERROR)
# define secrealloc(ret, name, size) if (!(ret = realloc(name, size))) exit(MEM_ERROR)
# define secstrdup(ret, str) if (!(ret = strdup(str))) exit(MEM_ERROR)
struct s_shell
typedef struct
{
/* struct s_ast *ast; */
/* struct s_var *vars; */
/* struct s_func *funcs; */
/* struct s_opt *opt; */
/* struct s_history *history; */
ts_opt *opt;
int last_status;
};
} ts_shell;
ts_shell *shell_init(void);
void shell_destroy(ts_shell *sh);
struct s_shell *shell_init(void);
void shell_destroy(struct s_shell *sh);
char *strmerges(int n, const char *s1, ...);
ts_shell *shell;
#endif /* !SHELL_H_ */
......@@ -5,7 +5,7 @@
** Login <seblu@epita.fr>