aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexis Lockwood2021-07-04 22:11:48 -0400
committerAlexis Lockwood2021-07-04 22:11:48 -0400
commit8f0babbd844857ada991a9ee0a0a27d4ba5162ca (patch)
tree5b8e96f727edd436ef92cd61398618ea460df3ca
parente8fa64b7d63713e739514ccd705f697f92837660 (diff)
Add ls_strerror
-rw-r--r--lib/ls_internal.c64
-rw-r--r--lib/ls_internal.h7
-rw-r--r--lib/ls_types.h50
-rw-r--r--ls_run.c5
4 files changed, 83 insertions, 43 deletions
diff --git a/lib/ls_internal.c b/lib/ls_internal.c
index 052e75d..27e8f7a 100644
--- a/lib/ls_internal.c
+++ b/lib/ls_internal.c
@@ -28,6 +28,59 @@
// --- PRIVATE DATATYPES -------------------------------------------------------
// --- PRIVATE CONSTANTS -------------------------------------------------------
+
+static LS_PROGMEM const char _s_ls_ok[]
+ = "OK";
+static LS_PROGMEM const char _s_ls_bad_keyword[]
+ = "bad keyword";
+static LS_PROGMEM const char _s_ls_duplicate_definition[]
+ = "duplicate definition";
+static LS_PROGMEM const char _s_ls_for_next_mismatch[]
+ = "FOR/NEXT mismatch";
+static LS_PROGMEM const char _s_ls_for_step_too_large[]
+ = "FOR: STEP too large";
+static LS_PROGMEM const char _s_ls_internal_error[]
+ = "internal error";
+static LS_PROGMEM const char _s_ls_io_error[]
+ = "IO error";
+static LS_PROGMEM const char _s_ls_out_of_memory[]
+ = "out of memory";
+static LS_PROGMEM const char _s_ls_stopped[]
+ = "stopped";
+static LS_PROGMEM const char _s_ls_syntax_error[]
+ = "syntax error";
+static LS_PROGMEM const char _s_ls_type_mismatch[]
+ = "type mismatch";
+static LS_PROGMEM const char _s_ls_undefined_label[]
+ = "undefined label";
+static LS_PROGMEM const char _s_ls_undefined_variable[]
+ = "undefined variable";
+static LS_PROGMEM const char _s_ls_while_wend_mismatch[]
+ = "WHILE/WEND mismatch";
+static LS_PROGMEM const char _s_ls_no_more_program[]
+ = "no more program";
+static LS_PROGMEM const char _s_ls_unknown[]
+ = "<unknown>";
+
+static LS_PROGMEM const char * _error_s_table[] = {
+ _s_ls_ok,
+ _s_ls_bad_keyword,
+ _s_ls_duplicate_definition,
+ _s_ls_for_next_mismatch,
+ _s_ls_for_step_too_large,
+ _s_ls_internal_error,
+ _s_ls_io_error,
+ _s_ls_out_of_memory,
+ _s_ls_stopped,
+ _s_ls_syntax_error,
+ _s_ls_type_mismatch,
+ _s_ls_undefined_label,
+ _s_ls_undefined_variable,
+ _s_ls_while_wend_mismatch,
+ _s_ls_no_more_program,
+ _s_ls_unknown,
+};
+
// --- PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
// --- PUBLIC VARIABLES --------------------------------------------------------
// --- PRIVATE VARIABLES -------------------------------------------------------
@@ -378,4 +431,15 @@ ls_exec_statement(ls_t * self, ls_token_t tok)
return true;
}
+char const *
+ls_strerror(ls_error_t e)
+{
+ int ec = (int) e;
+
+ if (ec < 0 || ec >= LS_ERROR_T_TOP)
+ return _error_s_table[LS_ERROR_T_TOP];
+ else
+ return _error_s_table[ec];
+}
+
// --- PRIVATE FUNCTION DEFINITIONS --------------------------------------------
diff --git a/lib/ls_internal.h b/lib/ls_internal.h
index 523f8b8..2c65721 100644
--- a/lib/ls_internal.h
+++ b/lib/ls_internal.h
@@ -66,8 +66,8 @@
#define ls_throw_err ls_throw_err_f
#else
#define ls_throw_err(self, e) do { \
- fprintf(stderr, ">throwing %d from %s:%d\n", (e), __FILE__, \
- __LINE__); \
+ fprintf(stderr, ">throwing <%s> from %s:%d\n", ls_strerror(e), \
+ __FILE__, __LINE__); \
ls_throw_err_f((self), (e)); \
} while (0)
#endif
@@ -205,5 +205,8 @@ bool ls_exec_line(ls_t * self);
/// occur.
bool ls_exec_statement(ls_t * self, ls_token_t tok);
+/// Convert an error code to an error message. If the error code is invalid,
+/// returns "<unknown error>".
+char const * ls_strerror(ls_error_t e);
#endif // !defined(LS_INTERNAL_H)
diff --git a/lib/ls_types.h b/lib/ls_types.h
index 00a80ed..fa77462 100644
--- a/lib/ls_types.h
+++ b/lib/ls_types.h
@@ -244,51 +244,23 @@ typedef struct {
uint16_t num;
} ls_label_cache_t;
-/// These are generally derived from the GW-BASIC errors. TODO: document them.
-/// For now read the GW-BASIC doc.
-///
-/// Many of these are not used by LittleScript itself but may be used by
-/// implementations (for example, file access). TODO: document which ones.
+/// Error codes.
typedef enum {
LS_OK,
- LS_NEXT_WITHOUT_FOR,
- LS_SYNTAX_ERROR,
- LS_RETURN_WITHOUT_GOSUB,
- LS_OUT_OF_DATA,
- LS_ILLEGAL_FUNCTION_CALL,
- LS_OVERFLOW,
- LS_OUT_OF_MEMORY,
- LS_UNDEFINED_LABEL,
- LS_SUBSCRIPT_OUT_OF_RANGE,
+
+ LS_BAD_KEYWORD, // this keyword not accepted here
LS_DUPLICATE_DEFINITION,
- LS_DIVISION_BY_ZERO,
- LS_TYPE_MISMATCH,
- LS_STRING_TOO_LONG,
- LS_UNDEFINED_FUNCTION,
- LS_NO_RESUNE,
- LS_RESUME_WITHOUT_ERROR,
- LS_UNPRINTABLE_ERROR,
- LS_MISSING_OPERAND,
- LS_DEVICE_TIMEOUT,
- LS_DEVICE_FAULT,
- LS_WHILE_WEND_MISMATCH,
LS_FOR_NEXT_MISMATCH,
LS_FOR_STEP_TOO_LARGE,
- LS_INTERNAL_ERROR,
- LS_BAD_FILE_NUMBER,
- LS_FILE_NOT_FOUND,
- LS_FILE_ALREADY_OPEN,
- LS_DEVICE_IO_ERROR,
- LS_FILE_ALREADY_EXISTS,
- LS_INPUT_PAST_END,
- LS_BAD_FILENAME,
- LS_DEVICE_UNAVAILABLE,
- LS_COMM_BUFFER_OVERFLOW,
- LS_PERMISSION_DENIED,
- LS_PATH_NOT_FOUND,
- LS_UNDEFINED_VARIABLE,
- LS_BAD_KEYWORD, /// Keyword not valid here
+ LS_INTERNAL_ERROR, // things that should fail an assert
+ LS_IO_ERROR,
+ LS_OUT_OF_MEMORY,
LS_STOPPED,
+ LS_SYNTAX_ERROR, // be nice to split this up a bit
+ LS_TYPE_MISMATCH,
+ LS_UNDEFINED_LABEL,
+ LS_UNDEFINED_VARIABLE,
+ LS_WHILE_WEND_MISMATCH,
/// To be returned by a fetcher if there is no more data. This is not
/// strictly an error condition; the parser should be allowed to read
diff --git a/ls_run.c b/ls_run.c
index 93d2d99..887da37 100644
--- a/ls_run.c
+++ b/ls_run.c
@@ -144,7 +144,8 @@ int main(int argc, char ** argv)
}
else if (e != 0)
{
- fprintf(stderr, ">error %d at %u:%u\n", (int) e, line, col);
+ fprintf(stderr, ">error: %s at %u:%u\n",
+ ls_strerror(e), line, col);
}
fclose(f);
@@ -225,7 +226,7 @@ static int _fetcher(void * arg, uint16_t loc)
if (n < self->cache_page_size)
{
if (ferror(self->f))
- return -LS_DEVICE_IO_ERROR;
+ return -LS_IO_ERROR;
}
char c = self->cache[self->n_page][