summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--mixlib/mix_src_file.c56
-rw-r--r--mixlib/mix_vm.c29
-rw-r--r--mixlib/mix_vm.h8
-rw-r--r--mixlib/xmix_vm.h2
-rw-r--r--mixutils/mixvm_command.c75
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