ESH

Executive Shell
git clone http://git.omkov.net/ESH
Log | Tree | Refs | README | Download

AuthorJamozed <[email protected]>
Date2021-09-11 06:15:34
Commit30bbeefe64d845ddc2dadda0fbe7dac5aed33a01
Parent99a3dff6f85c984a3d2e7b5de49763dfa2d58396

Reimplement compound statements

Diffstat

M src/bltn.c | 5 ++---
D src/cll/cll.h | 98 --------------------------------------------------------------------------------
M src/esh.h | 9 +++++----
M src/exec.c | 42 +++++++++++++++++++++++++-----------------
D src/exec.h | 38 --------------------------------------
M src/lex.c | 5 ++---
M src/lineread.c | 2 +-
M src/lineread.h | 2 +-
M src/main.c | 5 ++---
M src/parse.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++------------------------------
M src/util/array.c | 30 +++++++++++++-----------------
M src/util/array.h | 6 ++----
M src/util/util.h | 4 +---

13 files changed, 100 insertions, 222 deletions

diff --git a/src/bltn.c b/src/bltn.c
index 708429a..f5d8688 100644
--- a/src/bltn.c
+++ b/src/bltn.c
@@ -33,14 +33,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 #include "alias.h"
 #include "bltn.h"
 #include "esh.h"
-#include "exec.h"
 
 #include "cll/error.h"
 #include "cll/optget.h"
 
 #include <stdio.h>
 
-static int bltn_eval(char *av[]) { return execute__(&av[1]); }
+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[]);
@@ -50,7 +49,7 @@ extern int bltn_cd(char *av[]);
 extern int bltn_pwd(char *av[]);
 extern int bltn_set(char *av[]);
 
-static int getret(char *av[]) { printf("%d\n", _ret); return 0; }
+static int getret(char *av[]) { printf("%i\n", _ret); return 0; }
 
 struct bltn bltns[] = {
 	{"alias", &bltn_alias},
diff --git a/src/cll/cll.h b/src/cll/cll.h
deleted file mode 100644
index 8adf5b1..0000000
--- a/src/cll/cll.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// cll.h
-// cll header file for cll
-// Copyright (C) 2021, 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.
-*/
-
-#ifndef OMKOV_CLL_CLL_H_ZO7IRBJS
-#define OMKOV_CLL_CLL_H_ZO7IRBJS
-
-#include <float.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-typedef void *ptr;
-
-typedef uint8_t   u8;
-typedef uint16_t  u16;
-typedef uint32_t  u32;
-typedef uint64_t  u64;
-typedef uintptr_t uint_;
-
-#define UINT uint_
-
-typedef int8_t   s8;
-typedef int16_t  s16;
-typedef int32_t  s32;
-typedef int64_t  s64;
-typedef intptr_t sint;
-
-typedef float       f32;
-typedef double      f64;
-typedef long double f128;
-
-#define U8_MIN   UINT8_MIN
-#define U8_MAX   UINT8_MAX
-#define U16_MIN  UINT16_MIN
-#define U16_MAX  UINT16_MAX
-#define U32_MIN  UINT32_MIN
-#define U32_MAX  UINT32_MAX
-#define U64_MIN  UINT64_MIN
-#define U64_MAX  UINT64_MAX
-#define UINT_MIN UINTPTR_MIN
-#define UINT_MAX UINTPTR_MAX
-
-#define S8_MIN   INT8_MIN
-#define S8_MAX   INT8_MAX
-#define S16_MIN  INT16_MIN
-#define S16_MAX  INT16_MAX
-#define S32_MIN  INT32_MIN
-#define S32_MAX  INT32_MAX
-#define S64_MIN  INT64_MIN
-#define S64_MAX  INT64_MAX
-#define SINT_MIN INTPTR_MIN
-#define SINT_MAX INTPTR_MAX
-
-#define F32_MIN  FLT_MIN
-#define F32_MAX  FLT_MAX
-#define F64_MIN  DBL_MIN
-#define F64_MAX  DBL_MAX
-#define F128_MIN LDBL_MIN
-#define F128_MAX LDBL_MAX
-
-#define BIT(x) (1 << (x))
-
-#define IS_BIN(c) (c == '0' || c == '1')
-#define IS_OCT(c) (c >= '0' && c <= '7')
-#define IS_DEC(c) (c >= '0' && c <= '9')
-#define IS_DOZ(c) ((c >= '0' && c <= '9') || (c == 'A' || c == 'B'))
-#define IS_HEX(c) ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'))
-
-#endif // OMKOV_CLL_CLL_H_ZO7IRBJS
diff --git a/src/esh.h b/src/esh.h
index d62f33d..86d0dd9 100644
--- a/src/esh.h
+++ b/src/esh.h
@@ -33,19 +33,20 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 #ifndef ESH_ESH_H_SAZDXXFN
 #define ESH_ESH_H_SAZDXXFN
 
-#include "cll/cll.h"
+#include "util/array.h"
+#include "util/util.h"
 
 typedef enum {
-	LK_NIL,  LK_EOF,  LK_WORD, LK_END,
+	LK_NULL, LK_EOF,  LK_WORD, LK_END,
 	LK_PIPE, LK_RDIN, LK_ROUT, LK_RERR,
 } tok_k;
 
-typedef enum { AK_NIL, AK_COM } ast_k;
+typedef enum { AK_NULL, AK_COMP, AK_COMM } ast_k;
 
 typedef struct { tok_k k; u8 *s; } tok;
 typedef struct { u8 *s; UINT sp, sl; tok t; } lex;
 
-typedef struct ast { ast_k k; u8 *s, **a; UINT al; struct ast *c; } ast;
+typedef struct { ast_k k; u8 *s; array c; } ast;
 
 extern int _loop, _ret;
 
diff --git a/src/exec.c b/src/exec.c
index 9af7135..7e42746 100644
--- a/src/exec.c
+++ b/src/exec.c
@@ -32,7 +32,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 
 #include "bltn.h"
 #include "esh.h"
-#include "exec.h"
 
 #include "cll/error.h"
 
@@ -45,19 +44,40 @@ 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 launch(u8 *av[]);
 
 /* Execute a program. */
 int execute(ast *a) {
-	/* TODO dont assume that the ast is a command */
+	switch (a->k) {
+	case AK_COMP: { return execute_comp(a); }
+	case AK_COMM: { return execute_comm(a); }
+	default: { error(-1, "%s: Unimplemented AST", ast_ks[a->k]); }
+	}
+}
+
+/* Execute a compound statement. */
+static int execute_comp(ast *a) {
+	register int ret = 0;
 
+	for (UINT i = 0; i != a->c->size; i += 1) {
+		ret = execute(a->c->data[i]);
+	}
+	
+	return ret;
+}
+
+/* Execute a command statement. */
+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->a); }
+		if (strcmp((char *)a->s, b->s) == 0) { return b->f((char **)a->c->data); }
 	}
 
-	return launch(a->a);
+	return launch((u8 **)a->c->data);
 }
 
 /* Fork and execute an executable. */
@@ -75,17 +95,5 @@ static int launch(u8 *av[]) {
 	else if (pid == -1) { perror((char *)av[0]); }
 	else { waitpid(pid, &status, 0); }
 
-	return WEXITSTATUS(status);
-}
-
-/* -------------------------------------------------------------------------- */
-
-int execute__(char *av[]) {
-	if (!av[0]) { return _ret; }
-	
-	for (struct bltn *b = bltns; b->s; ++b) {
-		if (strcmp(av[0], b->s) == 0) { return b->f(av); }
-	}
-	
-	return launch((u8 **)av);
+	return status;
 }
diff --git a/src/exec.h b/src/exec.h
deleted file mode 100644
index 6c0f343..0000000
--- a/src/exec.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// exec.h
-// Exec header 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.
-*/
-
-#ifndef OMKOV_ESH_EXEC_H_VI5E8LVV
-#define OMKOV_ESH_EXEC_H_VI5E8LVV
-
-extern int execute__(char *argv[]);
-
-#endif // OMKOV_ESH_EXEC_H_VI5E8LVV
diff --git a/src/lex.c b/src/lex.c
index 202c072..60315e3 100644
--- a/src/lex.c
+++ b/src/lex.c
@@ -31,8 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 */
 
 #include "esh.h"
-
-#include "cll/cll.h"
+#include "util/util.h"
 
 #include <ctype.h>
 #include <stdio.h>
@@ -43,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 #define D (l->s[l->sp + 1])
 
 u8 *tok_ks[] = {
-	(u8 *)"NIL",  (u8 *)"EOF",  (u8 *)"WORD", (u8 *)"END",
+	(u8 *)"NULL", (u8 *)"EOF",  (u8 *)"WORD", (u8 *)"END",
 	(u8 *)"PIPE", (u8 *)"RDIN", (u8 *)"ROUT", (u8 *)"RERR",
 };
 
diff --git a/src/lineread.c b/src/lineread.c
index e80a3a2..0489df6 100644
--- a/src/lineread.c
+++ b/src/lineread.c
@@ -32,8 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 
 #include "conf.h"
 #include "lineread.h"
+#include "util/util.h"
 
-#include "cll/cll.h"
 #include "cll/error.h"
 
 #include <sys/ioctl.h>
diff --git a/src/lineread.h b/src/lineread.h
index c8406e1..7acab8a 100644
--- a/src/lineread.h
+++ b/src/lineread.h
@@ -33,7 +33,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 #ifndef OMKOV_ESH_LINEREAD_H_RPVXY3N7
 #define OMKOV_ESH_LINEREAD_H_RPVXY3N7
 
-#include "cll/cll.h"
+#include "util/util.h"
 
 extern u8  *lineread(void);
 extern void linefree(void);
diff --git a/src/main.c b/src/main.c
index 1057399..ee6bfb1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -31,10 +31,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 */
 
 #include "esh.h"
-#include "exec.h"
 #include "lineread.h"
+#include "util/util.h"
 
-#include "cll/cll.h"
 #include "cll/error.h"
 #include "cll/optget.h"
 
@@ -88,7 +87,7 @@ int main(int ac, char *av[]) { (void)(ac); A0 = av[0];
 		ast *a = parse(&l); if (!a) { goto loop; }
 		if (Pflag) { ast_debug(a); goto loop; }
 
-		_ret = execute(a);
+		_ret = WEXITSTATUS(execute(a));
 
 loop:;
 		ast_free(a); free(line);
diff --git a/src/parse.c b/src/parse.c
index a327ab3..46900c4 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -31,52 +31,57 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 */
 
 #include "esh.h"
+#include "util/llist.h"
+#include "util/util.h"
 
-#include "cll/cll.h"
+#include "cll/error.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 
-typedef struct { u8 **a; UINT al; } arr;
+u8 *ast_ks[] = { (u8 *)"NULL", (u8 *)"COMP", (u8 *)"COMM" };
 
-static const arr ARR_INIT = { NULL, 0 };
+static ast *parse_comp(lex *l);
+static ast *parse_comm(lex *l);
 
-u8 *ast_ks[] = { (u8 *)"NIL", (u8 *)"COM" };
-
-static void arr_push(arr *a, u8 *s);
-
-static ast *parse_com(lex *l);
-
-ast *ast_init(void) { return calloc(1, sizeof (ast)); }
+/* Initialise an AST node. */
+ast *ast_init(void) {
+	return assert_calloc(1, sizeof (ast));
+}
 
+/* Uninitialise an AST node. */
 void ast_free(ast *a) {
-	for (; a->al; a->al -= 1) { free(a->a[a->al - 1]); }
-	free(a->a); free(a);
+	if (a) { array_free(a->c); free(a); }
 }
 
 /* Parse a program. */
 ast *parse(lex *l) {
 	if (lex_peek(l).k == LK_EOF) { return NULL; }
 
-	/* TODO handle compound commands */
-	return parse_com(l);
+	return parse_comp(l);
 }
 
-/* Parse a command. */
-static ast *parse_com(lex *l) {
-	ast *a = ast_init(); arr av = ARR_INIT;
-	a->k = AK_COM; arr_push(&av, a->s = lex_next(l).s);
+/* Parse a comound statement. */
+static ast *parse_comp(lex *l) {
+	ast *a = ast_init(); a->k = AK_COMP;
+	a->c = array_init((void (*)(ptr))&ast_free);
 
-	/* Push each of the command arguments onto the array */
-	for (tok t; (t = lex_next(l)).k == LK_WORD;) { arr_push(&av, t.s); }
+	/* Push each command onto the array */
+	for (; lex_peek(l).k != LK_EOF;) { array_push(a->c, parse_comm(l)); }
 
-	a->al = av.al; arr_push(&av, NULL); a->a = av.a; return a;
+	return a;
 }
 
-/* Push a string to the end of an array. */
-void arr_push(arr *a, u8 *s) {
-	a->a = realloc(a->a, (a->al += 1) * sizeof (*a->a));
-	a->a[a->al - 1] = s;
+/* Parse a command statement. */
+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. */
+	array_push(a->c, (a->s = lex_next(l).s));
+	for (tok t; (t = lex_next(l)).k == LK_WORD;) { array_push(a->c, t.s); }
+	
+	array_push(a->c, NULL); return a;
 }
 
 /* Print parser debug output with an indent. */
@@ -84,11 +89,22 @@ 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);
 
-	/* Print command arguments if present. */
-	for (UINT i = 0; i != a->al; i += 1) { printf(" %s", a->a[i]); }
-	printf("\n");
-	
-	if (a->c) { ast_debug_indent(a->c, i + 1); }
+	/* Print children if present. */
+	switch (a->k) {
+	case AK_COMP: {
+		printf("\n");
+		for (UINT j = 0; j != a->c->size; j += 1) {
+			ast_debug_indent(a->c->data[j], i + 1);
+			printf("\n");
+		}
+	} break;
+	case AK_COMM: {
+		for (UINT j = 0; j != a->c->size - 1; j += 1) {
+			printf(" %s", (u8 *)a->c->data[j]);
+		}
+	} break;
+	default: { warn("%s: Unimplemented AST (debug)", ast_ks[a->k]); } break;
+	}
 }
 
 /* Print parser debug output. */
diff --git a/src/util/array.c b/src/util/array.c
index b708190..45f0a8d 100644
--- a/src/util/array.c
+++ b/src/util/array.c
@@ -36,29 +36,25 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 #include <stdlib.h>
 
 /* Initialise an array. */
-array array_init(void) {
-	return assert_calloc(1, sizeof (struct array_));
+array array_init(void (*free)(ptr)) {
+	register array a = assert_calloc(1, sizeof (*a));
+	a->free = free; return a;
 }
 
 /* Uninitialise an array. */
-void  array_free(array a) {
-	free(a);
+void array_free(array a) {
+	if (a) {
+		for (UINT i = 0; i != a->size; i += 1) {
+			if (a->free) { a->free(a->data[i]); }
+			else { free(a->data[i]); }
+		}
+		
+		free(a->data); free(a);
+	}
 }
 
 /* Push a pointer to an array. */
 void array_push(array a, ptr data) {
-	a->data = assert_realloc(a->data, (a->size += 1));
+	a->data = assert_realloc(a->data, (a->size += 1) * sizeof (*a->data));
 	a->data[a->size - 1] = data;
 }
-
-/* Pop a pointer from an array. */
-ptr array_pop(array a) {
-	ptr data = a->data[a->size - 1];
-	a->data = assert_realloc(a->data, (a->size -= 1));
-	return data;
-}
-
-/* Peek at a pointer on an array without popping. */
-ptr array_peek(array a) {
-	return a->data[a->size - 1];
-}
diff --git a/src/util/array.h b/src/util/array.h
index afce368..736bd53 100644
--- a/src/util/array.h
+++ b/src/util/array.h
@@ -37,13 +37,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 
 typedef struct array_ *array;
 
-struct array_ { ptr *data; UINT size; };
+struct array_ { ptr *data; UINT size; void (*free)(ptr); };
 
-extern array array_init(void);
+extern array array_init(void (*free)(ptr));
 extern void  array_free(array a);
 
 extern void array_push(array a, ptr data);
-extern ptr  array_pop(array a);
-extern ptr  array_peek(array a);
 
 #endif // ESH_UTIL_ARRAY_H_9LJ2QOUZ
diff --git a/src/util/util.h b/src/util/util.h
index 1a8dbb2..3e9c772 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -42,9 +42,7 @@ typedef uint8_t   u8;
 typedef uint16_t  u16;
 typedef uint32_t  u32;
 typedef uint64_t  u64;
-typedef uintptr_t uint_;
-
-#define UINT uint_
+typedef uintptr_t UINT;
 
 typedef int8_t   s8;
 typedef int16_t  s16;