summaryrefslogtreecommitdiffhomepage
path: root/mixlib/mix_vm_dump.c
diff options
context:
space:
mode:
Diffstat (limited to 'mixlib/mix_vm_dump.c')
-rw-r--r--mixlib/mix_vm_dump.c194
1 files changed, 194 insertions, 0 deletions
diff --git a/mixlib/mix_vm_dump.c b/mixlib/mix_vm_dump.c
new file mode 100644
index 0000000..33b5c38
--- /dev/null
+++ b/mixlib/mix_vm_dump.c
@@ -0,0 +1,194 @@
+/* ---------------------- mix_vm_dump.c :
+ * Implementation of the functions declared in mix_vm_dump.h
+ * ------------------------------------------------------------------
+** Copyright (C) 2000 jose antonio ortega ruiz <jaortega@acm.org>
+**
+** 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"
+#include <unistd.h>
+#include "xmix_vm.h"
+#include "mix_vm_dump.h"
+
+/* Create/destroy a dump context */
+mix_dump_context_t *
+mix_dump_context_new(gint fd, mix_address_t begin, mix_address_t end,
+ guint32 options)
+{
+ mix_dump_context_t *result = NULL;
+ GIOChannel *channel = NULL;
+
+ if ( fd == MIX_DUMP_DEF_CHANNEL ) fd = STDIN_FILENO;
+ channel = g_io_channel_unix_new (fd);
+ g_return_val_if_fail (channel != NULL, NULL);
+
+ if ( begin > end ) begin = end;
+ if ( end >= MEM_CELLS_NO_ ) end = MEM_CELLS_NO_;
+
+ result = g_new (mix_dump_context_t,1);
+ g_return_val_if_fail (result != NULL, NULL);
+
+ result->options = options;
+ result->begin = begin;
+ result->end = end;
+ result->channel = channel;
+
+ return result;
+}
+
+void
+mix_dump_context_delete (mix_dump_context_t *dc)
+{
+ g_return_if_fail (dc != NULL);
+ g_io_channel_close (dc->channel);
+ g_free (dc);
+}
+
+gboolean /* TRUE if success */
+mix_dump_context_set_channel (mix_dump_context_t *dc, gint fd)
+{
+ g_return_val_if_fail (dc != NULL, FALSE);
+ g_io_channel_close (dc->channel);
+ dc->channel = g_io_channel_unix_new (fd == MIX_DUMP_DEF_CHANNEL?
+ STDERR_FILENO : fd);
+ return ( dc->channel != NULL );
+}
+
+/* Use the dump context */
+#define WORD_FMT_ "%s %02d %02d %02d %02d %02d (%010ld)"
+#define SHORT_FMT_ "%s %02d %02d (%04d)"
+#define WORD_SIGN_(w) mix_word_is_negative (w)? "-":"+"
+#define SHORT_SIGN_(s) mix_short_is_negative (s)? "-":"+"
+#define WORD_ABS_(w) mix_word_magnitude (w)
+#define SHORT_ABS_(s) mix_short_magnitude (s)
+#define WORD_BYTE_(w,i) mix_byte_new (mix_word_magnitude (w)>>(6*(5-i)))
+#define SHORT_BYTE_(s,i) mix_byte_new (mix_short_magnitude (s)>>(6*(2-i)))
+#define WORD_ARGS_(w) WORD_SIGN_ (w), WORD_BYTE_ (w,1), WORD_BYTE_ (w,2), \
+ WORD_BYTE_ (w,3), WORD_BYTE_ (w,4), WORD_BYTE_ (w,5), WORD_ABS_ (w)
+#define SHORT_ARGS_(s) SHORT_SIGN_ (s), SHORT_BYTE_ (s,1), SHORT_BYTE_ (s,2), \
+ SHORT_ABS_ (s)
+
+static gboolean
+write_buffer_ (const gchar *buf, guint len, GIOChannel *io)
+{
+ guint k, err;
+
+ while ( len > 0 ) {
+ err = g_io_channel_write (io, (gchar *) buf, len, &k);
+ g_return_val_if_fail (err == G_IO_ERROR_NONE ||
+ err == G_IO_ERROR_AGAIN, FALSE);
+ len -= k;
+ }
+ return TRUE;
+}
+
+
+
+void
+mix_vm_dump (const mix_vm_t *vm, const mix_dump_context_t *dc)
+{
+ static const guint BUF_LEN = 40;
+ gchar buf[BUF_LEN];
+ guint j, i;
+
+ g_return_if_fail (vm != NULL);
+ g_return_if_fail (dc != NULL);
+
+
+ if ( (dc->options & MIX_DUMP_rA) == MIX_DUMP_rA )
+ {
+ mix_word_t rA = get_rA_ (vm);
+ guint k = g_snprintf (buf, BUF_LEN, "rA: " WORD_FMT_ "\n",
+ WORD_ARGS_ (rA));
+ g_return_if_fail (write_buffer_ (buf, k, dc->channel));
+ }
+
+ if ( (dc->options & MIX_DUMP_rX) == MIX_DUMP_rX )
+ {
+ mix_word_t rX = get_rX_ (vm);
+ guint k = g_snprintf (buf, BUF_LEN, "rX: " WORD_FMT_ "\n",
+ WORD_ARGS_ (rX));
+ g_return_if_fail (write_buffer_ (buf, k, dc->channel));
+ }
+
+ if ( (dc->options & MIX_DUMP_rJ) == MIX_DUMP_rJ )
+ {
+ mix_short_t rJ = get_rJ_ (vm);
+ guint k = g_snprintf (buf, BUF_LEN, "rJ: " SHORT_FMT_ "\n",
+ SHORT_ARGS_ (rJ));
+ g_return_if_fail (write_buffer_ (buf, k, dc->channel));
+ }
+
+ for (j = 0, i = 0; j < IREG_NO_; ++j)
+ {
+ if ( (dc->options & (MIX_DUMP_rI1<<j)) == (MIX_DUMP_rI1<<j) )
+ {
+ mix_short_t rI = mix_word_to_short_fast (get_rI_ (vm, j+1));
+ guint k = g_snprintf (buf, BUF_LEN, "rI%d: " SHORT_FMT_ "\t",
+ j+1, SHORT_ARGS_ (rI));
+ g_return_if_fail (write_buffer_ (buf, k, dc->channel));
+ i++;
+ }
+ if ( i%2 == 0 && i != 0 )
+ g_return_if_fail (write_buffer_ ("\n", 1, dc->channel));
+ }
+
+ if ( i%2 == 1 )
+ g_return_if_fail (write_buffer_ ("\n", 1, dc->channel));
+
+ if ( (dc->options & MIX_DUMP_OVER) == MIX_DUMP_OVER )
+ {
+ guint k = g_snprintf (buf, BUF_LEN, _("Overflow: %s\n"),
+ get_over_ (vm)? "T":"F");
+ g_return_if_fail (write_buffer_ (buf, k, dc->channel));
+ }
+
+ if ( (dc->options & MIX_DUMP_CMP) == MIX_DUMP_CMP )
+ {
+ guint k;
+ const gchar *val = "?";
+ switch (get_cmp_ (vm))
+ {
+ case mix_LESS:
+ val = "L";
+ break;
+ case mix_GREAT:
+ val = "G";
+ break;
+ case mix_EQ:
+ val = "E";
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ k = g_snprintf (buf, BUF_LEN, _("Cmp: %s\n"), val);
+ g_return_if_fail (write_buffer_ (buf, k, dc->channel));
+ }
+
+ if ( (dc->options & MIX_DUMP_CELLS) == MIX_DUMP_CELLS )
+ {
+ for (j = dc->begin; j < dc->end; ++j)
+ {
+ mix_word_t cell = get_cell_ (vm,j);
+ guint k = g_snprintf (buf, BUF_LEN, "%04d: " WORD_FMT_ "\n", j,
+ WORD_ARGS_ (cell));
+ g_return_if_fail (write_buffer_ (buf, k, dc->channel));
+ }
+ }
+}
+