Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Tiny BASIC
  3.  * Error Handling Module
  4.  *
  5.  * Released as Public Domain by Damian Gareth Walker 2019
  6.  * Created: 18-Aug-2019
  7.  */
  8.  
  9.  
  10. /* included headers */
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include "errors.h"
  15.  
  16.  
  17. /*
  18.  * Internal Data Structures
  19.  */
  20.  
  21.  
  22. /* Private data */
  23. typedef struct {
  24.   ErrorCode error; /* the last error encountered */
  25.   int line; /* the source line on which the error occurred */
  26.   int label; /* the label for the source line */
  27. } Private;
  28.  
  29.  
  30. /*
  31.  * Internal Data
  32.  */
  33.  
  34.  
  35. /* convenience variables */
  36. ErrorHandler *this; /* object being worked on */
  37. Private *data; /* private data of object being worked on */
  38.  
  39. /* global variables */
  40. static char *messages[E_LAST] = { /* the error messages */
  41.   "Successful",
  42.   "Invalid line number",
  43.   "Unrecognised command",
  44.   "Invalid variable",
  45.   "Invalid assignment",
  46.   "Invalid expression",
  47.   "Missing )",
  48.   "Invalid PRINT output",
  49.   "Bad command line",
  50.   "File not found",
  51.   "Invalid operator",
  52.   "THEN expected",
  53.   "Unexpected parameter",
  54.   "RETURN without GOSUB",
  55.   "Divide by zero",
  56.   "Overflow",
  57.   "Out of memory",
  58.   "Too many gosubs"
  59. };
  60.  
  61.  
  62. /*
  63.  * Public Methods
  64.  */
  65.  
  66.  
  67. /*
  68.  * Record an error encountered
  69.  * globals:
  70.  *   ErrorCode   error       the last error encountered
  71.  *   int         line        the source line
  72.  *   int         label       the line's label
  73.  * params:
  74.  *   ErrorCode   new_error   the error code to set
  75.  *   int         new_line    the source line to set
  76.  *   int         new_label   the label to set
  77.  */
  78. static void set_code (ErrorHandler *errors, ErrorCode new_error, int new_line,
  79.   int new_label) {
  80.  
  81.   /* initialise */
  82.   this = errors;
  83.   data = this->data;
  84.  
  85.   /* set the properties */
  86.   data->error = new_error;
  87.   data->line = new_line;
  88.   data->label = new_label;
  89. }
  90.  
  91. /*
  92.  * Return the last error code encountered
  93.  * params:
  94.  *   ErrorHandler*   errors   the error handler
  95.  * returns:
  96.  *   ErrorCode                the last error encountered
  97.  */
  98. static ErrorCode get_code (ErrorHandler *errors) {
  99.   this = errors;
  100.   data = this->data;
  101.   return data->error;
  102. }
  103.  
  104. /*
  105.  * Return the last error line encountered
  106.  * params:
  107.  *   ErrorHandler*   errors   the error handler
  108.  * returns:
  109.  *   int                      the source line of the last error
  110.  */
  111. static int get_line (ErrorHandler *errors) {
  112.   this = errors;
  113.   data = this->data;
  114.   return data->line;
  115. }
  116.  
  117. /*
  118.  * Return the last error label encountered
  119.  * params:
  120.  *   ErrorHandler*   errors   the error handler
  121.  * returns:
  122.  *   int                      the line label of the last error
  123.  */
  124. static int get_label (ErrorHandler *errors) {
  125.   this = errors;
  126.   data = this->data;
  127.   return data->label;
  128. }
  129.  
  130. /*
  131.  * Generate an error message
  132.  * params:
  133.  *   ErrorHandler*   errors     the error handler
  134.  * globals:
  135.  *   char*           messages   a list of error messages
  136.  * returns:
  137.  *   char*                      the full error message
  138.  */
  139. static char *get_text (ErrorHandler *errors) {
  140.  
  141.   /* local variables */
  142.   char
  143.     *message, /* the complete message */
  144.     *line_text, /* source line N */
  145.     *label_text; /* label N */
  146.  
  147.   /* initialise the error object */
  148.   this = errors;
  149.   data = this->data;
  150.  
  151.   /* get the source line, if there is one */
  152.   line_text = malloc (20);
  153.   if (data->line)
  154.     sprintf (line_text, ", source line %d", data->line);
  155.   else
  156.     strcpy (line_text, "");
  157.  
  158.   /* get the source label, if there is one */
  159.   label_text = malloc (19);
  160.   if (data->label)
  161.     sprintf (label_text, ", line label %d", data->label);
  162.   else
  163.     strcpy (label_text, "");
  164.  
  165.   /* put the error message together */
  166.   message = malloc (strlen (messages[data->error]) + strlen (line_text)
  167.     + strlen (label_text) + 1);
  168.   strcpy (message, messages[data->error]);
  169.   strcat (message, line_text);
  170.   strcat (message, label_text);
  171.   free (line_text);
  172.   free (label_text);
  173.  
  174.   /* return the assembled error message */
  175.   return message;
  176. }
  177.  
  178. /*
  179.  * ErrorHandler destructor
  180.  * params:
  181.  *   ErrorHandler*   errors   the doomed error handler
  182.  */
  183. static void destroy (ErrorHandler *errors) {
  184.   if ((this = errors)) {
  185.     data = this->data;
  186.     free (data);
  187.     free (this);
  188.   }
  189. }
  190.  
  191.  
  192. /*
  193.  * Constructors
  194.  */
  195.  
  196.  
  197. /*
  198.  * Principal constructor
  199.  * returns:
  200.  *   ErrorHandler*   the new error handler object
  201.  */
  202. ErrorHandler *new_ErrorHandler (void) {
  203.  
  204.     /* allocate memory */
  205.     this = malloc (sizeof (ErrorHandler));
  206.     this->data = data = malloc (sizeof (Private));
  207.  
  208.     /* initialise the methods */
  209.     this->set_code = set_code;
  210.     this->get_code = get_code;
  211.     this->get_line = get_line;
  212.     this->get_label = get_label;
  213.     this->get_text = get_text;
  214.     this->destroy = destroy;
  215.  
  216.     /* initialise the properties */
  217.     data->error = E_NONE;
  218.     data->line = 0;
  219.     data->label = 0;
  220.  
  221.     /* return the new object */
  222.     return this;
  223. }