diff options
author | dan <[email protected]> | 2023-06-03 14:41:14 -0400 |
---|---|---|
committer | dan <[email protected]> | 2023-06-03 14:41:14 -0400 |
commit | 48c02f4fccd13cf329594988a19a4edd1fce4774 (patch) | |
tree | a92d6af027aa5b9d3368801b770179cc83a928f3 | |
parent | f130b76fabb440b02c418a537074ec80489a9480 (diff) | |
download | forth-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.c | 47 | ||||
-rw-r--r-- | forthmachine.c | 6 | ||||
-rw-r--r-- | forthmachine.h | 4 | ||||
-rw-r--r-- | forthmachine_optable.c | 2 | ||||
-rw-r--r-- | stack.c | 34 | ||||
-rw-r--r-- | stack.h | 4 |
6 files changed, 71 insertions, 26 deletions
@@ -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) { @@ -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); } } @@ -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); |