diff options
-rw-r--r-- | mixlib/mix_src_file.c | 56 | ||||
-rw-r--r-- | mixlib/mix_vm.c | 29 | ||||
-rw-r--r-- | mixlib/mix_vm.h | 8 | ||||
-rw-r--r-- | mixlib/xmix_vm.h | 2 | ||||
-rw-r--r-- | mixutils/mixvm_command.c | 75 |
5 files changed, 137 insertions, 33 deletions
diff --git a/mixlib/mix_src_file.c b/mixlib/mix_src_file.c index 0569aa6..c6e1be0 100644 --- a/mixlib/mix_src_file.c +++ b/mixlib/mix_src_file.c @@ -1,7 +1,7 @@ /* -*-c-*- -------------- mix_src_file.c : * Implementation of the functions declared in mix_src_file.h * ------------------------------------------------------------------ - * Last change: Time-stamp: "00/12/17 12:56:50 jose" + * Last change: Time-stamp: "00/12/17 22:46:27 jose" * ------------------------------------------------------------------ * Copyright (C) 2000 jose antonio ortega ruiz <jaortega@acm.org> * @@ -33,36 +33,43 @@ struct mix_src_file_t guint lineno; /* the number of lines */ }; - -/* create a new src file from an existing disk file */ -mix_src_file_t * -mix_src_file_new_for_read (const gchar *path) +/* load the source file lines into memory */ +static gboolean +load_file_ (mix_src_file_t *file) { - mix_file_t *file = mix_file_new_with_def_ext (path, - mix_io_READ, - MIX_SRC_DEFEXT); - if (file == NULL) - return NULL; - else + mix_file_t *mf = mix_file_new_with_def_ext (file->path, + mix_io_READ, + MIX_SRC_DEFEXT); + if (mf != NULL) { enum {BUFFER_SIZE = 256}; static gchar BUFFER[BUFFER_SIZE]; - mix_src_file_t *result = g_new (mix_src_file_t, 1); - FILE *f = mix_file_to_FILE (file); - result->lines = g_ptr_array_new (); - result->path = g_strdup (path); - result->lineno = 0; + FILE *f = mix_file_to_FILE (mf); + file->lines = g_ptr_array_new (); + file->lineno = 0; while (fgets (BUFFER, BUFFER_SIZE, f) == BUFFER) { - g_ptr_array_add (result->lines, (gpointer) g_strdup (BUFFER)); - result->lineno++; + g_ptr_array_add (file->lines, (gpointer) g_strdup (BUFFER)); + file->lineno++; } - mix_file_delete (file); - return result; + mix_file_delete (mf); + return TRUE; } + return FALSE; +} + +/* create a new src file from an existing disk file */ +mix_src_file_t * +mix_src_file_new_for_read (const gchar *path) +{ + mix_src_file_t *result = g_new (mix_src_file_t, 1); + result->lines = NULL; + result->path = g_strdup (path); + result->lineno = 0; + return result; } /* destroy a src file object */ @@ -70,7 +77,7 @@ void mix_src_file_delete (mix_src_file_t *src) { g_return_if_fail (src != NULL); - g_ptr_array_free (src->lines, TRUE); + if (src->lines) g_ptr_array_free (src->lines, TRUE); g_free (src->path); g_free (src); } @@ -88,10 +95,11 @@ const gchar * mix_src_file_get_line (const mix_src_file_t *src, guint lineno) { g_return_val_if_fail (src != NULL, NULL); + if (src->lines == NULL && !load_file_ ((mix_src_file_t*)src)) + return NULL; if (lineno > src->lineno || lineno == 0) return NULL; - else - return (gchar *)g_ptr_array_index (src->lines, lineno - 1); + return (gchar *)g_ptr_array_index (src->lines, lineno - 1); } /* get the total no. of lines in the file */ @@ -99,6 +107,8 @@ guint mix_src_file_get_line_no (const mix_src_file_t *src) { g_return_val_if_fail (src != NULL, 0); + if (src->lines == NULL && !load_file_ ((mix_src_file_t*)src)) + return 0; return src->lineno; } diff --git a/mixlib/mix_vm.c b/mixlib/mix_vm.c index d1ad6e7..2c41097 100644 --- a/mixlib/mix_vm.c +++ b/mixlib/mix_vm.c @@ -52,6 +52,11 @@ vm_reset_ (mix_vm_t *vm) g_tree_destroy (vm->address_table); vm->address_table = NULL; } + if (vm->src_file != NULL) + { + mix_src_file_delete (vm->src_file); + vm->src_file = NULL; + } bp_clear_all_ (vm); } @@ -83,6 +88,7 @@ mix_vm_delete (mix_vm_t * vm) 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); + if (vm->src_file != NULL) mix_src_file_delete (vm->src_file); for (i = 0; i < BD_NO_; ++i) mix_device_delete (vm->devices[i]); g_free (vm); @@ -244,6 +250,7 @@ mix_vm_load_file (mix_vm_t *vm, const gchar *name) { mix_code_file_t *file; mix_ins_desc_t ins; + const gchar *sp; g_return_val_if_fail (vm != NULL, FALSE); file = mix_code_file_new_read (name); @@ -255,6 +262,11 @@ mix_vm_load_file (mix_vm_t *vm, const gchar *name) vm->line_table = g_tree_new (cmp_uint_); vm->address_table = g_tree_new (cmp_uint_); } + + sp = mix_code_file_get_source_path (file); + if (sp != NULL) + vm->src_file = mix_src_file_new_for_read (sp); + while ( mix_code_file_get_ins (file, &ins) ) { set_cell_ (vm, ins.address, ins.ins); @@ -275,6 +287,13 @@ mix_vm_load_file (mix_vm_t *vm, const gchar *name) return TRUE; } +const mix_src_file_t * +mix_vm_get_src_file (const mix_vm_t *vm) +{ + g_return_val_if_fail (vm != NULL, NULL); + return vm->src_file; +} + const mix_symbol_table_t * mix_vm_get_symbol_table (const mix_vm_t *vm) { @@ -320,11 +339,17 @@ mix_vm_exec_next (mix_vm_t *vm) { mix_ins_t ins; g_return_val_if_fail (vm != NULL, MIX_VM_ERROR); - if ( is_halted_ (vm) ) return MIX_VM_HALT; + if (get_loc_ (vm) >= MIX_VM_CELL_NO) halt_ (vm, TRUE); + if (is_halted_ (vm)) + { + reset_loc_ (vm); /* set current location to start address */ + halt_ (vm, FALSE); + return MIX_VM_HALT; + } mix_word_to_ins_uncheck (get_cell_ (vm, get_loc_ (vm)), ins); if (!(*ins_handlers_[ins.opcode]) (vm, &ins)) return MIX_VM_ERROR; - return MIX_VM_BREAK; + return bp_is_set_ (vm, get_loc_ (vm)) ? MIX_VM_BREAK : MIX_VM_OK; } /* Breakpoints */ diff --git a/mixlib/mix_vm.h b/mixlib/mix_vm.h index 6ddbb8e..cf4965c 100644 --- a/mixlib/mix_vm.h +++ b/mixlib/mix_vm.h @@ -26,6 +26,7 @@ #include "mix_types.h" #include "mix_ins.h" #include "mix_code_file.h" +#include "mix_src_file.h" #include "mix_symbol_table.h" /* Comparison flag */ @@ -114,6 +115,10 @@ mix_vm_exec_ins(mix_vm_t *vm, const mix_ins_t *ins); extern gboolean mix_vm_load_file(mix_vm_t *vm, const gchar *name); +/* Get the source file object corresponding to the last loaded code file */ +extern const mix_src_file_t * +mix_vm_get_src_file (const mix_vm_t *vm); + /* Get symbol table of loaded file */ extern const mix_symbol_table_t * mix_vm_get_symbol_table (const mix_vm_t *vm); @@ -127,7 +132,8 @@ mix_vm_get_prog_count (const mix_vm_t *vm); enum { MIX_VM_ERROR, /* error executing instructions */ MIX_VM_BREAK, /* breakpoint found */ - MIX_VM_HALT /* end of execution */ + MIX_VM_HALT, /* end of execution */ + MIX_VM_OK /* successful instruction execution */ }; extern int diff --git a/mixlib/xmix_vm.h b/mixlib/xmix_vm.h index a13ecc6..c2a1db1 100644 --- a/mixlib/xmix_vm.h +++ b/mixlib/xmix_vm.h @@ -26,6 +26,7 @@ #include "mix_symbol_table.h" #include "mix_device.h" +#include "mix_src_file.h" #include "mix_vm.h" /* The mix_vm_t type */ @@ -44,6 +45,7 @@ struct mix_vm_t GTree *address_table; /* adress -> source line no */ gint8 bp[MEM_CELLS_NO_/8]; /* each bit signals a break point */ mix_symbol_table_t *symbol_table; + mix_src_file_t *src_file; /* source of last loaded code file */ }; /* Macros for accessing/modifying the above structure. diff --git a/mixutils/mixvm_command.c b/mixutils/mixvm_command.c index 53d98e0..3d783e1 100644 --- a/mixutils/mixvm_command.c +++ b/mixutils/mixvm_command.c @@ -31,7 +31,7 @@ #include <mixlib/mix_vm.h> #include <mixlib/mix_vm_dump.h> -#include "mixlib/mix_eval.h" +#include <mixlib/mix_eval.h> #include "mixvm_command.h" /* The names of functions that actually do the manipulation. */ @@ -63,6 +63,8 @@ DEC_FUN (compile_); DEC_FUN (edit_); DEC_FUN (weval_); DEC_FUN (w2d_); +DEC_FUN (tron_); +DEC_FUN (troff_); DEC_FUN (quit_); /* A structure which contains information on the commands this program @@ -111,6 +113,8 @@ COMMAND commands[] = { { "weval", cmd_weval_, N_("Evaluate a given W-expres sion"), "weval WEXPR"}, { "w2d", cmd_w2d_, N_("Convert a MIX word to its decimal value"), "w2d WORD" }, + { "tron", cmd_tron_, N_("Turn on instruction tracing."), "tron" }, + { "troff", cmd_troff_, N_("Turn off instruction tracing."), "troff" }, { "quit", cmd_quit_, N_("Quit the program"), "quit" }, { (char *)NULL, (Function *)NULL, (char *)NULL } }; @@ -187,14 +191,15 @@ find_command_ (const char *name) return ((COMMAND *)NULL); } - + /* the virtual machine and dump context */ static mix_vm_t *vm_ = NULL; static mix_dump_context_t *dc_ = NULL; - /* the w-expression evaluator */ static mix_eval_t *eval_ = NULL; - +/* trace status */ +static gboolean is_tracing_ = FALSE; + static int cmd_help_ (char *arg) @@ -258,20 +263,57 @@ cmd_load_ (char *arg) } mix_eval_set_symbols_from_table (eval_, mix_vm_get_symbol_table (vm_)); - + fprintf (stderr, _("Program loaded. Start address: %d\n"), mix_vm_get_prog_count (vm_)); return TRUE; } +/* trace current instruction */ +static void +trace_ () +{ + const mix_src_file_t *file = mix_vm_get_src_file (vm_); + const gchar *line = ""; + gchar *strins; + mix_address_t loc = mix_vm_get_prog_count (vm_); + mix_word_t ins = mix_vm_get_addr_contents (vm_, loc); + mix_ins_t fins; + mix_word_to_ins_uncheck (ins, fins); + strins = mix_ins_to_string (&fins); + + if (file != NULL) + { + gulong b = mix_vm_get_break_lineno (vm_); + if (b > 0) line = mix_src_file_get_line (file, b); + } + + printf ("%d: [%s]\t%s", (gint)loc, strins, line); + if (strins != NULL) g_free (strins); +} + +static int +run_and_trace_ () +{ + int k = MIX_VM_OK; + if (!is_tracing_) + return mix_vm_run (vm_); + else while (k == MIX_VM_OK) + { + trace_ (); + k = mix_vm_exec_next (vm_); + } + return k; +} + static int cmd_run_ (char *arg) { if (arg != NULL && *arg != '\0' && cmd_load_ (arg) != TRUE) return TRUE; puts (_("Running ...")); - switch (mix_vm_run (vm_)) + switch (run_and_trace_ ()) { case MIX_VM_HALT: puts (_("... done")); @@ -301,6 +343,8 @@ static int cmd_next_ (char *arg) { int ins_no = 1; + int k; + if ( strlen (arg) != 0 ) { int k = 0; @@ -316,7 +360,8 @@ cmd_next_ (char *arg) while ( ins_no-- > 0 ) { - int k = mix_vm_exec_next (vm_); + if (is_tracing_) trace_ (); + k = mix_vm_exec_next (vm_); if (k == MIX_VM_HALT) { fprintf (stderr, _("End of program reached at address %d\n"), @@ -928,6 +973,22 @@ cmd_w2d_ (char *arg) return TRUE; } +static int +cmd_tron_ (char *arg) +{ + is_tracing_ = TRUE; + printf (_("Instruction tracing has been turned ON.\n")); + return TRUE; +} + +static int +cmd_troff_ (char *arg) +{ + is_tracing_ = FALSE; + printf (_("Instruction tracing has been turned OFF.\n")); + return TRUE; +} + /* external interface */ void |