diff options
author | Jose Antonio Ortega Ruiz <jao@gnu.org> | 2004-06-06 19:53:13 +0000 |
---|---|---|
committer | Jose Antonio Ortega Ruiz <jao@gnu.org> | 2004-06-06 19:53:13 +0000 |
commit | c39f8e909b0fde21c586c09f2cb7c6538da1d492 (patch) | |
tree | 3fe339e6282eaeafd4680356da55ca7e7c07583e | |
parent | 4fcb279164c3bbc584b4121dfda04a393ff6e8d5 (diff) | |
download | mdk-c39f8e909b0fde21c586c09f2cb7c6538da1d492.tar.gz mdk-c39f8e909b0fde21c586c09f2cb7c6538da1d492.tar.bz2 |
keep track of runtime errors and correctly report them.
-rw-r--r-- | mixlib/xmix_vm.c | 123 | ||||
-rw-r--r-- | mixlib/xmix_vm.h | 7 | ||||
-rw-r--r-- | mixlib/xmix_vm_handlers.c | 53 |
3 files changed, 115 insertions, 68 deletions
diff --git a/mixlib/xmix_vm.c b/mixlib/xmix_vm.c index 718a9d3..ecb67c9 100644 --- a/mixlib/xmix_vm.c +++ b/mixlib/xmix_vm.c @@ -56,6 +56,20 @@ get_dev_ (mix_vm_t *vm, mix_fspec_t type) return vm->devices[type]; } +/* error macro */ +#define fail_if_not_(vm,cond,error) \ +do { \ + if (!(cond)) \ + { \ + set_last_error_ (vm, error); \ + return FALSE; \ + } \ +} while (FALSE) + +#define fail_(vm,error) fail_if_not_ (vm, FALSE, error) + +#define fail_unexpected_(vm) fail_ (vm, MIX_VM_ERROR_UNEXPECTED) + /* Instruction handlers */ static gboolean @@ -136,7 +150,7 @@ spc_handler_ (mix_vm_t *vm, const mix_ins_t *ins) mix_word_negative (num) : num); break; } - default: return FALSE; + default: fail_ (vm, MIX_VM_ERROR_BAD_FSPEC); } inc_loc_ (vm); return TRUE; @@ -148,7 +162,8 @@ sla_handler_ (mix_vm_t *vm, const mix_ins_t *ins) mix_short_t n = get_M_ (vm,ins); g_assert (ins->opcode == mix_opSLx); - g_return_val_if_fail (mix_short_is_positive (n), FALSE); + + fail_if_not_ (vm, mix_short_is_positive (n), MIX_VM_ERROR_BAD_M); switch ( mix_ins_id_from_ins (*ins) ) { case mix_SLA: @@ -174,7 +189,7 @@ sla_handler_ (mix_vm_t *vm, const mix_ins_t *ins) &get_rA_ (vm), &get_rX_ (vm)); break; default: - return FALSE; + fail_unexpected_ (vm); } inc_loc_ (vm); @@ -189,16 +204,19 @@ mov_handler_ (mix_vm_t *vm, const mix_ins_t *ins) guint k, delta = ins->fspec; g_assert (ins->opcode == mix_opMOVE); - g_return_val_if_fail (mix_short_is_positive (from), FALSE); - g_return_val_if_fail (mix_short_is_positive (to), FALSE); - g_return_val_if_fail (MEMOK_ (from + delta -1), FALSE); - g_return_val_if_fail (MEMOK_ (to + delta - 1), FALSE); - - for (k = 0; k < delta; ++k) - set_cell_ (vm, to+k, get_cell_ (vm, from+k)); - set_rI_ (vm, 1, to+delta); - inc_loc_ (vm); - return TRUE; + if (mix_short_is_positive (from) + && mix_short_is_positive (to) + && MEMOK_ (from + delta -1) + && MEMOK_ (to + delta - 1)) + { + for (k = 0; k < delta; ++k) + set_cell_ (vm, to+k, get_cell_ (vm, from+k)); + set_rI_ (vm, 1, to+delta); + inc_loc_ (vm); + return TRUE; + } + else + return FALSE; } static gboolean @@ -258,8 +276,10 @@ static gboolean jbs_handler_ (mix_vm_t *vm, const mix_ins_t *ins) { g_assert (ins->opcode == mix_opJBUS); - g_return_val_if_fail (ins->fspec < BD_NO_, TRUE); - g_return_val_if_fail (get_dev_ (vm, ins->fspec) != NULL, TRUE); + fail_if_not_ (vm, ins->fspec < BD_NO_, MIX_VM_ERROR_BAD_DEVICE_NO); + fail_if_not_ (vm, get_dev_ (vm, ins->fspec) != NULL, + MIX_VM_ERROR_BAD_DEVICE_NO); + if ( mix_device_busy (get_dev_ (vm, ins->fspec)) ) { set_rJ_ (vm, get_loc_ (vm)); set_loc_ (vm, get_M_ (vm, ins)); @@ -272,18 +292,19 @@ ioc_handler_ (mix_vm_t *vm, const mix_ins_t *ins) { mix_address_t addr; mix_device_t *dev; - gboolean result; g_assert (ins->opcode == mix_opIOC); + addr = get_M_ (vm, ins); - g_return_val_if_fail (ins->fspec < BD_NO_, TRUE); + fail_if_not_ (vm, ins->fspec < BD_NO_, MIX_VM_ERROR_BAD_DEVICE_NO); + dev = get_dev_ (vm, ins->fspec); - g_return_val_if_fail (dev != NULL, TRUE); - result = - mix_device_ioc (dev, addr); + fail_if_not_ (vm, dev != NULL, MIX_VM_ERROR_BAD_DEVICE_NO); + + fail_if_not_ (vm, mix_device_ioc (dev, addr), MIX_VM_ERROR_DEV_CTL); inc_loc_ (vm); - return result; + return TRUE; } static gboolean @@ -291,21 +312,24 @@ inp_handler_ (mix_vm_t *vm, const mix_ins_t *ins) { mix_address_t addr; mix_device_t *dev; - gboolean result; g_assert (ins->opcode == mix_opIN); + fail_if_not_ (vm, ins->fspec < BD_NO_, MIX_VM_ERROR_BAD_DEVICE_NO); + addr = get_M_ (vm, ins); - g_return_val_if_fail (ins->fspec < BD_NO_, TRUE); - g_return_val_if_fail (MEMOK_ (addr), TRUE); + fail_if_not_ (vm, MEMOK_ (addr), MIX_VM_ERROR_BAD_ACCESS); + dev = get_dev_ (vm, ins->fspec); - g_return_val_if_fail ( dev != NULL, TRUE); - g_return_val_if_fail (MEM_CELLS_NO_ - addr > mix_device_block_size (dev), - TRUE); - result = - mix_device_read (dev, get_cell_ptr_ (vm, addr)); + fail_if_not_ (vm, dev != NULL, MIX_VM_ERROR_BAD_DEVICE_NO); + + fail_if_not_ (vm, MEM_CELLS_NO_ - addr > mix_device_block_size (dev), + MIX_VM_ERROR_BAD_ACCESS); + + fail_if_not_ (vm, mix_device_read (dev, get_cell_ptr_ (vm, addr)), + MIX_VM_ERROR_DEV_READ); inc_loc_ (vm); - return result; + return TRUE; } static gboolean @@ -313,29 +337,35 @@ out_handler_ (mix_vm_t *vm, const mix_ins_t *ins) { mix_address_t addr; mix_device_t *dev; - gboolean result; g_assert (ins->opcode == mix_opOUT); + + fail_if_not_ (vm, ins->fspec < BD_NO_, MIX_VM_ERROR_BAD_DEVICE_NO); + addr = get_M_ (vm, ins); - g_return_val_if_fail (ins->fspec < BD_NO_, TRUE); - g_return_val_if_fail (MEMOK_ (addr), TRUE); + fail_if_not_ (vm, MEMOK_ (addr), MIX_VM_ERROR_BAD_ACCESS); + dev = get_dev_ (vm, ins->fspec); - g_return_val_if_fail ( dev != NULL, TRUE); - g_return_val_if_fail (MEM_CELLS_NO_ - addr > mix_device_block_size (dev), - TRUE); - result = - mix_device_write (dev, get_cell_ptr_ (vm, addr)); + fail_if_not_ (vm, dev != NULL, MIX_VM_ERROR_BAD_DEVICE_NO); + + fail_if_not_ (vm, MEM_CELLS_NO_ - addr > mix_device_block_size (dev), + MIX_VM_ERROR_BAD_ACCESS); + + fail_if_not_ (vm, mix_device_write (dev, get_cell_ptr_ (vm, addr)), + MIX_VM_ERROR_DEV_WRITE); inc_loc_ (vm); - return result; + return TRUE; } static gboolean jrd_handler_ (mix_vm_t *vm, const mix_ins_t *ins) { g_assert (ins->opcode == mix_opJRED); - g_return_val_if_fail (ins->fspec < BD_NO_, TRUE); - g_return_val_if_fail (get_dev_ (vm, ins->fspec) != NULL, TRUE); + fail_if_not_ (vm, ins->fspec < BD_NO_, MIX_VM_ERROR_BAD_DEVICE_NO); + fail_if_not_ (vm, get_dev_ (vm, ins->fspec) != NULL, + MIX_VM_ERROR_BAD_DEVICE_NO); + inc_loc_ (vm); if ( !mix_device_busy (get_dev_ (vm, ins->fspec)) ) { @@ -353,7 +383,8 @@ jmp_handler_ (mix_vm_t *vm, const mix_ins_t *ins) mix_ins_id_t id = mix_ins_id_from_ins (*ins); g_assert (ins->opcode == mix_opJMP); - g_return_val_if_fail (MEMOK_ (addr), FALSE); + fail_if_not_ (vm, MEMOK_ (addr), MIX_VM_ERROR_BAD_ACCESS); + switch ( id ) { case mix_JMP: case mix_JSJ: @@ -386,7 +417,7 @@ jmp_handler_ (mix_vm_t *vm, const mix_ins_t *ins) jump = ( get_cmp_ (vm) != mix_GREAT ); break; default: - return FALSE; + fail_unexpected_ (vm); } inc_loc_ (vm); @@ -406,7 +437,7 @@ jpx_handler_ (mix_vm_t *vm, const mix_ins_t *ins) mix_word_t val; g_assert (ins->opcode >= mix_opJAx || ins->opcode <= mix_opJXx); - g_return_val_if_fail (MEMOK_ (addr), FALSE); + fail_if_not_ (vm, MEMOK_ (addr), MIX_VM_ERROR_BAD_ACCESS); switch (ins->opcode) { case mix_opJAx: val = get_rA_ (vm); break; @@ -448,7 +479,7 @@ jpx_handler_ (mix_vm_t *vm, const mix_ins_t *ins) || mix_word_is_negative (val); break; default: - return FALSE; + fail_unexpected_ (vm); } inc_loc_ (vm); @@ -509,7 +540,7 @@ ina_handler_ (mix_vm_t *vm, const mix_ins_t *ins) mix_word_reverse_sign (val); break; default: - return FALSE; + fail_unexpected_ (vm); } set_reg_ (vm, r, val); inc_loc_ (vm); diff --git a/mixlib/xmix_vm.h b/mixlib/xmix_vm.h index 45805e8..f4773eb 100644 --- a/mixlib/xmix_vm.h +++ b/mixlib/xmix_vm.h @@ -2,9 +2,9 @@ * This file contains internal declarations used in the implementation * of the mix_vm_t type. * ------------------------------------------------------------------ - * $Id: xmix_vm.h,v 1.8 2003/01/12 21:05:01 jao Exp $ + * $Id: xmix_vm.h,v 1.9 2004/06/06 19:53:13 jao Exp $ * ------------------------------------------------------------------ - * Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2000, 2002, 2003, 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 @@ -50,6 +50,7 @@ struct mix_vm_t mix_cmpflag_t cmpflag; mix_short_t loc_count; mix_vm_status_t status; + mix_vm_error_t last_error; mix_device_t * devices[BD_NO_]; mix_address_t start_addr; /* start address of loaded file */ GTree *line_table; /* source line no -> address */ @@ -86,6 +87,8 @@ enum { A_ = 0, X_, J_, I1_, I2_, I3_, I4_, I5_, I6_ }; #define get_pred_list_(vm) (vm->pred_list) #define get_address_list_(vm) (vm->address_list) #define get_status_(vm) (vm->status) +#define get_last_error_(vm) (vm->last_error) +#define set_last_error_(vm,error) ((vm)->last_error = (error)) #define set_reg_(vm,r,x) \ do { \ diff --git a/mixlib/xmix_vm_handlers.c b/mixlib/xmix_vm_handlers.c index 4d0285f..a778750 100644 --- a/mixlib/xmix_vm_handlers.c +++ b/mixlib/xmix_vm_handlers.c @@ -1,9 +1,9 @@ /* -*-c-*- -------------- xmix_vm_handlers.c : * Implementation of the functions declared in xmix_vm_handlers.h * ------------------------------------------------------------------ - * $Id: xmix_vm_handlers.c,v 1.7 2003/01/11 22:43:13 jao Exp $ + * $Id: xmix_vm_handlers.c,v 1.8 2004/06/06 19:54:11 jao Exp $ * ------------------------------------------------------------------ - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 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 @@ -103,31 +103,42 @@ mix_vm_command_info_t commands_[] = { /* trace current instruction */ static void -trace_ (mix_vm_cmd_dispatcher_t *dis) +do_trace_ (mix_vm_cmd_dispatcher_t *dis, gboolean error) { enum {BUFFER_LEN = 128}; static gchar STRINS[BUFFER_LEN]; - if (wants_logs_ (dis)) + const mix_src_file_t *file = mix_vm_get_src_file (dis->vm); + const gchar *line = "\n"; + mix_address_t loc = mix_vm_get_prog_count (dis->vm); + mix_word_t ins = mix_vm_get_addr_contents (dis->vm, loc); + mix_ins_t fins; + mix_word_to_ins_uncheck (ins, fins); + mix_ins_to_string_in_buffer (&fins, STRINS, BUFFER_LEN); + + if (file != NULL) { - const mix_src_file_t *file = mix_vm_get_src_file (dis->vm); - const gchar *line = "\n"; - mix_address_t loc = mix_vm_get_prog_count (dis->vm); - mix_word_t ins = mix_vm_get_addr_contents (dis->vm, loc); - mix_ins_t fins; - mix_word_to_ins_uncheck (ins, fins); - mix_ins_to_string_in_buffer (&fins, STRINS, BUFFER_LEN); + gulong b = mix_vm_get_break_lineno (dis->vm); + if (b > 0) line = mix_src_file_get_line (file, b); + } - if (file != NULL) - { - gulong b = mix_vm_get_break_lineno (dis->vm); - if (b > 0) line = mix_src_file_get_line (file, b); - } + if (!error) + log_message_ (dis, "%d: [%-15s]\t%s", (gint)loc, STRINS, line); + else + log_error_ (dis, "%d: [%-15s]\t%s", (gint)loc, STRINS, line); +} - log_message_ (dis, "%d: [%-15s]\t%s", (gint)loc, STRINS, line); +static void +trace_ (mix_vm_cmd_dispatcher_t *dis) +{ + if (wants_logs_ (dis)) + { + do_trace_ (dis, FALSE); } } +#define trace_error_(dis) do_trace_ (dis, TRUE) + /* run a program tracing executed instructions */ static int run_and_trace_ (mix_vm_cmd_dispatcher_t *dis) @@ -328,12 +339,14 @@ cmd_run_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) } break; case MIX_VM_ERROR: - log_error_ (dis, _("... error executing loaded file")); + log_error_ (dis, _("%s:"), mix_vm_get_last_error_string (dis->vm)); + trace_error_ (dis); break; default: g_assert_not_reached (); break; } + if (wants_logs_ (dis)) print_time_ (dis); return TRUE; @@ -373,8 +386,8 @@ cmd_next_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) } else if (k == MIX_VM_ERROR) { - log_error_ (dis, _("Error at address %d"), - mix_vm_get_prog_count (dis->vm)); + log_error_ (dis, _("%s:"), mix_vm_get_last_error_string (dis->vm)); + trace_error_ (dis); break; } } |