Commit a49bbbdc authored by Seblu's avatar Seblu

reorganisation des options

ajout des fonctions pour les alias
debut de reecriture du lexer final

parent f923fc3f
......@@ -4,7 +4,9 @@ bin_PROGRAMS=42sh
#42sh_LDADD = parser/libparse.a ../check/leaktrack/libmem.a evalexpr/libevalexpr.a
42sh_SOURCES= ast/ast.h \
42sh_SOURCES= alias/alias.h \
alias/alias.c \
ast/ast.h \
ast/ast_and.c \
ast/ast_bang.c \
ast/ast_case.c \
......@@ -21,6 +23,7 @@ bin_PROGRAMS=42sh
ast/ast_until.c \
ast/ast_while.c \
common/common.h \
common/isdigitstr.c \
common/mem.h \
common/strmerge.c \
common/strvmerge.c \
......@@ -28,10 +31,9 @@ bin_PROGRAMS=42sh
common/basename.c \
exec/exec.h \
exec/exec_ast.c \
opt/opt.h \
opt/opt.c \
opt/opt_init.c \
opt/opt_parser.c \
option/option.h \
option/option.c \
option/option_parser.c \
parser/parser.h \
parser/parser.c \
parser/lexer.c \
......
/*
** alias.c for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Wed Aug 23 00:39:17 2006 Seblu
** Last update Wed Aug 23 18:47:59 2006 Seblu
*/
#include <string.h>
#include "alias.h"
#include "../common/mem.h"
static size_t step = 5;
ts_aliases *alias_init(void)
{
ts_aliases *new;
secmalloc(new, sizeof (ts_aliases));
new->size = step;
new->pos = 0;
new->db = NULL;
return new;
}
void alias_add(ts_aliases *aliases, const char *name, const char *value)
{
ts_alias *new;
int freeplace = 0;
size_t index;
//check if already exist and if free place exist
for (register int i = 0; aliases && aliases->db[i]; ++i)
if (!strcmp(aliases->db[i]->name, name)) {
free(aliases->db[i]->value);
aliases->db[i]->value = strdup(value);
return;
}
else if (!freeplace && *aliases->db[i]->name == 0)
index = i;
//if a place is free, fill it
if (freeplace) {
aliases->db[index]->name = strdup(name);
aliases->db[index]->value = strdup(value);
return;
}
//create a new one
secmalloc(new, sizeof (ts_alias));
new->name = strdup(name);
new->value = strdup(value);
//add a new alias if not find
if (aliases->pos >= aliases->size) {
aliases->size += step;
secrealloc(aliases->db, aliases->db, aliases->size * sizeof (ts_alias));
}
aliases->db[aliases->pos] = new;
++aliases->pos;
}
int alias_remove(ts_aliases *aliases, const char *name)
{
//find alias index
for (register int i = 0; aliases && aliases->db[i]; ++i)
if (!strcmp(aliases->db[i]->name, name)) {
free(aliases->db[i]->name);
free(aliases->db[i]->value);
aliases->db[i]->name = "";
return 1;
}
return 0;
}
/*
** alias.h for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Wed Aug 23 00:32:09 2006 Seblu
** Last update Wed Aug 23 18:44:52 2006 Seblu
*/
#ifndef ALIAS_H_
# define ALIAS_H_
# include <stddef.h>
typedef struct s_alias
{
char *name;
char *value;
} ts_alias;
typedef struct s_aliases
{
size_t size;
size_t pos;
ts_alias **db;
} ts_aliases;
/*!
** Create a new aliases database
**
** @return new alias database
*/
ts_aliases *alias_init(void);
/*!
** Add an alias into an alias database
**
** @param aliases alias database
** @param name new alias name
** @param value new alias value
*/
void alias_add(ts_aliases *aliases, const char *name, const char *value);
/*!
** Remove an alias into an alias database
**
** @param aliases alias database
** @param name alias name to remove
**
** @return true, if alias was found in database, else false
*/
int alias_remove(ts_aliases *aliases, const char *name);
#endif
......@@ -5,7 +5,7 @@
** Login <seblu@epita.fr>
**
** Started on Sun Jul 30 03:59:48 2006 Seblu
** Last update Thu Aug 3 06:01:23 2006 Seblu
** Last update Tue Aug 22 22:41:29 2006 Seblu
*/
#ifndef COMMON_H_
......@@ -52,4 +52,13 @@ char *basename(const char *path);
*/
char *strndup(const char *str, size_t n);
/*!
** Compute if string is composed only by digit
**
** @param str string to test
**
** @return boolean result
*/
int isdigitstr(const char *str);
#endif
/*
** isdigitstr.c for 42sh
**
** Made by Seblu
** Login <seblu@seblu.net>
**
** Started on Sun Nov 13 08:13:54 2005 Seblu
** Last update Tue Aug 22 22:43:54 2006 Seblu
*/
int isdigitstr(const char *str)
{
if (*str == 0)
return 0;
for (; *str; str++)
if (!(*str >= '0' && *str <= '9'))
return 0;
return 1;
}
/*
** 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 Thu Aug 3 02:45:51 2006 Seblu
*/
#include "opt.h"
#include "../common/mem.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;
}
......@@ -5,14 +5,21 @@
** Login <seblu@epita.fr>
**
** Started on Tue Mar 21 19:00:38 2006 Seblu
** Last update Sun Jul 30 03:41:36 2006 Seblu
** Last update Wed Aug 23 18:37:38 2006 Seblu
*/
/*
** ============
** DECLARATIONS
** ============
*/
#include <string.h>
#include "option.h"
#include "../shell/shell.h"
#include "opt.h"
#include "../common/mem.h"
static const char *opts_table[NBR_OPT] =
static const char *opts_table[NBR_OPTION] =
{
"xpg_echo",
"dotglob",
......@@ -22,15 +29,22 @@ static const char *opts_table[NBR_OPT] =
"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
/*
** ===========
** DEFINITIONS
** ===========
*/
int opt_set(const char *name, ts_opt *shopt)
ts_options *option_init(void)
{
ts_options *new;
secmalloc(new, sizeof (ts_options));
new->command = NULL;
return new;
}
int option_set(ts_options *shopt, const char *name)
{
register int i;
......@@ -43,15 +57,7 @@ int opt_set(const char *name, ts_opt *shopt)
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)
int option_unset(ts_options *shopt, const char *name)
{
register int i;
......@@ -64,16 +70,7 @@ int opt_unset(const char *name, ts_opt *shopt)
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)
int option_isset(const ts_options *shopt, const char *name)
{
register int i;
......@@ -83,11 +80,6 @@ int opt_isset(const char *name, const ts_opt *shopt)
return -1;
}
/*!
** Return a list of know opt
**
** @return list of opt
*/
const char **opt_get()
{
return opts_table;
......
/*
** option.h for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Tue Mar 21 18:50:03 2006 Seblu
** Last update Wed Aug 23 18:39:43 2006 Seblu
*/
#ifndef OPTION_H_
# define OPTION_H_
#define NBR_OPTION 8
#define DEBUG_OPTION 0
typedef struct s_options
{
signed char item[NBR_OPTION];
char *command;
} ts_options;
/*
** ==============
** FILE: option.c
** ==============
*/
/*!
** Create a new options structure
**
** @return A new options structure
*/
ts_options *option_init(void);
/*!
** Set a shell option
**
** @param shopt structure to apply
** @param name name of the option to set
**
** @return 0 on failure, else 1
*/
int option_set(ts_options *shopt, const char *name);
/*!
** Unset a shell option
**
** @param shopt structure to apply
** @param name name of the option to unset
**
** @return 0 on failure, else 1
*/
int option_unset(ts_options *shopt, const char *name);
/*!
** Tell if an option is set. if option nane is not set return -1
**
** @param shopt structure where find
** @param name name to find
**
** @return 0 if unset, 1 if set and -1 if not exist
*/
int option_isset(const ts_options *shopt, const char *name);
/*!
** Return a list of know opt
**
** @return list of opt
*/
const char **opt_get();
/*
** =====================
** FILE: option_parser.c
** =====================
*/
/*!
** Parse the command line
**
** @param opt shell opt structure to set with options
** @param argc program argc
** @param argv program argv
*/
void option_parser(ts_options *opt, int argc, char **argv);
#endif
/*
** opt_parser.c for 42sh
** option_parser.c for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sun Jul 30 03:28:26 2006 Seblu
** Last update Thu Aug 3 05:22:32 2006 Seblu
** Last update Wed Aug 23 18:39:19 2006 Seblu
*/
#include <stdio.h>
#include "opt.h"
#include "option.h"
#include "../common/common.h"
/*!
......@@ -19,16 +19,16 @@
** @param argv program argv
** @param opt shell opt structure to set with options
*/
void opt_parser(int argc, char **argv, ts_opt *opt)
void option_parser(ts_options *opt, int argc, char **argv)
{
#ifdef DEBUG42
#if DEBUG_OPTION == 1
printf("* Option Parser\n");
#endif
if (argc == 1)
return;
for (int i = 1; i < argc; ++i)
{
#ifdef DEBUG42
#if DEBUG_OPTION == 1
printf("argv[%d]=%s\n", i, argv[i]);
#endif
const char *copt = argv[i];
......@@ -37,7 +37,7 @@ void opt_parser(int argc, char **argv, ts_opt *opt)
if (copt[1] == 'c')
{
opt->command = strvmerge((const char**)argv + i + 1);
#ifdef DEBUG42
#if DEBUG_OPTION == 1
printf("option c: %s\n", opt->command);
#endif
break;
......
This diff is collapsed.
......@@ -5,27 +5,41 @@
** Login <seblu@epita.fr>
**
** Started on Wed Aug 2 00:56:07 2006 Seblu
** Last update Sat Aug 19 01:30:25 2006 Seblu
** Last update Tue Aug 22 19:10:23 2006 Seblu
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <setjmp.h>
#include "parser.h"
#include "../common/mem.h"
#include "../shell/shell.h"
#include "../readline/readline.h"
/*
** Declaration
** ============
** DECLARATIONS
** ============
*/
/*
** Define is parser is run for DEBBUGING
*/
#define DEBUG_PARSER 1
static ts_ast_node *regnode(ts_parser *parser, ts_ast_node *node);
/*!
** Parse a line
** Parse an input, following the Grammar rule input
** input: list '\n'
** list EOF
** | '\n'
** | EOF
**
** @param parser
** @param parser parser struct
**
** @return
** @return parent ast node, for execution
*/
static ts_ast_node *parse_input(ts_parser *parser);
......@@ -33,8 +47,28 @@ static ts_ast_node *parse_list(ts_parser *parser);
static ts_ast_node *parse_andor(ts_parser *parser);
static ts_ast_node *parse_pipeline(ts_parser *parser);
static ts_ast_node *parse_command(ts_parser *parser);
/*!
** Notify a parse error
**
** @param parser parser where error appear
** @param t token near of the error
*/
static void parse_error(ts_parser *parser, ts_token t);
#if DEBUG_PARSER==1
# define debugmsg(msg) fprintf(stderr, "debug: %s\n", (msg))
#else
# define debugmsg(msg)
#endif
/*
** Implemantation
** ===========
** DEFINITIONS
** ===========
*/
ts_parser *parser_init(FILE *fs)
......@@ -42,92 +76,151 @@ ts_parser *parser_init(FILE *fs)
ts_parser *new;
secmalloc(new, sizeof (ts_parser));
fflush(fs);
new->fs = fs;
lexer_reset(new);
new->lexer = lexer_init(fs);
new->error = 0;
new->regnodes = NULL;
new->regsize = new->regpos = 0;
return new;
}
void parse_error(ts_parser *parser, ts_token t)
static ts_ast_node *regnode(ts_parser *parser, ts_ast_node *node)
{
if (!node)
return node;
if (parser->regpos >= parser->regsize) {
parser->regsize += 50;
secrealloc(parser->regnodes, parser->regnodes,
parser->regsize * sizeof (ts_ast_node));
}
parser->regnodes[parser->regpos] = node;
++parser->regpos;
return node;
}
static void parse_error(ts_parser *parser, ts_token t)
{
printf("%s: syntax error near unexpected token `%s'\n",
shell->name, t.str);
parser->status = PARSE_ERROR;
debugmsg("parse_error");
fprintf(stderr, "%s: syntax error near unexpected token `%s'\n",
shell->name, t.str);
parser->error = 1;
shell->status = ERROR_PARSE;
if (parser->regnodes)
for (register int i = 0; parser->regnodes[i]; ++i)
ast_destruct(parser->regnodes[i]);
longjmp(parser->stack, 1);
}
ts_ast_node *parse(ts_parser *parser)
{
lexer_reset(parser);
parser->status = PARSE_OK;
lexer_start(parser->lexer);
parser->regpos = 0;
parser->error = 0;
// prevent of too big register ast size
if (parser->regsize >= 200)
secrealloc(parser->regnodes, parser->regnodes,
(parser->regsize = 50) * sizeof (ts_ast_node));
if (setjmp(parser->stack))
return NULL;
//test lexer mode
while (1)
{
ts_token tok;
tok = lexer_gettoken(parser);
tok = lexer_gettoken(parser->lexer);
if (tok.id == TOK_EOF)
exit(42);
if (tok.id == TOK_NEWLINE)
lexer_reset(parser);
lexer_start(parser->lexer);
printf("Returned token: %d [%s]\n", tok.id, tok.str);
}
return parse_input(parser);
}
static ts_ast_node *parse_input(ts_parser *parser)
{
ts_token cur_token;
ts_ast_node *buf;
ts_token token;
ts_ast_node *buf;
cur_token = lexer_gettoken(parser);
if (cur_token.id == TOK_EOF)
debugmsg("parse_input");
token = lexer_lookahead(parser->lexer);
if (token.id == TOK_EOF)
return NULL;
if (cur_token.id == TOK_NEWLINE)
return ast_sep_create(NULL, NULL);
if (token.id == TOK_NEWLINE) {
token = lexer_gettoken(parser->lexer);
return NULL;
}
buf = parse_list(parser);
cur_token = lexer_gettoken(parser);
if (cur_token.id != TOK_EOF || cur_token.id != TOK_NEWLINE)
parse_error(parser, cur_token);
token = lexer_gettoken(parser->lexer);
if (token.id != TOK_EOF || token.id != TOK_NEWLINE)
parse_error(parser, token);
return buf;
}
static ts_ast_node *parse_list(ts_parser *parser)
{
ts_token next_token;
ts_ast_node *lhs;
/* ts_ast_node *rhs; */
ts_token token;
ts_ast_node *lhs;
ts_ast_node *rhs;
debugmsg("parse_list");
lhs = parse_andor(parser);
next_token = lexer_gettoken(parser);
/* if (next_token.id == TOK_SEP) { */
/* lhs = parse_andor(parser); */
/* } */
/* else if (next_token.id == TOK_SEPAND) { */
/* parse_error(parser, next_token); */
/* /\* return buf; *\/ */
/* } */
/* parse_error(parser, next_token); */
/* return ; */
return NULL;
token = lexer_lookahead(parser->lexer);
if (token.id == TOK_SEP || token.id == TOK_SEPAND) {
lexer_gettoken(parser->lexer);
rhs = parse_list(parser);
if (token.id == TOK_SEP)
return regnode(parser, ast_sep_create(lhs, rhs));
else
return regnode(parser, ast_sepand_create(lhs, rhs));
}
return lhs;
}
static ts_ast_node *parse_andor(ts_parser *parser)
{
parser = parser;
return NULL;
ts_token token;
ts_ast_node *lhs;
ts_ast_node *rhs;
debugmsg("parse_andor");
lhs = parse_pipeline(parser);
token = lexer_lookahead(parser->lexer);
if (token.id == TOK_AND || token.id == TOK_OR) {
lexer_gettoken(parser->lexer);
rhs = parse_andor(parser);
if (token.id == TOK_AND)
return regnode(parser, ast_and_create(lhs, rhs));
else
return regnode(parser, ast_or_create(lhs, rhs));
}
return lhs;
}
/* static ts_ast_node *parse_pipeline(ts_parser *parser) */
/* { */
/* parser=parser; */
/* return NULL; */
/* } */
static ts_ast_node *parse_pipeline(ts_parser *parser)
{
ts_token token;
ts_ast_node *lhs;
int banged = 0;
debugmsg("parse_pipeline");
token = lexer_lookahead(parser->lexer);
if (token.id == TOK_BANG) {
lexer_gettoken(parser->lexer);
banged = 1;
}
lhs = parse_command(parser);
return lhs;
}
/* static ts_ast_node *parse_command(ts_parser *parser) */
/* { */
/* parser=parser; */
/* return NULL; */
/* } */