Commit b13062fe authored by Seblu's avatar Seblu

suppression fichier shell_getopt.c (inutile)

ajout d'un script qui creer un fichier ast.png a partir du dernier dot ast generer
debut des ast printer
parser de commande
parent f3f51117
input: list '\n'
list EOF
input: list '\n'
list EOF
| '\n'
| EOF
......@@ -13,9 +13,9 @@ command: simple_command
| shell_command (redirection)*
| funcdec
simple_command: (prefix)* (element)+
simple_command: (prefix)* (element)+
shell_command: '{' compound_list '}'
shell_command: '{' compound_list '}'
| '(' compound_list ')'
| rule_for
| rule_while
......@@ -25,7 +25,7 @@ shell_command: '{' compound_list '}'
funcdec: ['function'] WORD '(' ')' ('\n')* shell_command (redirection)*
redirection: [NUMBER] '>' WORD
redirection: [NUMBER] '>' WORD
| [NUMBER] '<' WORD
| [NUMBER] '>>' WORD
| [NUMBER] '<<' HEREDOC
......@@ -51,9 +51,9 @@ rule_until: 'until' compound_list do_group
rule_case: 'case' WORD ('\n')* 'in' ('\n')* [case_clause] 'esac'
rule_if: 'if' compound_list 'then' compound_list [else_clause] 'fi'
rule_if: 'if' compound_list 'then' compound_list [else_clause] 'fi'
else_clause: 'else' compound_list
else_clause: 'else' compound_list
| 'elif' compound_list 'then' compound_list [else_clause]
do_group: 'do' compound_list 'done'
......
......@@ -15,11 +15,13 @@ bin_PROGRAMS=42sh
ast/ast_if.c \
ast/ast_or.c \
ast/ast_pipe.c \
ast/ast_print.c \
ast/ast_sep.c \
ast/ast_sepand.c \
ast/ast_subshell.c \
ast/ast_until.c \
ast/ast_while.c \
common/basename.c \
common/common.h \
common/constant.h \
common/isdigitstr.c \
......@@ -27,7 +29,6 @@ bin_PROGRAMS=42sh
common/strmerge.c \
common/strvmerge.c \
common/strndup.c \
common/basename.c \
exec/exec.h \
exec/exec_node.c \
parser/alias.h \
......
......@@ -5,12 +5,13 @@
** Login <seblu@epita.fr>
**
** Started on Sun Jul 30 04:40:03 2006 Seblu
** Last update Tue Aug 29 00:35:06 2006 Seblu
** Last update Fri Sep 1 00:30:34 2006 Seblu
*/
#ifndef AST_H_
# define AST_H_
# include <stdio.h>
# include "../common/macro.h"
typedef struct ast_node s_ast_node;
......@@ -18,7 +19,7 @@ typedef struct ast_node s_ast_node;
/*
** If ast node
*/
typedef struct if_node
typedef struct if_node
{
s_ast_node *cond;
s_ast_node *cond_true;
......@@ -28,7 +29,7 @@ typedef struct if_node
/*
** For ast node
*/
typedef struct for_node
typedef struct for_node
{
char *varname;
char **values;
......@@ -39,7 +40,7 @@ typedef struct for_node
** Case item (not an ast node)
*/
typedef struct case_item s_case_item;
struct case_item
struct case_item
{
char **pattern;
s_ast_node *exec;
......@@ -49,7 +50,7 @@ struct case_item
/*
** Case ast node
*/
typedef struct case_node
typedef struct case_node
{
char *word;
s_case_item *items;
......@@ -58,7 +59,7 @@ typedef struct case_node
/*
** While ast node
*/
typedef struct while_node
typedef struct while_node
{
s_ast_node *cond;
s_ast_node *exec;
......@@ -67,7 +68,7 @@ typedef struct while_node
/*
** Enumerate different type of redirection
*/
typedef enum redir_type
typedef enum redir_type
{
R_LESS, /* < */
R_LESSAND, /* <& */
......@@ -83,8 +84,8 @@ typedef enum redir_type
/*
** Redirection ast node
*/
typedef struct redir s_redir;
struct redir
typedef struct redir s_redir;
struct redir
{
e_redir_type type;
int fd;
......@@ -95,7 +96,7 @@ struct redir
/*
** Command ast node
*/
typedef struct cmd_node
typedef struct cmd_node
{
char **argv;
s_redir *redirs;
......@@ -108,7 +109,7 @@ typedef struct cmd_node
** 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 bin_node
typedef struct bin_node
{
s_ast_node *lhs;
s_ast_node *rhs;
......@@ -117,7 +118,7 @@ typedef struct bin_node
/*
** Funcdec node
*/
typedef struct funcdec_node
typedef struct funcdec_node
{
char *name;
s_ast_node *body;
......@@ -126,7 +127,7 @@ typedef struct funcdec_node
/*
** Enumerate all node type
*/
typedef enum node_type
typedef enum node_type
{
T_IF,
T_FOR,
......@@ -147,7 +148,7 @@ typedef enum node_type
/*
** This is a type for a node item
*/
typedef union node_item
typedef union node_item
{
s_if_node child_if;
s_for_node child_for;
......@@ -168,12 +169,29 @@ typedef union node_item
/*
** Generic ast node type
*/
struct ast_node
struct ast_node
{
e_node_type type;
u_node_item body;
};
/*!
** Print an ast to @arg filename file
**
** @param ast ast to print
** @param filename filename where ast is printed. if it's NULL
** random file name is generated.
*/
void ast_print(s_ast_node *ast, const char *filename);
/*!
** Print an ast node
**
** @param ast ast node to add to file
** @param fs file stream where print ast
*/
void ast_print_node(s_ast_node *ast, FILE *fs, unsigned int *node_id);
/*!
** Destroy node and all its childs
**
......@@ -305,6 +323,25 @@ void ast_cmd_add_redir(s_ast_node *node,
int fd,
char *word);
/*!
** Add a arg vector to a cmd node
**
** @param node node where add
** @param argv new arg vector
*/
void ast_cmd_add_argv(s_ast_node *node, char *argv);
/*!
** Add a prefix to a cmd node
**
** @param node node for addition
** @param assignment_word word to add
*/
void ast_cmd_add_prefix(s_ast_node *node, char *assignment_word);
void ast_cmd_print(s_ast_node *node, FILE *fs, unsigned int *node_id);
/*!
** Destruct a cmd node
**
......
......@@ -5,7 +5,7 @@
** Login <seblu@epita.fr>
**
** Started on Fri Aug 18 22:13:51 2006 Seblu
** Last update Mon Aug 28 23:56:46 2006 Seblu
** Last update Fri Sep 1 00:44:22 2006 Seblu
*/
#include "ast.h"
......@@ -42,18 +42,90 @@ void ast_cmd_add_redir(s_ast_node *node,
*this = red;
}
void ast_cmd_add_prefix(s_ast_node *node, char *assignment_word)
{
if (node->type != T_CMD)
return;
size_t size = 0;
if (node->body.child_cmd.prefix)
while (node->body.child_cmd.prefix[size])
++size;
secrealloc(node->body.child_cmd.prefix, node->body.child_cmd.prefix,
(++size + 1) * sizeof (char *));
node->body.child_cmd.prefix[size - 1] = assignment_word;
node->body.child_cmd.prefix[size] = NULL;
}
void ast_cmd_add_argv(s_ast_node *node, char *argv)
{
if (node->type != T_CMD)
return;
size_t size = 0;
if (node->body.child_cmd.argv)
while (node->body.child_cmd.argv[size])
++size;
secrealloc(node->body.child_cmd.argv, node->body.child_cmd.argv,
(++size + 1) * sizeof (char *));
node->body.child_cmd.argv[size - 1] = argv;
node->body.child_cmd.argv[size] = NULL;
}
void ast_cmd_print(s_ast_node *node, FILE *fs, unsigned int *node_id)
{
unsigned cur_id = *node_id;
if (node->type != T_CMD)
return;
fprintf(fs, "%u [label = \"Command\"];\n", *node_id);
//prefix
char **prefix = node->body.child_cmd.prefix;
if (prefix && prefix[0]) {
++*node_id;
fprintf(fs, "%u [label = \"", *node_id);
for (int i = 0; prefix && prefix[i]; ++i) {
fprintf(fs, "prefix[%d]=%s\\n", i, prefix[i]);
}
fprintf(fs, "\"];\n");
fprintf(fs, "%u -> %u\n", cur_id, *node_id);
}
//arguments
char **argv = node->body.child_cmd.argv;
if (argv && argv[0]) {
++*node_id;
fprintf(fs, "%u [label = \"", *node_id);
for (int i = 0; argv && argv[i]; ++i)
fprintf(fs, "argv[%d]=%s\\n", i, argv[i]);
fprintf(fs, "\"];\n");
fprintf(fs, "%u -> %u\n", cur_id, *node_id);
}
//redirs
if (node->body.child_cmd.redirs) {
int i = 0;
++*node_id;
fprintf(fs, "%u [label = \"", *node_id);
for (s_redir *this = node->body.child_cmd.redirs; this; this = this->next, ++i)
fprintf(fs, "redirs[%d]: fd=%d, type=%d, word=%s\\n", i, this->fd, this->type, this->word);
fprintf(fs, "\"];\n");
fprintf(fs, "%u -> %u\n", cur_id, *node_id);
}
}
void ast_cmd_destruct(s_ast_node *node)
{
s_redir *this, *buf;
if (node->type != T_CMD)
return;
for (register int i = 0; node->body.child_cmd.argv[i]; ++i)
free(node->body.child_cmd.argv[i]);
for (register int i = 0; node->body.child_cmd.prefix[i]; ++i)
free(node->body.child_cmd.prefix[i]);
free(node->body.child_cmd.argv);
free(node->body.child_cmd.prefix);
if (node->body.child_cmd.argv) {
for (register int i = 0; node->body.child_cmd.argv[i]; ++i)
free(node->body.child_cmd.argv[i]);
free(node->body.child_cmd.argv);
}
if (node->body.child_cmd.prefix) {
for (register int i = 0; node->body.child_cmd.prefix[i]; ++i)
free(node->body.child_cmd.prefix[i]);
free(node->body.child_cmd.prefix);
}
for (this = node->body.child_cmd.redirs; this; this = buf) {
free(this->word);
buf = this->next;
......
/*
** ast_print.c for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sat Mar 25 23:11:01 2006 Seblu
** Last update Fri Sep 1 00:31:28 2006 Seblu
*/
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "ast.h"
#define NODE_TYPE_COUNT 14
typedef void (*print_fct)(s_ast_node *, FILE *, unsigned int *);
struct ast_print_switch
{
e_node_type type;
print_fct fct;
};
struct ast_print_switch print_table[NODE_TYPE_COUNT] =
{
{T_IF, NULL}, // ast_if_print},
{T_FOR, NULL}, //ast_for_print},
{T_WHILE, NULL}, //ast_while_print},
{T_UNTIL, NULL}, //ast_until_print},
{T_CMD, ast_cmd_print},
{T_AND, NULL}, //ast_and_print},
{T_OR, NULL}, //ast_or_print},
{T_SUBSHELL, NULL}, //ast_subshell_print},
{T_FUNCDEC, NULL}, //ast_funcdec_print},
{T_BANG, NULL}, //ast_bang_print},
{T_PIPE, NULL}, //ast_pipe_print},
{T_SEPAND, NULL}, //ast_sepand_print},
{T_SEP, NULL}, //ast_sep_print},
{T_CASE, NULL} //ast_sepand_print}
};
static char *newastfilename(void);
void ast_print(s_ast_node *ast, const char *filename)
{
FILE *fs;
unsigned int index;
if (ast == NULL)
return;
//open file stream
if (!filename)
filename = newastfilename();
if (!(fs = fopen(filename, "w")))
return;
//write dot header
fprintf(fs, "digraph \"42sh-ast\" {\n");
fprintf(fs, "node [fontname=Vera, color=lightblue2, style=filled];\n");
//start ast node wrinting
ast_print_node(ast, fs, &index);
//write dot foot and close
fprintf(fs, "}");
fclose(fs);
}
void ast_print_node(s_ast_node *ast, FILE *fs, unsigned int *node_id)
{
for (register int i = 0; i < NODE_TYPE_COUNT; ++i)
if (print_table[i].type == ast->type)
(print_table[i].fct)(ast, fs, node_id);
}
static char *newastfilename(void)
{
static char buf[PATH_MAX];
time_t st;
struct tm *t;
struct stat buf2;
int more = 0;
st = time(NULL);
t = localtime(&st);
do
snprintf(buf, 256, "/tmp/42sh-ast-%d-%d-%d-%d-%d-%d--%d.dot", 1900 + t->tm_year,
1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, more++);
while (stat(buf, &buf2) != -1 && more < 50);
return buf;
}
......@@ -5,7 +5,7 @@
** Login <seblu@epita.fr>
**
** Started on Thu Aug 3 02:41:37 2006 Seblu
** Last update Tue Aug 29 00:00:40 2006 Seblu
** Last update Wed Aug 30 00:36:03 2006 Seblu
*/
#include "ast.h"
......
#!/bin/sh
for i in /tmp/42sh-ast-*.dot; do
last="$i"
done
echo "$last to echo x${last%*.dot}"
dot -Tpng $last -o ${last%*.dot}.png
ln -sf ${last%*.dot}.png ast.png
......@@ -5,7 +5,7 @@
** Login <seblu@epita.fr>
**
** Started on Sun Jul 30 04:36:53 2006 Seblu
** Last update Tue Aug 29 02:33:06 2006 Seblu
** Last update Tue Aug 29 21:54:23 2006 Seblu
*/
#include <stdio.h>
......@@ -154,7 +154,7 @@ static int lexer_cut(s_lexer *lexer);
** @param id new token id
** @param s new token string
*/
static void token_set(s_token *token, e_tokenid id, const char *s);
static void token_set(s_token *token, e_tokenid id, char *s);
/*
......@@ -221,10 +221,10 @@ s_token lexer_getheredoc(s_lexer *lexer, const char *delim)
return token;
}
static void token_set(s_token *token, e_tokenid id, const char *s)
static void token_set(s_token *token, e_tokenid id, char *s)
{
if (token->id == TOK_WORD)
free((char*) token->str);
free(token->str);
token->id = id;
token->str = s;
if (s) token->len = strlen(s);
......
......@@ -5,7 +5,7 @@
** Login <seblu@epita.fr>
**
** Started on Wed Aug 2 00:56:07 2006 Seblu
** Last update Tue Aug 29 02:28:28 2006 Seblu
** Last update Fri Sep 1 01:00:42 2006 Seblu
*/
#include <stdio.h>
......@@ -24,26 +24,26 @@
*/
/* static ts_token keywords[] = */
/* { */
/* {TOK_IF, "if"}, */
/* {TOK_THEN, "then"}, */
/* {TOK_ELSE, "else"}, */
/* {TOK_FI, "fi"}, */
/* {TOK_ELIF, "elif"}, */
/* {TOK_DO, "do"}, */
/* {TOK_DONE, "done"}, */
/* {TOK_CASE, "case"}, */
/* {TOK_ESAC, "esac"}, */
/* {TOK_WHILE, "while"}, */
/* {TOK_UNTIL, "until"}, */
/* {TOK_FOR, "for"}, */
/* {TOK_IN, "in"}, */
/* {TOK_LBRACE, "{"}, */
/* {TOK_RBRACE, "}"}, */
/* {TOK_BANG, "!"}, */
/* {TOK_NONE, NULL} */
/* }; */
static s_token keywords[] =
{
{TOK_IF, "if", 2},
{TOK_THEN, "then", 4},
{TOK_ELSE, "else", 4},
{TOK_FI, "fi", 2},
{TOK_ELIF, "elif", 4},
{TOK_DO, "do", 2},
{TOK_DONE, "done", 4},
{TOK_CASE, "case", 4},
{TOK_ESAC, "esac", 4},
{TOK_WHILE, "while", 5},
{TOK_UNTIL, "until", 5},
{TOK_FOR, "for", 3},
{TOK_IN, "in", 2},
{TOK_LBRACE, "{", 1},
{TOK_RBRACE, "}", 1},
{TOK_BANG, "!", 1},
{TOK_NONE, NULL, 0}
};
static s_ast_node *regnode(s_parser *parser, s_ast_node *node);
......@@ -69,6 +69,8 @@ static s_ast_node *parse_pipeline(s_parser *parser);
static s_ast_node *parse_command(s_parser *parser);
static s_ast_node *parse_simplecommand(s_parser *parser);
/*!
** Notify a parse error
**
......@@ -128,6 +130,31 @@ static void parse_error(s_parser *parser, s_token t)
longjmp(parser->stack, 1);
}
/* static int is_keyword(s_token t) */
/* { */
/* for (int i = 0; keywords[i].id != TOK_NONE; ++i) */
/* if (!strncmp(t.str, keywords[i].str, keywords[i].len)) { */
/* t.id = keywords[i].id; */
/* return 1; */
/* } */
/* return 0; */
/* } */
static int is_assignment(s_token t)
{
return strchr(t.str, '=') == NULL ? 0 : 1;
}
static void recon(s_token t)
{
//check for keywords
for (int i = 0; keywords[i].id != TOK_NONE; ++i)
if (!strncmp(t.str, keywords[i].str, keywords[i].len)) {
t.id = keywords[i].id;
}
//check
}
s_ast_node *parse(s_parser *parser)
{
parser->regpos = 0;
......@@ -170,7 +197,7 @@ static s_ast_node *parse_input(s_parser *parser)
}
buf = parse_list(parser);
token = lexer_gettoken(parser->lexer);
if (token.id != TOK_EOF || token.id != TOK_NEWLINE)
if (token.id != TOK_EOF && token.id != TOK_NEWLINE)
parse_error(parser, token);
return buf;
}
......@@ -235,17 +262,37 @@ static s_ast_node *parse_command(s_parser *parser)
{
s_token token;
debugmsg("parse_command");
token = lexer_lookahead(parser->lexer);
//if (token.id == TOK_WORD)
recon(token);
if (token.id == TOK_WORD) {
return parse_simplecommand(parser);
}
return NULL;
}
/* static s_ast_node *parse_simplecommand(s_parser *parser) */
/* { */
/* parser=parser; */
/* return NULL; */
/* } */
static s_ast_node *parse_simplecommand(s_parser *parser)
{
s_token token;
s_ast_node *cmd;
debugmsg("parse_simplecommand");
cmd = regnode(parser, ast_cmd_create());
//get prefix
while (is_assignment(lexer_lookahead(parser->lexer)))
ast_cmd_add_prefix(cmd, lexer_gettoken(parser->lexer).str);
//get element
if ((token = lexer_gettoken(parser->lexer)).id == TOK_WORD)
ast_cmd_add_argv(cmd, token.str);
else
parse_error(parser, token);
while (recon(token = lexer_lookahead(parser->lexer)),
token.id == TOK_WORD) {
ast_cmd_add_argv(cmd, token.str);
lexer_gettoken(parser->lexer);
}
return cmd;
}
/* static s_ast_node *parse_shellcommand(s_parser *parser) */
/* { */
......
......@@ -5,7 +5,7 @@
** Login <seblu@epita.fr>
**
** Started on Wed Aug 2 00:49:50 2006 Seblu
** Last update Tue Aug 29 02:28:08 2006 Seblu
** Last update Fri Sep 1 00:21:07 2006 Seblu
*/
#include <setjmp.h>
......@@ -66,7 +66,7 @@ typedef enum tokenid
typedef struct token
{
e_tokenid id;
const char *str;
char *str;
size_t len;
} s_token;
......
......@@ -5,11 +5,13 @@
** Login <seblu@epita.fr>
**
** Started on Sun Jul 30 03:28:26 2006 Seblu
** Last update Tue Aug 29 00:54:37 2006 Seblu
** Last update Wed Aug 30 00:27:53 2006 Seblu
*/
#include <stdio.h>
#include <string.h>
#include "option.h"
#include "shell.h"
#include "../common/common.h"
/*!
......@@ -19,29 +21,26 @@
** @param argv program argv
** @param opt shell opt structure to set with options
*/
void getoptions(s_options *opt, int argc, char **argv)
void getoptions(s_options *opt, int argc, char **argv)
{
#if DEBUG_OPTION == 1
printf("* Option Parser\n");
#endif
if (argc == 1)
return;
for (int i = 1; i < argc; ++i)
{
for (int i = 1; i < argc; ++i) {
#if DEBUG_OPTION == 1
printf("argv[%d]=%s\n", i, argv[i]);
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);
const char *copt = argv[i];
if (!strcmp(copt, "-c") || !strcmp(copt, "--command")) {
opt->command = strvmerge((const char**)argv + i + 1);
#if DEBUG_OPTION == 1
printf("option c: %s\n", opt->command);
printf("option c: %s\n", opt->command);
#endif
break;
}
}
break;
}
else if (!strcmp(copt, "--ast-print"))
option_set(shell->options, "ast_print");
}
}
......@@ -5,7 +5,7 @@
** Login <seblu@epita.fr>
**
** Started on Tue Mar 21 19:00:38 2006 Seblu
** Last update Tue Aug 29 00:22:20 2006 Seblu
** Last update Wed Aug 30 00:19:38 2006 Seblu
*/
/*
......@@ -27,6 +27,7 @@ static const char *opts_table[NBR_OPTION] =
"nocaseglob",
"nullglob",
"expand_aliases",
"ast_print",
};
/*
......
......@@ -5,13 +5,13 @@
** Login <seblu@epita.fr>
**
** Started on Tue Mar 21 18:50:03 2006 Seblu
** Last update Tue Aug 29 00:54:50 2006 Seblu
** Last update Wed Aug 30 00:19:19 2006 Seblu
*/
#ifndef OPTION_H_
# define OPTION_H_
#define NBR_OPTION 8
#define NBR_OPTION 9
#define DEBUG_OPTION 0
......
......@@ -5,12 +5,13 @@
** Login <seblu@epita.fr>
**
** Started on Mon Apr 10 23:57:28 2006 Seblu
** Last update Tue Aug 29 00:53:31 2006 Seblu
** Last update Wed Aug 30 00:20:33 2006 Seblu
*/
#include <stdio.h>
#include <libgen.h>
#include "shell.h"
#include "option.h"
#include "../ast/ast.h"
#include "../parser/parser.h"
#include "../exec/exec.h"
......@@ -44,6 +45,8 @@ int main(int argc, char *argv[])