From 27d6571f6c147c6d76421ba817114756cd2511ec Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Sun, 6 Jun 2004 22:58:58 +0000 Subject: correct error tracking and reporting. --- mixlib/mix_vm.c | 111 ++++++++++++++++++++++++++++++++++++-------------------- mixlib/mix_vm.h | 45 +++++++++++++++++------ 2 files changed, 105 insertions(+), 51 deletions(-) diff --git a/mixlib/mix_vm.c b/mixlib/mix_vm.c index 4bbc976..8e8a065 100644 --- a/mixlib/mix_vm.c +++ b/mixlib/mix_vm.c @@ -1,22 +1,22 @@ /* -*-c-*- ------------------ mix_vm.c : * Implementation of the functions declared in mix_vm.h * ------------------------------------------------------------------ - * Copyright (C) 2000, 2001 Free Software Foundation, Inc. - * + * Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc. + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * + * */ #include "mix.h" @@ -37,6 +37,7 @@ vm_reset_reload_ (mix_vm_t *vm, gboolean is_reload) set_over_ (vm, FALSE); set_cmp_ (vm, mix_EQ); set_loc_ (vm, MIX_WORD_ZERO); + set_last_error_ (vm, MIX_VM_ERROR_NONE); for ( k = 0; k < MEM_CELLS_NO_; ++k) set_cell_ (vm, k, MIX_WORD_ZERO); if (vm->symbol_table != NULL ) @@ -81,7 +82,7 @@ mix_vm_t * mix_vm_new (void) { int i; - + mix_vm_t *vm = g_new (struct mix_vm_t,1); vm->line_table = NULL; vm->address_table = NULL; @@ -89,13 +90,14 @@ mix_vm_new (void) vm->src_file = NULL; vm->pred_list = mix_predicate_list_new (vm); vm->address_list = NULL; - + vm->last_error = MIX_VM_ERROR_NONE; + for (i = 0; i < BD_NO_; ++i) vm->devices[i] = NULL; - + vm->clock = mix_vm_clock_new (); vm->factory = mix_device_new; - + vm_reset_ (vm); return vm; @@ -106,9 +108,9 @@ void mix_vm_delete (mix_vm_t * vm) { int i; - + g_return_if_fail (vm != NULL); - + if (vm->line_table != NULL) g_tree_destroy (vm->line_table); if (vm->address_table != NULL) g_tree_destroy (vm->address_table); if (vm->symbol_table != NULL) mix_symbol_table_delete (vm->symbol_table); @@ -127,14 +129,14 @@ mix_vm_connect_device (mix_vm_t *vm, mix_device_t *device) { mix_device_t *old; mix_device_type_t type; - + g_return_val_if_fail (vm != NULL, NULL); g_return_val_if_fail (device != NULL, NULL); - + type = mix_device_type (device); old = vm->devices[type]; vm->devices[type] = device; - + return old; } @@ -202,7 +204,7 @@ mix_vm_get_rI (const mix_vm_t *vm, guint idx) return mix_word_to_short_fast (get_rI_ (vm, idx)); } -void +void mix_vm_set_rA (mix_vm_t *vm, mix_word_t value) { g_return_if_fail (vm != NULL); @@ -216,7 +218,7 @@ mix_vm_set_rX (mix_vm_t *vm, mix_word_t value) set_rX_ (vm, value); } -void +void mix_vm_set_rJ (mix_vm_t *vm, mix_short_t value) { g_return_if_fail (vm != NULL); @@ -224,7 +226,7 @@ mix_vm_set_rJ (mix_vm_t *vm, mix_short_t value) set_rJ_ (vm, mix_short_to_word_fast (value)); } -void +void mix_vm_set_rI (mix_vm_t *vm, guint idx, mix_short_t value) { g_return_if_fail (vm != NULL); @@ -273,16 +275,14 @@ mix_word_t mix_vm_get_addr_contents (const mix_vm_t *vm, mix_address_t addr) { g_return_val_if_fail (vm != NULL, MIX_WORD_ZERO); - g_return_val_if_fail (MEMOK_ (addr), MIX_WORD_ZERO); - return get_cell_ (vm, addr); + return (MEMOK_ (addr))? get_cell_ (vm, addr) : MIX_WORD_ZERO; } void mix_vm_set_addr_contents (mix_vm_t *vm, mix_address_t addr, mix_word_t value) { g_return_if_fail (vm != NULL); - g_return_if_fail (MEMOK_ (addr)); - set_cell_ (vm, addr, value); + if (MEMOK_ (addr)) set_cell_ (vm, addr, value); } gboolean @@ -315,7 +315,7 @@ mix_vm_load_file (mix_vm_t *vm, const gchar *name) mix_ins_desc_t ins; const gchar *sp; gboolean reload = FALSE; - + g_return_val_if_fail (vm != NULL, FALSE); file = mix_code_file_new_read (name); if (file == NULL) @@ -343,16 +343,16 @@ mix_vm_load_file (mix_vm_t *vm, const gchar *name) } vm->src_file = sfile; - - while ( mix_code_file_get_ins (file, &ins) ) + + while ( mix_code_file_get_ins (file, &ins) ) { set_cell_ (vm, ins.address, ins.ins); if ( vm->line_table != NULL ) { - g_tree_insert (vm->line_table, + g_tree_insert (vm->line_table, GUINT_TO_POINTER (ins.lineno), GUINT_TO_POINTER ((guint)ins.address)); - g_tree_insert (vm->address_table, + g_tree_insert (vm->address_table, GUINT_TO_POINTER ((guint)ins.address), GUINT_TO_POINTER (ins.lineno)); } @@ -360,7 +360,7 @@ mix_vm_load_file (mix_vm_t *vm, const gchar *name) set_loc_ (vm, mix_code_file_get_start_addr (file)); set_start_ (vm, get_loc_ (vm)); mix_code_file_delete (file); - + set_status_ (vm, MIX_VM_LOADED); return TRUE; } @@ -379,7 +379,7 @@ mix_vm_get_symbol_table (const mix_vm_t *vm) return vm->symbol_table; } -mix_address_t +mix_address_t mix_vm_get_prog_count (const mix_vm_t *vm) { g_return_val_if_fail (vm != NULL, MIX_SHORT_ZERO); @@ -394,13 +394,13 @@ mix_vm_get_address_lineno (const mix_vm_t *vm, mix_address_t addr) guint lineno; g_return_val_if_fail (vm != NULL, 0); - g_return_val_if_fail (MEMOK_ (addr), 0); + if (!(MEMOK_ (addr))) return 0; lineno = GPOINTER_TO_UINT (g_tree_lookup (vm->address_table, gp_addr)); return lineno; } /* Get the address for a given source line number */ -typedef struct +typedef struct { guint lineno; mix_address_t result; @@ -422,7 +422,7 @@ mix_address_t mix_vm_get_lineno_address (const mix_vm_t *vm, guint lineno) { addr_traverse_t tr; - + g_return_val_if_fail (vm != NULL, MIX_VM_CELL_NO); if (!vm->line_table) return MIX_VM_CELL_NO; tr.lineno = lineno; @@ -438,14 +438,14 @@ mix_vm_run (mix_vm_t *vm) { mix_ins_t ins; g_return_val_if_fail (vm != NULL, MIX_VM_ERROR); - + while ( !is_halted_ (vm) ) { mix_word_to_ins_uncheck (get_cell_ (vm, get_loc_ (vm)), ins); vm->address_list = g_slist_prepend (vm->address_list, GINT_TO_POINTER ((gint)get_loc_ (vm))); - if ( !(*ins_handlers_[ins.opcode]) (vm,&ins) ) + if ( !(*ins_handlers_[ins.opcode]) (vm,&ins) ) return set_status_ (vm, MIX_VM_ERROR); else update_time_ (vm, &ins); @@ -489,6 +489,39 @@ mix_vm_get_run_status (const mix_vm_t *vm) return get_status_ (vm); } +mix_vm_error_t +mix_vm_get_last_error (const mix_vm_t *vm) +{ + g_return_val_if_fail (vm != NULL, MIX_VM_ERROR_UNEXPECTED); + return get_last_error_ (vm); +} + +const gchar * +mix_vm_get_last_error_string (const mix_vm_t *vm) +{ + return mix_vm_get_error_string (mix_vm_get_last_error (vm)); +} + +const gchar * +mix_vm_get_error_string (mix_vm_error_t code) +{ + static const gchar *errors[] = { + N_("No error"), + N_("Invalid memory address"), + N_("Invalid device number"), + N_("Invalid fspec"), + N_("Invalid M-value"), + N_("Cannot access device"), + N_("Cannot access device for reading"), + N_("Cannot access device for writing"), + N_("Unexpected error"), + N_("Unknow error code") + }; + + return errors[(code < 0 || code > MIX_VM_ERROR_UNEXPECTED) + ? MIX_VM_ERROR_UNEXPECTED + 1 : code]; +} + /* Breakpoints */ gulong mix_vm_get_break_lineno (const mix_vm_t *vm) @@ -503,7 +536,7 @@ mix_vm_get_break_lineno (const mix_vm_t *vm) } } -typedef struct +typedef struct { mix_vm_t *vm; guint lineno; @@ -528,7 +561,7 @@ gint /* if >0 the line no. of the break point */ mix_vm_set_breakpoint (mix_vm_t *vm, guint lineno) { bp_traverse_t tr; - + g_return_val_if_fail (vm != NULL, MIX_VM_BP_ERROR); if (!vm->line_table) return MIX_VM_BP_NDEBUG; tr.lineno = lineno; @@ -542,7 +575,7 @@ mix_vm_set_breakpoint (mix_vm_t *vm, guint lineno) } gint -mix_vm_set_breakpoint_address (mix_vm_t *vm, guint address) +mix_vm_set_breakpoint_address (mix_vm_t *vm, guint address) { g_return_val_if_fail (vm != NULL, MIX_VM_BP_ERROR); if (address >= MIX_VM_CELL_NO) @@ -572,7 +605,7 @@ clear_break_ (gpointer key, gpointer value, gpointer data) } else if (GPOINTER_TO_UINT (key) > tr->lineno) return TRUE; - + return FALSE; } @@ -580,7 +613,7 @@ gint /* one of MIX_VM_BP_ */ mix_vm_clear_breakpoint (mix_vm_t *vm, guint lineno) { bp_traverse_t tr; - + g_return_val_if_fail (vm != NULL, MIX_VM_BP_ERROR); if (!vm->line_table) return MIX_VM_BP_NDEBUG; tr.lineno = lineno; @@ -591,7 +624,7 @@ mix_vm_clear_breakpoint (mix_vm_t *vm, guint lineno) } gint -mix_vm_clear_breakpoint_address (mix_vm_t *vm, guint address) +mix_vm_clear_breakpoint_address (mix_vm_t *vm, guint address) { g_return_val_if_fail (vm != NULL, MIX_VM_BP_ERROR); if (address >= MIX_VM_CELL_NO) diff --git a/mixlib/mix_vm.h b/mixlib/mix_vm.h index b7412bf..005bfc2 100644 --- a/mixlib/mix_vm.h +++ b/mixlib/mix_vm.h @@ -1,22 +1,22 @@ /* ---------------------- mix_vm.h : * Types and functions implementing the MIX virtual machine * ------------------------------------------------------------------ - * Copyright (C) 2000, 2001 Free Software Foundation, Inc. - * + * Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc. + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * + * */ @@ -55,7 +55,6 @@ mix_vm_connect_device (mix_vm_t *vm, mix_device_t *device); extern mix_device_t * mix_vm_get_device (const mix_vm_t *vm, mix_device_type_t dev); - /* install a device factory for automatic connection */ typedef mix_device_t * (* mix_device_factory_t) (mix_device_type_t device); extern void @@ -82,19 +81,18 @@ mix_vm_get_rJ(const mix_vm_t *vm); extern mix_short_t mix_vm_get_rI(const mix_vm_t *vm, guint idx); -extern void +extern void mix_vm_set_rA(mix_vm_t *vm, mix_word_t value); extern void mix_vm_set_rX(mix_vm_t *vm, mix_word_t value); -extern void +extern void mix_vm_set_rJ(mix_vm_t *vm, mix_short_t value); -extern void +extern void mix_vm_set_rI(mix_vm_t *vm, guint idx, mix_short_t value); - /* Access to the comparison flag and overflow toggle */ extern mix_cmpflag_t mix_vm_get_cmpflag(const mix_vm_t *vm); @@ -125,7 +123,7 @@ mix_vm_set_addr_contents(mix_vm_t *vm, mix_address_t addr, mix_word_t value); extern gboolean /* TRUE if success */ mix_vm_exec_ins(mix_vm_t *vm, const mix_ins_t *ins); -/* Load a code file into memory (-name- does not need the default extension) +/* Load a code file into memory (-name- does not need the default extension) * resetting the vm's state */ extern gboolean @@ -140,7 +138,7 @@ extern const mix_symbol_table_t * mix_vm_get_symbol_table (const mix_vm_t *vm); /* Get current program counter */ -extern mix_address_t +extern mix_address_t mix_vm_get_prog_count (const mix_vm_t *vm); /* Get the source line number for a given address */ @@ -163,6 +161,28 @@ typedef enum { MIX_VM_EMPTY /* no program loaded */ } mix_vm_status_t; +/* execution errors */ +typedef enum { + MIX_VM_ERROR_NONE, /* no error */ + MIX_VM_ERROR_BAD_ACCESS, /* bad memory address */ + MIX_VM_ERROR_BAD_DEVICE_NO, /* bad device number */ + MIX_VM_ERROR_BAD_FSPEC, /* invalid fspec */ + MIX_VM_ERROR_BAD_M, /* invalid M-value */ + MIX_VM_ERROR_DEV_CTL, /* error accessing device for ioctl */ + MIX_VM_ERROR_DEV_READ, /* error accessing device for reading */ + MIX_VM_ERROR_DEV_WRITE, /* error accessing device for writing */ + MIX_VM_ERROR_UNEXPECTED /* unexpected error */ +} mix_vm_error_t; + +extern mix_vm_error_t +mix_vm_get_last_error (const mix_vm_t *vm); + +extern const gchar * +mix_vm_get_last_error_string (const mix_vm_t *vm); + +extern const gchar * +mix_vm_get_error_string (mix_vm_error_t code); + /* run until next breakpoint or end of execution */ extern mix_vm_status_t mix_vm_run (mix_vm_t *vm); @@ -190,6 +210,7 @@ enum { MIX_VM_BP_OK = 0 /* success */ }; + extern gint /* if >0 the line no. of the break point */ mix_vm_set_breakpoint (mix_vm_t *vm, guint lineno); -- cgit v1.2.3