From de22dd53415040ce2e9f5e79c598a3001f5c716d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Luttringer?= Date: Tue, 14 Nov 2006 19:36:44 +0000 Subject: [PATCH] work on execution work on variables work on functions --- Makefile.am | 23 +- README | 3 + configure.ac | 14 +- src/common/basename.c | 4 +- src/common/env.c | 60 ++++ src/common/{common.h => function.h} | 38 ++- src/common/getcwd2.c | 22 ++ src/exec/exec_cmd.c | 467 +++++++++++++--------------- src/parser/alias.c | 18 +- src/parser/alias.h | 18 +- src/parser/lexer.c | 4 +- src/parser/parser.c | 4 +- src/shell/func.c | 36 +++ src/shell/func.h | 46 +++ src/shell/getoptions.c | 8 +- src/shell/option.c | 46 +-- src/shell/option.h | 29 +- src/shell/shell.c | 103 ++++++ src/shell/shell.h | 20 +- src/shell/shell_destroy.c | 29 -- src/shell/shell_entry.c | 62 ---- src/shell/shell_init.c | 90 ------ src/shell/var.c | 144 +++++++++ src/shell/var.h | 69 ++++ 24 files changed, 826 insertions(+), 531 deletions(-) create mode 100644 README create mode 100644 src/common/env.c rename src/common/{common.h => function.h} (68%) create mode 100644 src/common/getcwd2.c create mode 100644 src/shell/func.c create mode 100644 src/shell/func.h create mode 100644 src/shell/shell.c delete mode 100644 src/shell/shell_destroy.c delete mode 100644 src/shell/shell_entry.c delete mode 100644 src/shell/shell_init.c create mode 100644 src/shell/var.c create mode 100644 src/shell/var.h diff --git a/Makefile.am b/Makefile.am index 90f5e5e..498b4af 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,8 +21,10 @@ bin_PROGRAMS=42sh src/builtin/builtin.c \ src/builtin/builtin_exit.c \ src/common/basename.c \ - src/common/common.h \ src/common/constant.h \ + src/common/env.c \ + src/common/function.h \ + src/common/getcwd2.c \ src/common/isdigitstr.c \ src/common/macro.h \ src/common/strmerge.c \ @@ -39,21 +41,24 @@ bin_PROGRAMS=42sh src/exec/exec_sep.c \ src/exec/exec_sepand.c \ src/exec/exec_while.c \ - src/parser/alias.h \ src/parser/alias.c \ - src/parser/getline.h \ + src/parser/alias.h \ src/parser/getline.c \ - src/parser/parser.h \ + src/parser/getline.h \ src/parser/parser.c \ + src/parser/parser.h \ src/parser/lexer.c \ + src/shell/func.c \ + src/shell/func.h \ src/shell/getoptions.c \ - src/shell/option.h \ src/shell/option.c \ + src/shell/option.h \ + src/shell/shell.c \ src/shell/shell.h \ - src/shell/shell_entry.c \ - src/shell/shell_init.c \ - src/shell/shell_destroy.c \ - src/shell/prompt.c + src/shell/prompt.c \ + src/shell/var.c \ + src/shell/var.h + CLEANFILES= *~ \#*\# diff --git a/README b/README new file mode 100644 index 0000000..de54a03 --- /dev/null +++ b/README @@ -0,0 +1,3 @@ +42sh + +This program was written by Sebastien Luttringer aka Seblu diff --git a/configure.ac b/configure.ac index 07a584e..b15e549 100644 --- a/configure.ac +++ b/configure.ac @@ -98,16 +98,6 @@ AC_ARG_WITH([noerror], ] ) -AC_ARG_WITH([dynamic], - [AS_HELP_STRING([--with-dynamic], [Compiling with dynamic libraries])], - [dnl action-if-given - dynamic=true - ], - [dnl action-if-not-given - dynamic=false - ] -) - AC_ARG_WITH([debug], [AS_HELP_STRING([--with-debug], [use -g and don't use -DNDEBUG -O3])], [dnl action-if-given @@ -125,7 +115,7 @@ AC_ARG_WITH([efence], CFLAGS="$CFLAGS -include stdlib.h -include efence.h" ], [dnl action-if-not-given - test "$dynamic" = "true" || LDFLAGS="$LDFLAGS -static" + true ] ) @@ -141,4 +131,4 @@ AC_CONFIG_FILES([ Makefile ]) -AC_OUTPUT \ No newline at end of file +AC_OUTPUT diff --git a/src/common/basename.c b/src/common/basename.c index a669d83..5f63afb 100644 --- a/src/common/basename.c +++ b/src/common/basename.c @@ -5,11 +5,11 @@ ** Login ** ** Started on Thu Aug 3 05:29:46 2006 Seblu -** Last update Sat Aug 19 01:57:49 2006 Seblu +** Last update Tue Nov 14 15:37:34 2006 seblu */ #include -#include "common.h" +#include "function.h" char *basename(const char *path) { diff --git a/src/common/env.c b/src/common/env.c new file mode 100644 index 0000000..a75e586 --- /dev/null +++ b/src/common/env.c @@ -0,0 +1,60 @@ +/* +** env.c for 42sh +** +** Made by seblu +** Login +** +** Started on Tue Nov 14 14:38:42 2006 seblu +** Last update Tue Nov 14 15:37:46 2006 seblu +*/ + +#include +#include +#include +#include +#include "function.h" + +int setenv2(char *name, + char *value, + int overwrite) +{ + extern char **environ; + char *buf; + char **env = environ; + size_t len; + + assert(name && value && env); + len = strlen(name); + if (!overwrite) + for (; *env; ++env) + if (!strncmp(name, *env, len) && (*env)[len] == '=') + return 1; + buf = strmerge(3, name, "=", value); + return !putenv(buf) ? 0 : 2; +} + +int unsetenv2(const char *name) +{ + extern char **environ; + size_t len; + char **ep = environ; + char **dp = ep; + + if (name == NULL || *name == '\0' || strchr(name, '=') != NULL) + { + errno = EINVAL; + return -1; + } + len = strlen(name); + for (; *ep; ++ep) + { + if (!strncmp(*ep, name, len) && (*ep)[len] == '=') + { + dp = ep; + do + dp[0] = dp[1]; + while (++dp, *dp); + } + } + return 0; +} diff --git a/src/common/common.h b/src/common/function.h similarity index 68% rename from src/common/common.h rename to src/common/function.h index 489aaae..6d7396c 100644 --- a/src/common/common.h +++ b/src/common/function.h @@ -1,15 +1,15 @@ /* -** common.h for 42sh +** function.h for 42sh ** ** Made by Seblu ** Login ** ** Started on Sun Jul 30 03:59:48 2006 Seblu -** Last update Wed Oct 11 16:56:07 2006 seblu +** Last update Tue Nov 14 15:36:14 2006 seblu */ -#ifndef COMMON_H_ -# define COMMON_H_ +#ifndef FUNCTION_H_ +# define FUNCTION_H_ /*! ** Merge strings @@ -74,4 +74,34 @@ int isdigitstr(const char *str); */ char **strvectoradd(char **vector, char *str); +/*! +** Return the current working directory in a malloced string. +** +** @return the current working directory +*/ +char *getcwd2(void); + +/*! +** Add a name and value to the current environment +** +** @param name variable name +** @param value variable value +** @param overwrite boolean which tell if overwrite a existing value +** +** @return boolean success +*/ +int setenv2(char *name, + char *value, + int overwrite); + +/*! +** Remove from environment a variable. +** @warning Don't use unsetenv ! +** +** @param name env variable to remove +** +** @return boolean success +*/ +int unsetenv2(const char *name); + #endif diff --git a/src/common/getcwd2.c b/src/common/getcwd2.c new file mode 100644 index 0000000..40e7099 --- /dev/null +++ b/src/common/getcwd2.c @@ -0,0 +1,22 @@ +/* +** getcwd2.c for 42sh +** +** Made by seblu +** Login +** +** Started on Tue Nov 14 14:20:08 2006 seblu +** Last update Tue Nov 14 14:23:39 2006 seblu +*/ + +#include +#include +#include "macro.h" + +char *getcwd2(void) +{ + char *get; + const size_t BUF_SIZE = PATH_MAX * sizeof (char); + + secmalloc(get, BUF_SIZE); + return getcwd(get, BUF_SIZE); +} diff --git a/src/exec/exec_cmd.c b/src/exec/exec_cmd.c index a4cf213..be6f226 100644 --- a/src/exec/exec_cmd.c +++ b/src/exec/exec_cmd.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Sat Apr 8 07:38:48 2006 Seblu -** Last update Sun Nov 12 04:04:09 2006 seblu +** Last update Tue Nov 14 13:50:59 2006 seblu */ #define DEBUG_EXEC 0 @@ -19,295 +19,250 @@ #include #include #include -#include "../main/42sh.h" +#include "../shell/shell.h" #include "../ast/ast.h" -#include "execution.h" +#include "exec.h" #include "../builtin/builtin.h" -#include "../var/var.h" -#include "../globbing/quoting.h" -#include "../history/history.h" -#include "../expand/expand.h" +/* #define rederror(prompt) do { perror(prompt); return 0; } while (0) */ -#define rederror(prompt) do { perror(prompt); return 0; } while (0) +/* struct s_reds_context */ +/* { */ +/* int old; */ +/* int save; */ +/* int end; */ +/* }; */ -struct s_reds_context -{ - int old; - int save; - int end; -}; -static void create_fork(struct s_cmd *cmd, struct s_42sh *sh); -static void launch_cmd(struct s_cmd *cmd); -static int apply_reds(struct s_redir **reds); -static void parse_prefix(char **prefix, int glob, struct s_42sh *s); -static struct s_reds_context *save_reds_context(struct s_redir **reds); -static void restore_reds_context(struct s_reds_context *context); -static int get_filedes(const char *txt); -static void cmd_debugger(struct s_cmd *cmd); +static int exec_forked(s_cmd_node *cmd); +static void exec_argv(char **argv); +static void exec_prefix(char **prefix, int glob); +static void cmd_debugger(s_cmd_node *cmd); -/*! -** Execute a command node -** -** @param cmd cmd to execute -** @param sh sh params -*/ -void exec_cmd(struct s_cmd *cmd, struct s_42sh *sh) +void exec_cmd(s_cmd_node *cmd) { - struct s_reds_context *context; - - assert(cmd && sh); + assert(cmd); if (DEBUG_EXEC) - cmd_debugger(cmd); - word_expansion(&cmd->argv, sh); - if (!cmd->argv) - { - parse_prefix(cmd->assign_words, 0, sh); - return; - } - if (is_a_builtin(cmd->argv[0], sh)) - { - context = save_reds_context(cmd->redirs); - if (!apply_reds(cmd->redirs)) - sh->last_status = RED_ERROR; - else - sh->last_status = exec_builtin(cmd, sh); - restore_reds_context(context); - free(context); + cmd_debugger(cmd); + //FIXME: expansions here + if (!cmd->argv) { + if (cmd->prefix) exec_prefix(cmd->prefix, 0); + return; } + if (is_a_builtin(cmd->argv[0])) + shell->status = exec_builtin(cmd); else - create_fork(cmd, sh); + shell->status = exec_forked(cmd); } -/*! -** Execute a command in a pipeline. This call preserve for too many system call fork -** Take care, this must be called after a fork -** -** @param cmd cmd to execute -** @param sh sh structure -*/ -void exec_piped_cmd(struct s_cmd *cmd, struct s_42sh *sh) +static int exec_forked(s_cmd_node *cmd) { - assert(cmd && sh); - if (DEBUG_EXEC) - cmd_debugger(cmd); - word_expansion(&cmd->argv, sh); - if (!apply_reds(cmd->redirs)) - exit(RED_ERROR); - if (is_a_builtin(cmd->argv[0], sh)) - sh->last_status = exec_builtin(cmd, sh); - else - { - parse_prefix(cmd->assign_words, 1, sh); - launch_cmd(cmd); - } -} + pid_t pid; + int status; -/*! -** Set redirection for builtin -** -** @param reds redirection informations -** -** @return save of all fd permutations -*/ -static struct s_reds_context *save_reds_context(struct s_redir **reds) -{ - struct s_reds_context *context; - register int i; - - for (i = 0; reds[i]; ++i) - ; - secmalloc(context, (i + 1) * sizeof (struct s_reds_context)); - for (i = 0; reds[i]; ++i) - { - context[i].old = reds[i]->fd; - context[i].save = dup(reds[i]->fd); - context[i].end = 0; - } - context[i].end = 1; - return context; -} - -static void restore_reds_context(struct s_reds_context *context) -{ - register int i; - - for (i = 0; !context[i].end; ++i) - dup2(context[i].save, context[i].old); -} - -/*! -** Manage fork enterpise for a command -** -** @param cmd command to execute -** @param sh shell struct -*/ -static void create_fork(struct s_cmd *cmd, struct s_42sh *sh) -{ - pid_t pid; - int status; - - if ((pid = fork()) == -1) - { - fprintf(stderr, "42sh: Cannot fork\n"); - sh->last_status = FORK_ERROR; - return; + if ((pid = fork()) == -1) { + fprintf(stderr, "%s: Cannot fork\n", shell->name); + return ERROR_FORK; } - if (pid) - { - waitpid(pid, &status, 0); - sh->last_status = WEXITSTATUS(status); - } - else - { - parse_prefix(cmd->assign_words, 1, sh); - if (!apply_reds(cmd->redirs)) - exit(RED_ERROR); - launch_cmd(cmd); + if (pid) { + waitpid(pid, &status, 0); + return WEXITSTATUS(status); } + if (cmd->prefix) + exec_prefix(cmd->prefix, 1); + exec_argv(cmd->argv); + assert(0); } -/*! -** Certify a correct changement of context -** -** @param cmd Execute a command -*/ -static void launch_cmd(struct s_cmd *cmd) +static void exec_argv(char **argv) { - execvp(cmd->argv[0], cmd->argv); + assert(argv && argv[0]); + execvp(argv[0], argv); if (errno == ENOENT) - if (strchr(cmd->argv[0], '/') == NULL) - fprintf(stderr, "42sh: %s: command not found\n", cmd->argv[0]); + if (strchr(argv[0], '/') == NULL) + fprintf(stderr, "%s: %s: command not found\n", shell->name, argv[0]); else - fprintf(stderr, "42sh: %s: No such file or directory\n", cmd->argv[0]); + fprintf(stderr, "%s: %s: No such file or directory\n", + shell->name, argv[0]); else - perror("42sh"); + perror(shell->name); exit((errno == ENOENT) ? 127 : 126); } -/*! -** Parse prefix of command, and set variable local or global. -** -** @param prefix assignment words list -** @param glob variable set is global only or local -** @param sh shell info -*/ -static void parse_prefix(char **prefix, int glob, struct s_42sh *sh) +static void exec_prefix(char **prefix, int glob) { - register int i; char *value; - if (!prefix) - return; - for (i = 0; prefix[i]; ++i) - { - if (!(value = strchr(prefix[i], '='))) - assert(0); - *value++ = 0; - if (glob) - var_setenv(prefix[i], value, !0); - else - var_set(sh->vars, prefix[i], value, !0); + assert(prefix); + for (int i = 0; prefix[i]; ++i) { + if (!(value = strchr(prefix[i], '='))) + assert(0); + *value++ = 0; + if (glob) + var_setenv(prefix[i], value, !0); + else + var_set(sh->vars, prefix[i], value, !0); } } -/*! -** Apply redirections whitout save of file descriptors -** -** @param reds list of redirections -*/ -static int apply_reds(struct s_redir **reds) -{ - int fd; - int i; - char *filename; - assert(reds); - for (i = 0; reds[i]; ++i) - { - switch (reds[i]->type) - { - case R_LESS: - if ((fd = open(reds[i]->file, O_RDONLY)) == -1) - rederror("42sh"); - dup2(fd, reds[i]->fd); - break; - case R_DLESSDASH: - case R_DLESS: - if ((fd = mkstemp(filename = strdup("42sh.heredocs.XXXXXX"))) == -1) - rederror("42sh"); - write(fd, reds[i]->file, strlen(reds[i]->file)); - lseek(fd, 0, SEEK_SET); - unlink(filename); - free(filename); - dup2(fd, STDIN_FILENO); - close(fd); - break; - case R_GREAT: - case R_CLOBBER: - if ((fd = open(reds[i]->file, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) - rederror("42sh"); - dup2(fd, reds[i]->fd); - break; - case R_DGREAT: - if ((fd = open(reds[i]->file, O_WRONLY | O_CREAT | O_APPEND, 0666)) == -1) - rederror("42sh"); - dup2(fd, reds[i]->fd); - break; - case R_GREATAND: - case R_LESSAND: - if ((fd = get_filedes(reds[i]->file)) == -1) - return 0; - if (fd == -2) - close(reds[i]->fd); - else - dup2(fd, reds[i]->fd); - break; - default: - return 0; - } - } - return 1; -} +/* /\*! */ +/* ** Execute a command in a pipeline. This call preserve for too many system call fork */ +/* ** Take care, this must be called after a fork */ +/* ** */ +/* ** @param cmd cmd to execute */ +/* ** @param sh sh structure */ +/* *\/ */ +/* void exec_piped_cmd(struct s_cmd *cmd, struct s_42sh *sh) */ +/* { */ +/* assert(cmd && sh); */ +/* if (DEBUG_EXEC) */ +/* cmd_debugger(cmd); */ +/* word_expansion(&cmd->argv, sh); */ +/* if (!apply_reds(cmd->redirs)) */ +/* exit(RED_ERROR); */ +/* if (is_a_builtin(cmd->argv[0], sh)) */ +/* sh->last_status = exec_builtin(cmd, sh); */ +/* else */ +/* { */ +/* parse_prefix(cmd->prefix, 1, sh); */ +/* launch_cmd(cmd); */ +/* } */ +/* } */ -/*! -** Retrieve an fd from and redirect words -** -** @param txt fd in string -** -** @return -1 if fail, -2 for close fd else fd -*/ -static int get_filedes(const char *txt) -{ - long fd; - char *endbuf; +/* /\*! */ +/* ** Set redirection for builtin */ +/* ** */ +/* ** @param reds redirection informations */ +/* ** */ +/* ** @return save of all fd permutations */ +/* *\/ */ +/* static struct s_reds_context *save_reds_context(struct s_redir **reds) */ +/* { */ +/* struct s_reds_context *context; */ +/* register int i; */ - assert(txt); - if (txt[0] == '-' && txt[1] == 0) - return -2; - fd = strtol(txt, &endbuf, 10); - if (endbuf == txt || *endbuf != 0) - { - fprintf(stderr, "42sh: %s: ambiguous redirect\n", txt); - return -1; - } - if (-1 == fcntl(fd, F_GETFL)) - { - endbuf = strmerges(2, "42sh: ", txt); - perror(endbuf); - free(endbuf); - return -1; - } - return 0; -} +/* for (i = 0; reds[i]; ++i) */ +/* ; */ +/* secmalloc(context, (i + 1) * sizeof (struct s_reds_context)); */ +/* for (i = 0; reds[i]; ++i) */ +/* { */ +/* context[i].old = reds[i]->fd; */ +/* context[i].save = dup(reds[i]->fd); */ +/* context[i].end = 0; */ +/* } */ +/* context[i].end = 1; */ +/* return context; */ +/* } */ + +/* static void restore_reds_context(struct s_reds_context *context) */ +/* { */ +/* register int i; */ + +/* for (i = 0; !context[i].end; ++i) */ +/* dup2(context[i].save, context[i].old); */ +/* } */ + + + + + +/* /\*! */ +/* ** Apply redirections whitout save of file descriptors */ +/* ** */ +/* ** @param reds list of redirections */ +/* *\/ */ +/* static int apply_reds(struct s_redir **reds) */ +/* { */ +/* int fd; */ +/* int i; */ +/* char *filename; */ + +/* assert(reds); */ +/* for (i = 0; reds[i]; ++i) */ +/* { */ +/* switch (reds[i]->type) */ +/* { */ +/* case R_LESS: */ +/* if ((fd = open(reds[i]->file, O_RDONLY)) == -1) */ +/* rederror("42sh"); */ +/* dup2(fd, reds[i]->fd); */ +/* break; */ +/* case R_DLESSDASH: */ +/* case R_DLESS: */ +/* if ((fd = mkstemp(filename = strdup("42sh.heredocs.XXXXXX"))) == -1) */ +/* rederror("42sh"); */ +/* write(fd, reds[i]->file, strlen(reds[i]->file)); */ +/* lseek(fd, 0, SEEK_SET); */ +/* unlink(filename); */ +/* free(filename); */ +/* dup2(fd, STDIN_FILENO); */ +/* close(fd); */ +/* break; */ +/* case R_GREAT: */ +/* case R_CLOBBER: */ +/* if ((fd = open(reds[i]->file, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) */ +/* rederror("42sh"); */ +/* dup2(fd, reds[i]->fd); */ +/* break; */ +/* case R_DGREAT: */ +/* if ((fd = open(reds[i]->file, O_WRONLY | O_CREAT | O_APPEND, 0666)) == -1) */ +/* rederror("42sh"); */ +/* dup2(fd, reds[i]->fd); */ +/* break; */ +/* case R_GREATAND: */ +/* case R_LESSAND: */ +/* if ((fd = get_filedes(reds[i]->file)) == -1) */ +/* return 0; */ +/* if (fd == -2) */ +/* close(reds[i]->fd); */ +/* else */ +/* dup2(fd, reds[i]->fd); */ +/* break; */ +/* default: */ +/* return 0; */ +/* } */ +/* } */ +/* return 1; */ +/* } */ + +/* /\*! */ +/* ** Retrieve an fd from and redirect words */ +/* ** */ +/* ** @param txt fd in string */ +/* ** */ +/* ** @return -1 if fail, -2 for close fd else fd */ +/* *\/ */ +/* static int get_filedes(const char *txt) */ +/* { */ +/* long fd; */ +/* char *endbuf; */ + +/* assert(txt); */ +/* if (txt[0] == '-' && txt[1] == 0) */ +/* return -2; */ +/* fd = strtol(txt, &endbuf, 10); */ +/* if (endbuf == txt || *endbuf != 0) */ +/* { */ +/* fprintf(stderr, "42sh: %s: ambiguous redirect\n", txt); */ +/* return -1; */ +/* } */ +/* if (-1 == fcntl(fd, F_GETFL)) */ +/* { */ +/* endbuf = strmerges(2, "42sh: ", txt); */ +/* perror(endbuf); */ +/* free(endbuf); */ +/* return -1; */ +/* } */ +/* return 0; */ +/* } */ /*! ** Debug execution ** ** @param cmd command */ -static void cmd_debugger(struct s_cmd *cmd) +static void cmd_debugger(s_cmd_node *cmd) { int i; @@ -315,13 +270,13 @@ static void cmd_debugger(struct s_cmd *cmd) fprintf(stderr, "exec command\n"); for (i = 0; cmd->argv && cmd->argv[i]; ++i) fprintf(stderr, "argv[%d] : %-15s\n", i, cmd->argv[i]); - for (i = 0; cmd->assign_words && cmd->assign_words[i]; ++i) - fprintf(stderr, "prefix[%d] : %-15s\n", i, cmd->assign_words[i]); - for (i = 0; cmd->redirs && cmd->redirs[i]; ++i) - { - fprintf(stderr, "reds[%d] : type : %d\n", i, cmd->redirs[i]->type); - fprintf(stderr, " : fd : %d\n", cmd->redirs[i]->fd); - fprintf(stderr, " : file : %s\n", cmd->redirs[i]->file); + for (i = 0; cmd->prefix && cmd->prefix[i]; ++i) + fprintf(stderr, "prefix[%d] : %-15s\n", i, cmd->prefix[i]); +/* for (i = 0; cmd->redirs && cmd->redirs[i]; ++i) */ +/* { */ +/* fprintf(stderr, "reds[%d] : type : %d\n", i, cmd->redirs[i]->type); */ +/* fprintf(stderr, " : fd : %d\n", cmd->redirs[i]->fd); */ +/* fprintf(stderr, " : file : %s\n", cmd->redirs[i]->file); */ } fprintf(stderr, "-----------------------------------\n"); } diff --git a/src/parser/alias.c b/src/parser/alias.c index 14420ef..53cd370 100644 --- a/src/parser/alias.c +++ b/src/parser/alias.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Wed Aug 23 00:39:17 2006 Seblu -** Last update Mon Aug 28 23:08:31 2006 Seblu +** Last update Tue Nov 14 15:34:32 2006 seblu */ #include @@ -14,20 +14,20 @@ static size_t step = 5; -s_aliases *alias_init(void) +s_alias *alias_init(void) { - s_aliases *new; + s_alias *new; - secmalloc(new, sizeof (s_aliases)); + secmalloc(new, sizeof (s_alias)); new->size = step; new->pos = 0; new->db = NULL; return new; } -void alias_add(s_aliases *aliases, const char *name, const char *value) +void alias_add(s_alias *aliases, const char *name, const char *value) { - s_alias *new; + s_alias_item *new; int freeplace = 0; size_t index; @@ -47,19 +47,19 @@ void alias_add(s_aliases *aliases, const char *name, const char *value) return; } //create a new one - secmalloc(new, sizeof (s_alias)); + secmalloc(new, sizeof (s_alias_item)); 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 (s_alias)); + secrealloc(aliases->db, aliases->db, aliases->size * sizeof (s_alias_item)); } aliases->db[aliases->pos] = new; ++aliases->pos; } -int alias_remove(s_aliases *aliases, const char *name) +int alias_remove(s_alias *aliases, const char *name) { //find alias index for (register int i = 0; aliases && aliases->db[i]; ++i) diff --git a/src/parser/alias.h b/src/parser/alias.h index ab2f9f8..637244f 100644 --- a/src/parser/alias.h +++ b/src/parser/alias.h @@ -5,7 +5,7 @@ ** Login ** ** Started on Wed Aug 23 00:32:09 2006 Seblu -** Last update Mon Aug 28 23:07:38 2006 Seblu +** Last update Tue Nov 14 15:32:55 2006 seblu */ #ifndef ALIAS_H_ @@ -13,25 +13,25 @@ # include -typedef struct alias +typedef struct alias_item { char *name; char *value; -} s_alias; +} s_alias_item; -typedef struct aliases +typedef struct alias { size_t size; size_t pos; - s_alias **db; -} s_aliases; + s_alias_item **db; +} s_alias; /*! ** Create a new aliases database ** ** @return new alias database */ -s_aliases *alias_init(void); +s_alias *alias_init(void); /*! ** Add an alias into an alias database @@ -40,7 +40,7 @@ s_aliases *alias_init(void); ** @param name new alias name ** @param value new alias value */ -void alias_add(s_aliases *aliases, const char *name, const char *value); +void alias_add(s_alias *aliases, const char *name, const char *value); /*! ** Remove an alias into an alias database @@ -50,6 +50,6 @@ void alias_add(s_aliases *aliases, const char *name, const char *value); ** ** @return true, if alias was found in database, else false */ -int alias_remove(s_aliases *aliases, const char *name); +int alias_remove(s_alias *aliases, const char *name); #endif diff --git a/src/parser/lexer.c b/src/parser/lexer.c index a8eb485..ad1b47a 100644 --- a/src/parser/lexer.c +++ b/src/parser/lexer.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Sun Jul 30 04:36:53 2006 Seblu -** Last update Sun Nov 12 03:11:19 2006 seblu +** Last update Tue Nov 14 15:38:16 2006 seblu */ #include @@ -15,7 +15,7 @@ #include "parser.h" #include "../shell/shell.h" #include "getline.h" -#include "../common/common.h" +#include "../common/function.h" #include "../common/macro.h" /* diff --git a/src/parser/parser.c b/src/parser/parser.c index f9cbc97..7185685 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Wed Aug 2 00:56:07 2006 Seblu -** Last update Sun Nov 12 02:58:03 2006 seblu +** Last update Tue Nov 14 15:38:06 2006 seblu */ @@ -17,7 +17,7 @@ #include #include "parser.h" #include "../common/macro.h" -#include "../common/common.h" +#include "../common/function.h" #include "../shell/shell.h" #include "getline.h" diff --git a/src/shell/func.c b/src/shell/func.c new file mode 100644 index 0000000..1d0372f --- /dev/null +++ b/src/shell/func.c @@ -0,0 +1,36 @@ +/* +** func.c for 42sh +** +** Made by seblu +** Login +** +** Started on Tue Nov 14 14:52:39 2006 seblu +** Last update Tue Nov 14 15:59:57 2006 seblu +*/ + +/* +** ============ +** DECLARATIONS +** ============ +*/ + +#include +#include "func.h" +#include "../common/macro.h" + +/* +** =========== +** DEFINITIONS +** =========== +*/ + +s_func *func_init(void) +{ + s_func *new; + + secmalloc(new, sizeof (s_func)); + new->count = 0; + new->size = FUNC_DEFAULT_SIZE; + secmalloc(new->table, new->size * sizeof (s_func_item)); + return new; +} diff --git a/src/shell/func.h b/src/shell/func.h new file mode 100644 index 0000000..4f1c8f0 --- /dev/null +++ b/src/shell/func.h @@ -0,0 +1,46 @@ +/* +** func.h for 42sh +** +** Made by seblu +** Login +** +** Started on Tue Nov 14 14:52:22 2006 seblu +** Last update Tue Nov 14 15:59:32 2006 seblu +*/ + +#ifndef FUNC_H_ +# define FUNC_H_ + +# include +# include +# include "../ast/ast.h" + +enum { FUNC_DEFAULT_SIZE = 5 }; + +typedef struct func_item +{ + char *name; + s_ast_node *body; +} s_func_item; + +typedef struct func +{ + s_func_item *table; + size_t count; + size_t size; +} s_func; + +/*! +** Init a function structure. +** +** @return a malloced func structure +*/ +s_func *func_init(void); + +/* int func_add(char *, struct s_ast *, struct s_func **); */ +/* int func_del(const char *, struct s_func **); */ +/* int func_exec(const char *, struct s_42sh *); */ +/* void func_clean(struct s_func **); */ +/* struct s_ast *func_get(const char *, struct s_func **); */ + +#endif diff --git a/src/shell/getoptions.c b/src/shell/getoptions.c index 58ca9ca..8d9d316 100644 --- a/src/shell/getoptions.c +++ b/src/shell/getoptions.c @@ -5,14 +5,14 @@ ** Login ** ** Started on Sun Jul 30 03:28:26 2006 Seblu -** Last update Mon Sep 25 02:52:45 2006 Seblu +** Last update Tue Nov 14 15:38:32 2006 seblu */ #include #include #include "option.h" #include "shell.h" -#include "../common/common.h" +#include "../common/function.h" /*! ** Parse the command line @@ -21,7 +21,7 @@ ** @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_option *opt, int argc, char **argv) { #if DEBUG_OPTION == 1 printf("* Option Parser\n"); @@ -41,7 +41,7 @@ void getoptions(s_options *opt, int argc, char **argv) break; } else if (!strcmp(copt, "--ast-print")) - option_set(shell->options, "ast_print"); + option_set(shell->option, "ast_print"); else { printf("Error: Invalid option %s\n", copt); exit(1); diff --git a/src/shell/option.c b/src/shell/option.c index 47749a1..5c352b3 100644 --- a/src/shell/option.c +++ b/src/shell/option.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Tue Mar 21 19:00:38 2006 Seblu -** Last update Sun Nov 12 20:11:40 2006 Seblu +** Last update Tue Nov 14 20:30:23 2006 seblu */ /* @@ -19,16 +19,16 @@ #include "../shell/shell.h" #include "../common/macro.h" -static const char *opts_table[NBR_OPTION] = - { - "xpg_echo", - "dotglob", - "extglob", - "nocaseglob", - "nullglob", - "expand_aliases", - "ast_print", - }; +static const char *opts_table[OPTION_COUNT] = { + "xpg_echo", + "dotglob", + "extglob", + "nocaseglob", + "nullglob", + "expand_aliases", + "ast_print", + "readline", +}; /* ** =========== @@ -36,30 +36,38 @@ static const char *opts_table[NBR_OPTION] = ** =========== */ -s_options *option_init(void) +s_option *option_init(void) { - s_options *new; + s_option *new; - secmalloc(new, sizeof (s_options)); + secmalloc(new, sizeof (s_option)); new->command = NULL; //FIXME: item is uninitialized! Do it here return new; } -int option_set(s_options *shopt, const char *name) +void option_set_default(s_option *shopt) +{ + //unset all + for (int i = 0; i < OPTION_COUNT; ++i) + shopt->item[i] = 0; + //set those which are on by default + option_set(shopt, "readline"); +} + +int option_set(s_option *shopt, const char *name) { register int i; for (i = 0; opts_table[i]; ++i) - if (!strcmp(name, opts_table[i])) - { + if (!strcmp(name, opts_table[i])) { shopt->item[i] = 1; return 1; } return 0; } -int option_unset(s_options *shopt, const char *name) +int option_unset(s_option *shopt, const char *name) { register int i; @@ -72,7 +80,7 @@ int option_unset(s_options *shopt, const char *name) return 0; } -int option_isset(const s_options *shopt, const char *name) +int option_isset(const s_option *shopt, const char *name) { register int i; diff --git a/src/shell/option.h b/src/shell/option.h index 9df1f9d..7a56648 100644 --- a/src/shell/option.h +++ b/src/shell/option.h @@ -5,21 +5,21 @@ ** Login ** ** Started on Tue Mar 21 18:50:03 2006 Seblu -** Last update Wed Aug 30 00:19:19 2006 Seblu +** Last update Tue Nov 14 15:29:08 2006 seblu */ #ifndef OPTION_H_ # define OPTION_H_ -#define NBR_OPTION 9 - #define DEBUG_OPTION 0 -typedef struct options +enum { OPTION_COUNT = 9 }; + +typedef struct option { - signed char item[NBR_OPTION]; + signed char item[OPTION_COUNT]; char *command; -} s_options; +} s_option; /* ** ============== @@ -32,7 +32,14 @@ typedef struct options ** ** @return A new options structure */ -s_options *option_init(void); +s_option *option_init(void); + +/*! +** Set default shell options +** +** @param opt option struct +*/ +void option_set_default(s_option *shopt); /*! ** Set a shell option @@ -42,7 +49,7 @@ s_options *option_init(void); ** ** @return 0 on failure, else 1 */ -int option_set(s_options *shopt, const char *name); +int option_set(s_option *shopt, const char *name); /*! ** Unset a shell option @@ -52,7 +59,7 @@ int option_set(s_options *shopt, const char *name); ** ** @return 0 on failure, else 1 */ -int option_unset(s_options *shopt, const char *name); +int option_unset(s_option *shopt, const char *name); /*! ** Tell if an option is set. if option nane is not set return -1 @@ -62,7 +69,7 @@ int option_unset(s_options *shopt, const char *name); ** ** @return 0 if unset, 1 if set and -1 if not exist */ -int option_isset(const s_options *shopt, const char *name); +int option_isset(const s_option *shopt, const char *name); /*! ** Return a list of know opt @@ -84,6 +91,6 @@ const char **opt_get(); ** @param argc program argc ** @param argv program argv */ -void getoptions(s_options *opt, int argc, char **argv); +void getoptions(s_option *opt, int argc, char **argv); #endif diff --git a/src/shell/shell.c b/src/shell/shell.c new file mode 100644 index 0000000..88465b4 --- /dev/null +++ b/src/shell/shell.c @@ -0,0 +1,103 @@ +/* +** shell.c for 42sh +** +** Made by Seblu +** Login +** +** Started on Mon Apr 10 23:57:28 2006 Seblu +** Last update Tue Nov 14 15:46:38 2006 seblu +*/ + +#include +#include "shell.h" +#include "option.h" +#include "../ast/ast.h" +#include "../parser/parser.h" +#include "../exec/exec.h" +#include "../common/macro.h" +#include "../common/function.h" + +/* +** ============ +** DECLARATIONS +** ============ +*/ + +/* +** Global shell structure +*/ +s_shell *shell = NULL; + +/*! +** Program entry point +** +** @param argc Argument count +** @param argv Argument vector +** +** @return return program value +*/ +int main(int argc, char *argv[]); + +/*! +** Initialize a shell structure +** +** @param path path of the current shell +** +** @return an initialized shell structure +*/ +s_shell *shell_init(void); + +/* +** =========== +** DEFINITIONS +** =========== +*/ + +int main(int argc, char *argv[]) +{ + s_ast_node *ast; + s_parser *parser; + + // shell initialization + shell = shell_init(); + // Set shell name + shell->name = basename(argv[0]); + // Set default option + option_set_default(shell->option); + // parse argv for user options + getoptions(shell->option, argc, argv); + //FIXME: set PWD et OLDPWD variable + // shell parser init + parser = parser_init(STDIN_FILENO); + // parse and execute stdin stream + do { + ast = parse(parser); + if (parser->error && isinteractive()) + continue; + else if (parser->error) + return ERROR_PARSE; + if (option_isset(shell->option, "ast_print")) + ast_print(ast, NULL); + if (ast) + exec_node(ast); + ast_destruct(ast); + } + while (!parser->lexer->eof); + if (isinteractive()) + fprintf(stderr, "exit\n"); + return shell->status; +} + +s_shell *shell_init(void) +{ + s_shell *new; + + secmalloc(new, sizeof (s_shell)); + new->var = var_init(); + new->func = func_init(); + new->alias = alias_init(); + new->option = option_init(); + new->name = "42sh"; + new->status = 0; + return new; +} diff --git a/src/shell/shell.h b/src/shell/shell.h index 079c00a..43d45f1 100644 --- a/src/shell/shell.h +++ b/src/shell/shell.h @@ -1,11 +1,11 @@ /* -** shell.h for 42sh in /home/seblu/devel/c/42sh +** shell.h for 42sh ** ** Made by Seblu ** Login ** ** Started on Sun Jul 16 20:03:53 2006 Seblu -** Last update Tue Oct 17 09:38:57 2006 seblu +** Last update Tue Nov 14 15:30:52 2006 seblu */ #ifndef SHELL_H_ @@ -15,22 +15,20 @@ # include # include "../common/constant.h" # include "../parser/alias.h" +# include "var.h" # include "option.h" +# include "func.h" -typedef struct shell +typedef struct shell { -/* struct s_var *vars; */ -/* struct s_func *funcs; */ -/* struct s_history *history; */ - s_aliases *aliases; - s_options *options; + s_var *var; + s_func *func; + s_alias *alias; + s_option *option; char *name; int status; } s_shell; -s_shell *shell_init(const char *argv0); -void shell_destroy(s_shell *sh); - const char *get_prompt(e_prompt pty); /*! diff --git a/src/shell/shell_destroy.c b/src/shell/shell_destroy.c deleted file mode 100644 index 2422084..0000000 --- a/src/shell/shell_destroy.c +++ /dev/null @@ -1,29 +0,0 @@ -/* -** sh_destroy.c for 42sh in /home/seblu/devel/c++/tiger -** -** Made by Seblu -** Login -** -** Started on Fri Apr 7 00:19:04 2006 Seblu -** Last update Tue Aug 29 00:31:48 2006 Seblu -*/ - -#include -#include -#include "shell.h" - - -/*! -** Destroy 42SH structure. -** -** @param sh structure to destroy -** -*/ -void shell_destroy(s_shell *sh) -{ - assert(sh); -/* var_delete(&sh->vars); */ -/* func_clean(&sh->funcs); */ -/* free(sh->opt); */ - free(sh); -} diff --git a/src/shell/shell_entry.c b/src/shell/shell_entry.c deleted file mode 100644 index 4d44829..0000000 --- a/src/shell/shell_entry.c +++ /dev/null @@ -1,62 +0,0 @@ -/* -** main.c for 42sh -** -** Made by Seblu -** Login -** -** Started on Mon Apr 10 23:57:28 2006 Seblu -** Last update Sun Nov 12 16:38:29 2006 Seblu -*/ - -#include -#include -#include "shell.h" -#include "option.h" -#include "../ast/ast.h" -#include "../parser/parser.h" -#include "../exec/exec.h" -#include "../common/macro.h" - -/* -** Global shell structure -*/ -s_shell *shell = NULL; - -/*! -** Program entry point -** -** @param argc Argument count -** @param argv Argument vector -** -** @return return program value -*/ -int main(int argc, char *argv[]) -{ - s_ast_node *ast; - s_parser *parser; - - // shell initialization - shell = shell_init(argv[0]); - // parse argv - getoptions(shell->options, argc, argv); - // shell parser init - parser = parser_init(STDIN_FILENO); - // parse and execute stdin stream - do - { - ast = parse(parser); - if (parser->error && isinteractive()) - continue; - else if (parser->error) - return ERROR_PARSE; - if (option_isset(shell->options, "ast_print")) - ast_print(ast, NULL); - if (ast) - exec_node(ast); - ast_destruct(ast); - } - while (!parser->lexer->eof); - if (isinteractive()) - fprintf(stderr, "exit\n"); - return shell->status; -} diff --git a/src/shell/shell_init.c b/src/shell/shell_init.c deleted file mode 100644 index ae3fe0f..0000000 --- a/src/shell/shell_init.c +++ /dev/null @@ -1,90 +0,0 @@ -/* -** shell_init.c for 42sh -** -** Made by Seblu -** Login -** -** Started on Sun Jul 16 20:11:09 2006 Seblu -** Last update Tue Aug 29 00:55:19 2006 Seblu -*/ - -#include -#include -#include -#include -#include -#include -#include "shell.h" -#include "option.h" -#include "../common/macro.h" -#include "../common/common.h" - - -/* static int pwd_isgood(); */ -/* static void set_default_option(struct s_opt *); */ - -/*! -** Create shell structure -** -** @return the new shell structure -*/ -s_shell *shell_init(const char *argv0) -{ - s_shell *new; - - secmalloc(new, sizeof (s_shell)); -/* new->vars = NULL; */ -/* new->funcs = NULL; */ -/* new->history = NULL; */ - new->aliases = alias_init(); - new->options = option_init(); -/* if (!pwd_isgood()) */ -/* { */ -/* var_setenv("PWD", (tmp = var_getcwd()), 1); */ -/* free(tmp); */ -/* } */ -/* var_unsetenv("OLDPWD"); */ - new->name = basename(argv0); - new->status = 0; - return new; -} - -/*! -** Default sh option -** -*/ -/* static void set_default_option(struct s_opt *opt) */ -/* { */ -/* opt_unset("xpg_echo", opt); */ -/* opt_unset("dotglob", opt); */ -/* opt_unset("extglob", opt); */ -/* opt_unset("nocaseglob", opt); */ -/* opt_unset("expand_aliases", opt); */ -/* opt_unset("bonus", opt); */ -/* opt_unset("readline", opt); */ -/* } */ - -/*! -** Check if pwd, if set on the current directory -** -** @return bool satus -*/ -/* static int pwd_isgood() */ -/* { */ -/* char *pwd; */ -/* struct stat s_pwd; */ -/* ino_t ino_pwd; */ - -/* pwd = getenv("PWD"); */ -/* if (stat(pwd, &s_pwd) == -1) */ -/* return 0; */ -/* ino_pwd = s_pwd.st_ino; */ -/* pwd = var_getcwd(); */ -/* if (stat(pwd, &s_pwd) == -1) */ -/* { */ -/* perror("42sh"); */ -/* exit(1); */ -/* } */ -/* free(pwd); */ -/* return ino_pwd == s_pwd.st_ino; */ -/* } */ diff --git a/src/shell/var.c b/src/shell/var.c new file mode 100644 index 0000000..ef85790 --- /dev/null +++ b/src/shell/var.c @@ -0,0 +1,144 @@ +/* +** var.c for 42sh +** +** Made by seblu +** Login +** +** Started on Tue Nov 14 13:55:46 2006 seblu +** Last update Tue Nov 14 16:25:06 2006 seblu +*/ + +#include +#include +#include +#include "var.h" +#include "../common/macro.h" +#include "../common/function.h" + +s_var *var_init(void) +{ + s_var *var; + + secmalloc(var, sizeof (s_var)); + var->count = 0; + var->size = VAR_DEFAULT_SIZE; + secmalloc(var->table, var->size * sizeof (s_var_item)); + return var; +} + +const char *var_get(const s_var *var, const char *name) +{ + const char *res; + + assert(name && var); + if ((res = getenv(name))) + return res; + for (size_t i = 0; i < var->count; ++i) { + if (!(var->table[i].name)) + continue; + if (!strcmp(var->table[i].name, name)) + return var->table[i].value; + } + return NULL; +} + +void var_set(s_var *var, + char *name, + char *value, + int env, + int overwrite) +{ + assert(0); var = var; name = value; env = overwrite; +/* size_t i; */ +/* int pos = -1; */ + +/* if (getenv(name)) { */ +/* setenv2(name, value, overwrite); */ +/* return; */ +/* } */ +/* for (i = 0; i < var->count; ++i) */ +/* { */ +/* if (!(var->table[i].name)) */ +/* pos = i; */ +/* else */ +/* if (!strcmp(var->table[i].name, name)) */ +/* break; */ +/* } */ +/* if (i < var->count) */ +/* set_exist_var(var, value, overwrite, i); */ +/* else */ +/* if (pos != -1) */ +/* set_non_exist_var(var, value, name, pos); */ +/* else */ +/* add_var(var, name, value); */ +} + +int var_unset(s_var *var, const char *name) +{ + assert(var && name); +/* if (getenv(name)) { */ +/* var_unsetenv(name); */ +/* return 0; */ +/* } */ +/* for (i = 0; i < var->len_var; ++i) */ +/* { */ +/* if (!(var->tab_var[i].name)) */ +/* continue; */ +/* if (!strcmp(var->tab_var[i].name, name)) */ +/* { */ +/* free(var->tab_var[i].name); */ +/* free(var->tab_var[i].value); */ +/* var->tab_var[i].name = NULL; */ +/* var->tab_var[i].value = NULL; */ +/* return 0; */ +/* } */ +/* } */ + return 1; +} + +/* static void add_var(struct s_var *var, */ +/* const char *name, */ +/* const char *value) */ +/* { */ +/* struct s_local_var *new_buff; */ + +/* if (var->len_var >= var->size) */ +/* { */ +/* var->size += 50; */ +/* secrealloc(new_buff, var->tab_var, sizeof (struct s_local_var) * var->size); */ +/* free(var->tab_var); */ +/* var->tab_var = new_buff; */ +/* } */ +/* secstrdup(var->tab_var[var->len_var].name, name); */ +/* secstrdup(var->tab_var[var->len_var].value, value); */ +/* ++var->len_var; */ +/* } */ + +/* static void set_exist_var(struct s_var *var, */ +/* const char *value, */ +/* char perm, */ +/* unsigned int i) */ +/* { */ +/* if (!perm) */ +/* return; */ +/* free(var->tab_var[i].value); */ +/* secstrdup(var->tab_var[i].value, value); */ +/* } */ + +/* static void set_non_exist_var(struct s_var *var, */ +/* const char *value, */ +/* const char *name, */ +/* unsigned int i) */ +/* { */ +/* secstrdup(var->tab_var[i].name, name); */ +/* secstrdup(var->tab_var[i].value, value); */ +/* } */ + +void var_print(const s_var *var) +{ + for (size_t i = 0; i < var->count; ++i) { + if (!(var->table[i].name)) + continue; + printf("%s=%s\n", var->table[i].name, var->table[i].value); + } +} diff --git a/src/shell/var.h b/src/shell/var.h new file mode 100644 index 0000000..3a95641 --- /dev/null +++ b/src/shell/var.h @@ -0,0 +1,69 @@ +/* +** var.h for 42sh +** +** Made by seblu +** Login +** +** Started on Tue Nov 14 13:54:14 2006 seblu +** Last update Tue Nov 14 15:26:09 2006 seblu +*/ + +#ifndef VAR_H_ +# define VAR_H_ + +# include + +enum { VAR_DEFAULT_SIZE = 25 }; + +typedef struct var_item +{ + char *value; + char *name; +} s_var_item; + +/*! +** The variable structure +** - table: The table of variables +** - count: The number of variables +** - size: The size of the table (mem alloced) +*/ +typedef struct var +{ + s_var_item *table; + size_t count; + size_t size; +} s_var; + +/*! +** Create a malloced variable structure +** +** @return new variable structure +*/ +s_var *var_init(void); + +/*! +** Get a variable in a var struct +** +** @param var variable struct +** @param name variable name +** +** @return value of the variable, NULL if not exist +*/ +const char *var_get(const s_var *var, const char *name); + + +void var_set(s_var *var, + char *name, + char *value, + int env, + int overwrite); + +/*! +** Print all variables on standard output +** +** @param var var struct +*/ +void var_print(const s_var *var); + + +#endif /* ! VAR_H_ */ -- GitLab