diff options
| -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); | 
