/* ---------------------- mix_vm_dump.c : * Implementation of the functions declared in mix_vm_dump.h * ------------------------------------------------------------------ ** Copyright (C) 2000 jose antonio ortega ruiz ** ** 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 #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); 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<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)); } } }