Author | Jamozed <[email protected]> |
Date | 2021-09-11 11:19:36 |
Commit | de472f3d6ef1bb1c9594755d2c900bc95d959912 |
Parent | 30bbeefe64d845ddc2dadda0fbe7dac5aed33a01 |
Reimplement command evaluation
Diffstat
M | src/alias.c | | | 2 | +- |
M | src/alias.h | | | 2 | +- |
M | src/bltn.c | | | 26 | +++++++++++++++----------- |
M | src/bltn.h | | | 2 | +- |
M | src/bltns/cd.c | | | 8 | +++----- |
A | src/bltns/eval.c | | | 87 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | src/bltns/pwd.c | | | 10 | ++++------ |
M | src/bltns/set.c | | | 4 | +--- |
M | src/esh.h | | | 18 | ++++++++++++------ |
A | src/eval.c | | | 71 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | src/exec.c | | | 16 | +++++++++------- |
M | src/main.c | | | 34 | ++++++++++++---------------------- |
M | src/parse.c | | | 24 | ++++++++++++------------ |
13 files changed, 229 insertions, 75 deletions
diff --git a/src/alias.c b/src/alias.c index ffddd28..a518672 100644 --- a/src/alias.c +++ b/src/alias.c @@ -60,7 +60,7 @@ void pushalias(akas_t *akas, aka_t aka) { return; } -int bltn_alias(char *argv[]) { +int bltn_alias(int ac, char *argv[]) { if (!argv[1]) { for (aka_t *a = akas.dat; a->str; ++a) { printf("alias %s='%s'\n", a->str, a->com); } return 0; } diff --git a/src/alias.h b/src/alias.h index 9e5a8a6..c18eabe 100644 --- a/src/alias.h +++ b/src/alias.h @@ -43,6 +43,6 @@ extern void initalias(void); extern void freealias(void); extern void pushalias(akas_t *akas, aka_t aka); -extern int bltn_alias(char *argv[]); +extern int bltn_alias(int ac, char *argv[]); #endif // ESH_ALIAS_H_0BXOPDLM diff --git a/src/bltn.c b/src/bltn.c index f5d8688..c854294 100644 --- a/src/bltn.c +++ b/src/bltn.c @@ -39,17 +39,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. #include <stdio.h> -static int bltn_eval(char *av[]) { warn("eval: Unimplemented"); return -1; } -static int bltn_exit(char *av[]) { (void)(av); _loop = 0; return 0; } -static int bltn_false(char *av[]) { (void)(av); return 1; } -static int bltn_help(char *av[]); -static int bltn_true(char *av[]) { (void)(av); return 0; } +static int bltn_exit(int ac, char *av[]) { _loop = 0; return 0; } +static int bltn_false(int ac, char *av[]) { return 1; } +static int bltn_help(int ac, char *av[]); +static int bltn_true(int ac, char *av[]) { return 0; } -extern int bltn_cd(char *av[]); -extern int bltn_pwd(char *av[]); -extern int bltn_set(char *av[]); +extern int bltn_cd(int ac, char *av[]); +extern int bltn_eval(int ac, char *av[]); +extern int bltn_pwd(int ac, char *av[]); +extern int bltn_set(int ac, char *av[]); -static int getret(char *av[]) { printf("%i\n", _ret); return 0; } +static int getret(int ac, char *av[]) { printf("%i\n", _ret); return 0; } struct bltn bltns[] = { {"alias", &bltn_alias}, @@ -65,6 +65,10 @@ struct bltn bltns[] = { {NULL, NULL} }; -static int bltn_help(char *av[]) { (void)(av); - puts("ESH, version " PROJECT_VERSION); return 0; +static int bltn_help(int ac, char *av[]) { + puts("ESH, version " PROJECT_VERSION); + puts("Copyright (C) 2020, Jakob Wakeling"); + puts("All rights reserved."); + puts("OMKOV Permissive Licence (https://www.omkov.net/OLPE)"); + return 0; } diff --git a/src/bltn.h b/src/bltn.h index 3c461ca..4e811dc 100644 --- a/src/bltn.h +++ b/src/bltn.h @@ -33,7 +33,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. #ifndef OMKOV_ESH_BLTN_H_XQ5D812A #define OMKOV_ESH_BLTN_H_XQ5D812A -struct bltn { const char *s; int (*f)(char *[]); }; +struct bltn { const char *s; int (*f)(int, char *[]); }; extern struct bltn bltns[]; #endif // OMKOV_ESH_BLTN_H_XQ5D812A diff --git a/src/bltns/cd.c b/src/bltns/cd.c index 1d35d99..3c20798 100644 --- a/src/bltns/cd.c +++ b/src/bltns/cd.c @@ -1,4 +1,4 @@ -// cd.c, version 0.1.1 +// cd.c // cd builtin source file for ESH // Copyright (C) 2020, Jakob Wakeling // All rights reserved. @@ -39,8 +39,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. #include <stdlib.h> #include <string.h> -#define VERSION "0.1.1" - static struct lop lops[] = { { "help", ARG_NUL, 256 }, { "version", ARG_NUL, 257 }, @@ -52,7 +50,7 @@ static int mode = 0; static void hlp(void); static void ver(void); -int bltn_cd(char *av[]) { +int bltn_cd(int ac, char *av[]) { struct opt opt = OPTGET_INIT; opt.str = "LP"; opt.lops = lops; for (int o; (o = optget(&opt, av, 1)) != -1;) switch (o) { case 'L': { mode = 0; break; } @@ -85,7 +83,7 @@ static void hlp(void) { } static void ver(void) { - puts("ESH cd, version " VERSION); + puts("ESH, version " PROJECT_VERSION); puts("Copyright (C) 2020, Jakob Wakeling"); puts("All rights reserved."); puts("OMKOV Permissive Licence (https://www.omkov.net/OLPE)"); diff --git a/src/bltns/eval.c b/src/bltns/eval.c new file mode 100644 index 0000000..778bf7e --- /dev/null +++ b/src/bltns/eval.c @@ -0,0 +1,87 @@ +// eval.c +// eval builtin source file for ESH +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#include "../esh.h" +#include "../util/util.h" + +#include "../cll/optget.h" + +#include <stdio.h> +#include <string.h> + +static struct lop lops[] = { + { "help", ARG_NUL, 256 }, + { "version", ARG_NUL, 257 }, + { NULL, 0, 0 } +}; + +static void hlp(void); +static void ver(void); + +int bltn_eval(int ac, char *av[]) { + struct opt opt = OPTGET_INIT; opt.str = ""; opt.lops = lops; + for (int o; (o = optget(&opt, av, 1)) != -1;) switch (o) { + case 256: { hlp(); return 0; } + case 257: { ver(); return 0; } + default: { return 1; } + } + + u8 *args, *dest; UINT size = 0; + + for (UINT i = 0; i != ac - opt.ind; i += 1) { + size += (strlen(av[opt.ind + i]) + 1); + } + + args = assert_calloc(size, sizeof (*args)); dest = args; + + for (UINT i = 0; i != ac - opt.ind; i += 1) { + if (i != 0) { strncat((char *)dest, " ", 1); dest += 1; } + strcat((char *)dest, av[opt.ind + i]); dest += strlen(av[opt.ind + i]); + } + + eval(args, size); return 0; +} + +static void hlp(void) { + puts("eval - Execute arguments as a command\n"); + puts("Usage: eval [argument...]\n"); + puts("Options:"); + puts(" --help Display help information"); + puts(" --version Display version information"); +} + +static void ver(void) { + puts("ESH, version " PROJECT_VERSION); + puts("Copyright (C) 2020, Jakob Wakeling"); + puts("All rights reserved."); + puts("OMKOV Permissive Licence (https://www.omkov.net/OLPE)"); +} diff --git a/src/bltns/pwd.c b/src/bltns/pwd.c index 615e9e3..6ae9fe9 100644 --- a/src/bltns/pwd.c +++ b/src/bltns/pwd.c @@ -1,5 +1,5 @@ -// pwd.c, version 1.0.1b -// OMKOV coreutils pwd adapted as an ESH builtin +// pwd.c +// pwd builtin source file for ESH // Copyright (C) 2020, Jakob Wakeling // All rights reserved. @@ -37,8 +37,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. #include <stdio.h> #include <stdlib.h> -#define VERSION "1.0.1b" - static struct lop lops[] = { { "help", ARG_NUL, 256 }, { "version", ARG_NUL, 257 }, @@ -50,7 +48,7 @@ static int mode = 0; static void hlp(void); static void ver(void); -int bltn_pwd(char *av[]) { +int bltn_pwd(int ac, char *av[]) { struct opt opt = OPTGET_INIT; opt.str = "LP"; opt.lops = lops; for (int o; (o = optget(&opt, av, 1)) != -1;) switch (o) { case 'L': { mode = 0; break; } @@ -82,7 +80,7 @@ static void hlp(void) { } static void ver(void) { - puts("OMKOV coreutils pwd, version " VERSION); + puts("ESH, version " PROJECT_VERSION); puts("Copyright (C) 2020, Jakob Wakeling"); puts("All rights reserved."); puts("OMKOV Permissive Licence (https://www.omkov.net/OLPE)"); diff --git a/src/bltns/set.c b/src/bltns/set.c index 48fffbf..36ec030 100644 --- a/src/bltns/set.c +++ b/src/bltns/set.c @@ -46,12 +46,10 @@ static struct lop lops[] = { { NULL, 0, 0 } }; -static int mode = 0; - static void hlp(void); static void ver(void); -int bltn_set(char *av[]) { +int bltn_set(int ac, char *av[]) { struct opt opt = OPTGET_INIT; opt.str = ""; opt.lops = lops; for (int o; (o = optget(&opt, av, 1)) != -1;) switch (o) { case 256: { hlp(); return 0; } diff --git a/src/esh.h b/src/esh.h index 86d0dd9..592fd5d 100644 --- a/src/esh.h +++ b/src/esh.h @@ -43,11 +43,14 @@ typedef enum { typedef enum { AK_NULL, AK_COMP, AK_COMM } ast_k; +typedef struct ast_ *ast; + typedef struct { tok_k k; u8 *s; } tok; typedef struct { u8 *s; UINT sp, sl; tok t; } lex; -typedef struct { ast_k k; u8 *s; array c; } ast; +struct ast_ { ast_k k; u8 *s; array c; }; +extern bool Lflag, Pflag; extern int _loop, _ret; extern u8 *tok_ks[]; @@ -57,14 +60,17 @@ extern lex lex_init(u8 *src, UINT len); extern tok lex_next(lex *l); extern tok lex_peek(lex *l); -extern ast *ast_init(void); -extern void ast_free(ast *a); +extern ast ast_init(void); +extern void ast_free(ast a); + +extern ast parse(lex *l); -extern ast *parse(lex *l); +extern int execute(ast a); -extern int execute(ast *a); +extern void eval(u8 *src, UINT len); +extern void eval_file(const u8 *file); extern void lex_debug(lex *l); -extern void ast_debug(ast *a); +extern void ast_debug(ast a); #endif // ESH_ESH_H_SAZDXXFN diff --git a/src/eval.c b/src/eval.c new file mode 100644 index 0000000..eadaca0 --- /dev/null +++ b/src/eval.c @@ -0,0 +1,71 @@ +// eval.c +// Evaluation source file for ESH +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#include "esh.h" +#include "util/util.h" + +#include "cll/error.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* Evaluate a string. */ +extern void eval(u8 *src, UINT len) { + lex l = lex_init(src, len); + if (Lflag) { lex_debug(&l); goto ret; } + + ast a = parse(&l); if (!a) { goto ret; } + if (Pflag) { ast_debug(a); goto ret; } + + _ret = WEXITSTATUS(execute(a)); + +ret:; + ast_free(a); +} + +/* Evaluate a file. */ +extern void eval_file(const u8 *file) { + FILE *fi; u8 *fb; size_t fl; + + if (!(fi = fopen((char *)file, "r"))) { + warn("%s: %s", file, serr()); + _ret = WEXITSTATUS(-1); return; + } + + fseek(fi, 0, SEEK_END); fl = ftell(fi); rewind(fi); + + fb = assert_malloc((fl + 1) * sizeof (*fb)); + fread(fb, 1, fl, fi); fb[fl] = 0; fclose(fi); + + eval(fb, fl); free(fb); return; +} diff --git a/src/exec.c b/src/exec.c index 7e42746..bfea0ce 100644 --- a/src/exec.c +++ b/src/exec.c @@ -1,5 +1,5 @@ // exec.c -// Exec source file for ESH +// Execution source file for ESH // Copyright (C) 2020, Jakob Wakeling // All rights reserved. @@ -44,13 +44,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. #include <stdlib.h> #include <string.h> -static int execute_comp(ast *a); -static int execute_comm(ast *a); +static int execute_comp(ast a); +static int execute_comm(ast a); static int launch(u8 *av[]); /* Execute a program. */ -int execute(ast *a) { +int execute(ast a) { switch (a->k) { case AK_COMP: { return execute_comp(a); } case AK_COMM: { return execute_comm(a); } @@ -59,7 +59,7 @@ int execute(ast *a) { } /* Execute a compound statement. */ -static int execute_comp(ast *a) { +static int execute_comp(ast a) { register int ret = 0; for (UINT i = 0; i != a->c->size; i += 1) { @@ -70,11 +70,13 @@ static int execute_comp(ast *a) { } /* Execute a command statement. */ -static int execute_comm(ast *a) { +static int execute_comm(ast a) { if (!a->s) { return _ret; } /* What does this achieve? */ for (struct bltn *b = bltns; b->s; b += 1) { - if (strcmp((char *)a->s, b->s) == 0) { return b->f((char **)a->c->data); } + if (strcmp((char *)a->s, b->s) == 0) { + return b->f(a->c->size - 1, (char **)a->c->data); + } } return launch((u8 **)a->c->data); diff --git a/src/main.c b/src/main.c index ee6bfb1..e60db54 100644 --- a/src/main.c +++ b/src/main.c @@ -45,13 +45,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. #include <string.h> static struct lop lops[] = { - { "help", ARG_NUL, 256 }, - { "version", ARG_NUL, 257 }, + { "help", ARG_NUL, 256 }, + { "version", ARG_NUL, 257 }, + { "debug-lex", ARG_NUL, 258 }, + { "debug-parse", ARG_NUL, 259 }, { NULL, 0, 0 } }; -static bool Lflag = false, Pflag = false; - +bool Lflag = false, Pflag = false; int _loop = 1, _ret; static jmp_buf jmp; @@ -63,12 +64,12 @@ static void hlp(void); static void ver(void); int main(int ac, char *av[]) { (void)(ac); A0 = av[0]; - struct opt opt = OPTGET_INIT; opt.str = "LP"; opt.lops = lops; + struct opt opt = OPTGET_INIT; opt.str = ""; opt.lops = lops; for (int o; (o = optget(&opt, av, 1)) != -1;) switch (o) { - case 'L': { Lflag = true; } break; - case 'P': { Pflag = true; } break; case 256: { hlp(); return 0; } case 257: { ver(); return 0; } + case 258: { Lflag = true; } break; + case 259: { Pflag = true; } break; default: { return 1; } } @@ -81,16 +82,7 @@ int main(int ac, char *av[]) { (void)(ac); A0 = av[0]; u8 *line = lineread(); if (!line) { if (errno) { warn("%s, %d", serr(), errno); } break; } - lex l = lex_init(line, strlen((char *)line)); - if (Lflag) { lex_debug(&l); goto loop; } - - ast *a = parse(&l); if (!a) { goto loop; } - if (Pflag) { ast_debug(a); goto loop; } - - _ret = WEXITSTATUS(execute(a)); - -loop:; - ast_free(a); free(line); + eval(line, strlen((char *)line)); free(line); } while (_loop); linefree(); return warned; @@ -102,12 +94,10 @@ static void reset(int signo) { (void)(signo); static void hlp(void) { puts("ESH - Executive Shell\n"); - puts("Usage: esh [-LP]\n"); + puts("Usage: esh\n"); puts("Options:"); - puts(" -L Print lexer debug output"); - puts(" -P Print parser debug output"); - puts(" --help Display help information"); - puts(" --version Display version information"); + puts(" --help Display help information"); + puts(" --version Display version information"); return; } diff --git a/src/parse.c b/src/parse.c index 46900c4..c4f731f 100644 --- a/src/parse.c +++ b/src/parse.c @@ -41,29 +41,29 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. u8 *ast_ks[] = { (u8 *)"NULL", (u8 *)"COMP", (u8 *)"COMM" }; -static ast *parse_comp(lex *l); -static ast *parse_comm(lex *l); +static ast parse_comp(lex *l); +static ast parse_comm(lex *l); /* Initialise an AST node. */ -ast *ast_init(void) { - return assert_calloc(1, sizeof (ast)); +ast ast_init(void) { + return assert_calloc(1, sizeof (struct ast_)); } /* Uninitialise an AST node. */ -void ast_free(ast *a) { +void ast_free(ast a) { if (a) { array_free(a->c); free(a); } } /* Parse a program. */ -ast *parse(lex *l) { +ast parse(lex *l) { if (lex_peek(l).k == LK_EOF) { return NULL; } return parse_comp(l); } /* Parse a comound statement. */ -static ast *parse_comp(lex *l) { - ast *a = ast_init(); a->k = AK_COMP; +static ast parse_comp(lex *l) { + ast a = ast_init(); a->k = AK_COMP; a->c = array_init((void (*)(ptr))&ast_free); /* Push each command onto the array */ @@ -73,8 +73,8 @@ static ast *parse_comp(lex *l) { } /* Parse a command statement. */ -static ast *parse_comm(lex *l) { - ast *a = ast_init(); a->k = AK_COMM; +static ast parse_comm(lex *l) { + ast a = ast_init(); a->k = AK_COMM; a->c = array_init(NULL); /* Push each command argument onto the array. */ @@ -85,7 +85,7 @@ static ast *parse_comm(lex *l) { } /* Print parser debug output with an indent. */ -static void ast_debug_indent(ast *a, UINT i) { +static void ast_debug_indent(ast a, UINT i) { for (UINT j = 0; j != i; ++j) { printf("\t"); } printf("%s: %s", ast_ks[a->k], a->s); @@ -108,4 +108,4 @@ static void ast_debug_indent(ast *a, UINT i) { } /* Print parser debug output. */ -void ast_debug(ast *a) { ast_debug_indent(a, 0); } +void ast_debug(ast a) { ast_debug_indent(a, 0); }