aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordan <[email protected]>2023-06-03 14:41:14 -0400
committerdan <[email protected]>2023-06-03 14:41:14 -0400
commit48c02f4fccd13cf329594988a19a4edd1fce4774 (patch)
treea92d6af027aa5b9d3368801b770179cc83a928f3
parentf130b76fabb440b02c418a537074ec80489a9480 (diff)
downloadforth-48c02f4fccd13cf329594988a19a4edd1fce4774.tar.gz
forth-48c02f4fccd13cf329594988a19a4edd1fce4774.tar.bz2
forth-48c02f4fccd13cf329594988a19a4edd1fce4774.zip
feat: forthmachine and stack errors handled with error handlers, not just by printing
-rw-r--r--forth.c47
-rw-r--r--forthmachine.c6
-rw-r--r--forthmachine.h4
-rw-r--r--forthmachine_optable.c2
-rw-r--r--stack.c34
-rw-r--r--stack.h4
6 files changed, 71 insertions, 26 deletions
diff --git a/forth.c b/forth.c
index e44d372..c70cc83 100644
--- a/forth.c
+++ b/forth.c
@@ -8,16 +8,42 @@
#include "stack.h"
#include "forthmachine.h"
+int exitcode = EXIT_SUCCESS;
+
+// Only used when in buffer_eval mode.
int initialised = false;
+// Only used when in buffer_eval mode.
forthmachine* fm;
-int lastline = 0;
+
+// Pointer to errormessage.
+// Only used when in buffer_eval mode.
+char* errormessage;
+
+void buffer_eval_handleerror(char* err) {
+ exitcode = EXIT_FAILURE;
+ // Set errormessage global
+ errormessage = malloc(sizeof(char) * MAX_OUTPUT_BUFFER_SIZE);
+ strcpy(errormessage, err);
+ #ifdef __EMSCRIPTEN__
+ initialised = false;
+ free(fm);
+ fm = NULL;
+ strcat(errormessage, "\nEnvironment has been reset.\n");
+ #endif
+}
+
+
char* buffer_eval(int len, char* line) {
if (!initialised) {
- fm = forthmachine_new();
+ // initialise global forthmachine instance on first call
+ fm = forthmachine_new(buffer_eval_handleerror);
initialised = true;
}
strcpy(fm->outputbuffer, "");
forthmachine_eval(fm, len, line);
+ if (exitcode == EXIT_FAILURE) {
+ return errormessage;
+ }
if (fm->outputbuffer && strlen(fm->outputbuffer)) {
return fm->outputbuffer;
} else {
@@ -25,8 +51,14 @@ char* buffer_eval(int len, char* line) {
}
}
+void error_print(char* error) {
+ exitcode = exitcode || EXIT_FAILURE;
+ fprintf(stderr, "%s\n", error);
+ exit(exitcode);
+}
+
void stdin_eval() {
- forthmachine* fm = forthmachine_new();
+ forthmachine* fm = forthmachine_new(error_print);
char *line = NULL;
size_t len = 0;
ssize_t read;
@@ -40,8 +72,12 @@ void stdin_eval() {
#ifndef __EMSCRIPTEN__
int main(int argc, char** argv) {
- if (argc>1) printf("%s", buffer_eval(strlen(argv[1])+1, argv[1]));
- else stdin_eval();
+ if (argc>1) {
+ printf("%s", buffer_eval(strlen(argv[1])+1, argv[1]));
+ } else {
+ stdin_eval();
+ }
+ return exitcode;
}
#else
@@ -50,6 +86,7 @@ int main(int argc, char** argv) {
#define EXTERN
EXTERN EMSCRIPTEN_KEEPALIVE char* extern_eval(char* line) {
+ exitcode = EXIT_SUCCESS;
return buffer_eval(strlen(line)+1, line);
}
#endif
diff --git a/forthmachine.c b/forthmachine.c
index ba67013..a421630 100644
--- a/forthmachine.c
+++ b/forthmachine.c
@@ -2,14 +2,16 @@
#include <stdio.h>
#include <string.h>
#include "drhstrings.h"
+#include "errorhandler.h"
#include "stack.h"
/****/
-forthmachine* forthmachine_new() {
+forthmachine* forthmachine_new(errorhandler errorhandler) {
forthmachine* fm = (forthmachine*)malloc(sizeof(forthmachine));
fm->ot = optable_new();
- fm->s = stack_new();
+ fm->s = stack_new(errorhandler);
fm->outputbuffer = (char*)malloc(sizeof(char) * MAX_OUTPUT_BUFFER_SIZE);
+ fm->errorhandler = errorhandler;
strcpy(fm->outputbuffer, "");
return fm;
}
diff --git a/forthmachine.h b/forthmachine.h
index de59fc5..a3a4522 100644
--- a/forthmachine.h
+++ b/forthmachine.h
@@ -3,6 +3,7 @@
#include <stdio.h>
#include <stdbool.h>
#include "stack.h"
+#include "errorhandler.h"
#define OPTABLE_MAX_SIZE 1024
@@ -69,11 +70,12 @@ struct forthmachine {
optable* ot;
stack* s;
char* outputbuffer;
+ errorhandler errorhandler;
};
#define MAX_OUTPUT_BUFFER_SIZE 1024
-forthmachine* forthmachine_new();
+forthmachine* forthmachine_new(errorhandler errorhandler);
void forthmachine_eval(forthmachine* fm, int len, char* line);
#endif //OPTABLE_H
diff --git a/forthmachine_optable.c b/forthmachine_optable.c
index 08241ed..8164d5c 100644
--- a/forthmachine_optable.c
+++ b/forthmachine_optable.c
@@ -316,7 +316,7 @@ void optable_defineop(optable* optable, char *input, int* starti) {
// get code
int wordi = 0;
char wordbuf[WORD_LEN_LIMIT];
- stack* ifcounter = stack_new();
+ stack* ifcounter = stack_new(NULL);
while (input[i] != ';' && opsi < DEFINED_FUNC_MAX_LENGTH) {
char c = input[i++];
if (notdelim(c) && wordi < WORD_LEN_LIMIT) {
diff --git a/stack.c b/stack.c
index 9242f2d..3fadaf4 100644
--- a/stack.c
+++ b/stack.c
@@ -1,13 +1,15 @@
#include "stack.h"
+#include "errorhandler.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-stack* stack_new() {
+stack* stack_new(errorhandler errorhandler) {
stack* s = (stack*)malloc(sizeof(stack));
s->size = 0;
s->maxsize = 1024;
s->start = (stackitem*)malloc(sizeof(stackitem) * s->maxsize);
+ s->errorhandler = errorhandler;
return s;
}
@@ -16,9 +18,13 @@ void stack_free(stack* s) {
free(s);
}
-void exitunderflow() {
- fprintf(stderr, "Error Stack Underflow");
- exit(1);
+
+#define ERROR_STACK_EMPTY_CANNOT_POP "Error: Cannot pop from an empty stack"
+#define ERROR_STACK_OVERFLOW "Error: Stack Overflow"
+#define ERROR_OUTPUT_BUFFER_OVERFLOW "Error: Output would overflow buffer if printed"
+
+static void stack_handleerror(stack* s, char* errormessage) {
+ s->errorhandler(errormessage);
}
stackitem stack_pop(stack* s) {
@@ -28,7 +34,7 @@ stackitem stack_pop(stack* s) {
return si;
} else {
// tried to pop empty stack
- exitunderflow();
+ stack_handleerror(s, ERROR_STACK_EMPTY_CANNOT_POP);
return 0;
}
}
@@ -38,7 +44,7 @@ stackitem stack_peek(stack* s) {
return s->start[s->size - 1];
} else {
// tried to pop empty stack
- exitunderflow();
+ stack_handleerror(s, ERROR_STACK_EMPTY_CANNOT_POP);
return 0;
}
}
@@ -46,8 +52,7 @@ stackitem stack_peek(stack* s) {
void stack_push(stack *s, stackitem si) {
// fprintf(stderr, "pushing %d", si);
if (s->size >= s->maxsize) {
- fprintf(stderr, "Error: Stack Overflow");
- exit(1);
+ stack_handleerror(s, ERROR_STACK_OVERFLOW);
} else {
s->start[s->size] = si;
s->size = s->size + 1;
@@ -64,21 +69,18 @@ int stack_depth(stack* s) {
void stack_tostringappend(stack* s, int sbmaxlen, char* sb) {
int i = strlen(sb);
if (i >= sbmaxlen) {
- fprintf(stderr, "Error: Output would overflow buffer if printed");
- exit(0);
+ stack_handleerror(s, ERROR_OUTPUT_BUFFER_OVERFLOW);
}
sprintf(&(sb[i]), "<%d>", s->size);
i = strlen(sb);
if (i >= sbmaxlen) {
- fprintf(stderr, "Error: Output would overflow Buffer if printed");
- exit(0);
+ stack_handleerror(s, ERROR_OUTPUT_BUFFER_OVERFLOW);
}
for (int j = 0; j < s->size; j++) {
sprintf(&(sb[i]), " %d", s->start[j]);
i = strlen(sb);
if (i >= sbmaxlen) {
- fprintf(stderr, "Error: Output would overflow Buffer if printed");
- exit(0);
+ stack_handleerror(s, ERROR_OUTPUT_BUFFER_OVERFLOW);
}
}
sprintf(&(sb[i]), "\n");
@@ -96,7 +98,7 @@ void stack_roll(stack* s) {
s->start[i] = newtop;
} else {
// tried to pop empty stack
- exitunderflow();
+ stack_handleerror(s, ERROR_STACK_EMPTY_CANNOT_POP);
}
}
@@ -107,7 +109,7 @@ void stack_pick(stack *s) {
stack_push(s, s->start[maxindex - posfromtop]);
} else {
// tried to pop empty stack
- exitunderflow();
+ stack_handleerror(s, ERROR_STACK_EMPTY_CANNOT_POP);
}
}
diff --git a/stack.h b/stack.h
index 3978d0a..b4319ec 100644
--- a/stack.h
+++ b/stack.h
@@ -1,5 +1,6 @@
#include <stdlib.h>
#include <stdio.h>
+#include "errorhandler.h"
#ifndef STACK_H
#define STACK_H
@@ -10,9 +11,10 @@ typedef struct {
int size;
int maxsize;
stackitem* start;
+ errorhandler errorhandler;
} stack;
-stack* stack_new();
+stack* stack_new(errorhandler errorhandler);
void stack_free(stack* s);