The beginnings of the new bytecode interpreter.

Estimated hours taken: 40

 The beginnings of the new bytecode interpreter. Probably
 just over half the code is the same or a
 superficially modified revision of the old one.

bytecode/mb_bytecode.c
bytecode/mb_bytecode.h
	Almost identical. Only real change is made MB_read_cstring not use
	any static variables

bytecode/mb_disasm.c
bytecode/mb_disasm.h
	Again, code very similar. Changed all the functions to write to a
	buffer instead of a file and to allow for bytecode indenting. Output
	format string for some instructions changed (hopefully more menaingful
	than just a dump of numbers)

bytecode/mb_machine.c
bytecode/mb_machine.h
	(completely different from old machine.c)
	The actual part that contains an abstract machine.
	 The rest is really just support code.
	 The instruction_table array is how instructions are dispatched. Look
	 at instr_xxxx for the actual interpreter code. Not all instructions
	 are implemented. MB_step and MB_run execute the actual
	  interpreting code

bytecode/mb_machine_show.h
bytecode/mb_machine_show.c
	  displays output showing the state of the machine


bytecode/mb_mem.c
bytecode/mb_mem.h
	  Identical to old mem apart from file name changes

bytecode/mb_util.c
bytecode/mb_util.h
	  took out strdup (not needed) and changed some comments

bytecode/mb_stack.c
bytecode/mb_stack.h
	  word based stack that will reallocate itself if it needs to


bytecode/mbi.c
	  front end for bytecode interpreter

bytecode/mdis.c
	  disassembles a file and dumps it to the screen
This commit is contained in:
Levi Cameron
2001-01-24 07:42:29 +00:00
parent cf2b6c80df
commit 2ca8f64b76
18 changed files with 5015 additions and 129 deletions

View File

@@ -17,7 +17,7 @@ INCPATH = -I$(RUNTIME_DIR) \
-I$(BOEHM_GC_DIR) \
-I$(BOEHM_GC_DIR)/include \
-I.
LIBPATH = -L$(RUNTIME_DIR) -L$(BOEHM_GC_DIR)
LIBPATH = -L$(RUNTIME_DIR) -L$(BOEHM_GC_DIR) -L.
CFLAGS = -g $(EXTRA_CFLAGS) -D_POSIX_SOURCE $(INCPATH) -DDEBUGGING
MGNUC = MERCURY_ALL_C_INCL_DIRS="$(INCPATH)" $(SCRIPTS_DIR)/mgnuc
MGNUCFLAGS = $(CFLAGS)
@@ -37,14 +37,15 @@ HDRS = $(MB_HDRS) getopt.h
ORIG_CS = bytecode.c dict.c disasm.c machine.c mbi.c mbi_main.c \
mdis.c mem.c static_data.c template.c util.c
LIBS = -lmer ` \
case "$(GRADE)" in \
*.par*.gc*.prof*) echo "-lpar_gc_prof" ;; \
*.par*.gc*) echo "-lpar_gc" ;; \
*.gc*.prof*) echo "-lgc_prof" ;; \
*.gc*) echo "-lgc" ;; \
esac \
`
#LIBS = -lmer ` \
# case "$(GRADE)" in \
# *.par*.gc*.prof*) echo "-lpar_gc_prof" ;; \
# *.par*.gc*) echo "-lpar_gc" ;; \
# *.gc*.prof*) echo "-lgc_prof" ;; \
# *.gc*) echo "-lgc" ;; \
# esac \
# `
LIBS = libgc.a
#-----------------------------------------------------------------------------#

View File

@@ -3,7 +3,7 @@
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
**
** $Id: bytecode.h,v 1.12 1997-07-27 14:59:19 fjh Exp $
** $Id: bytecode.h,v 1.13 2001-01-24 07:42:22 lpcam Exp $
*/
/*
@@ -14,7 +14,7 @@
#ifndef MB_BYTECODE_H
#define MB_BYTECODE_H
#include "conf.h"
#include "mercury_conf.h"
#include "mercury_types.h"
#include "mercury_float.h"
#include "gc.h"
@@ -43,13 +43,25 @@ typedef short
typedef char*
MB_CString;
typedef MR_Word
MB_Word;
typedef MR_Integer
MB_Integer;
typedef MR_Float
MB_Float;
typedef MR_Float64
MB_Float64;
typedef struct MB_Tag_struct {
MB_Byte id;
union {
MB_Byte primary;
struct {
MB_Byte primary;
Word secondary;
MB_Word secondary;
} pair;
MB_Byte enum_tag;
} opt;
@@ -84,8 +96,8 @@ typedef struct MB_Op_arg_struct {
MB_Byte id;
union {
MB_Short var;
Integer int_const;
Float float_const;
MB_Integer int_const;
MB_Float float_const;
} opt;
} MB_Op_arg;
@@ -122,9 +134,9 @@ typedef struct MB_Cons_id_struct {
MB_Short arity;
MB_Tag tag;
} cons;
Integer int_const;
MB_Integer int_const;
MB_CString string_const;
Float float_const;
MB_Float float_const;
struct {
MB_CString module_id;
MB_CString pred_id;

1218
bytecode/mb_bytecode.c Normal file

File diff suppressed because it is too large Load Diff

439
bytecode/mb_bytecode.h Normal file
View File

@@ -0,0 +1,439 @@
/*
** Copyright (C) 1997 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
**
** $Id: mb_bytecode.h,v 1.1 2001-01-24 07:42:22 lpcam Exp $
**
** This file contains the bytecode format and data types
** This must be the same as that in compiler/bytecode.m
*/
#ifndef MB_BYTECODE_H
#define MB_BYTECODE_H
#include <stdio.h>
#include "mercury_conf.h"
#include "mercury_types.h"
#include "mercury_float.h"
#include "mb_util.h"
/* XXX expects sizeof(unsigned char) == 1 */
typedef unsigned char
MB_Byte;
typedef MR_INT_LEAST16_TYPE
MB_Short;
typedef MR_Word
MB_Word;
typedef MR_Integer
MB_Integer;
typedef MR_Float
MB_Float;
typedef MR_Float64
MB_Float64;
typedef MR_Bool
MB_Bool;
typedef struct MB_Tag_struct {
MB_Byte id;
union {
MB_Byte primary;
struct {
MB_Byte primary;
MB_Word secondary;
} pair;
MB_Byte enum_tag;
} opt;
} MB_Tag;
/*
* Possible values for Tag.id ...
*/
#define MB_TAG_SIMPLE 0
#define MB_TAG_COMPLICATED 1
#define MB_TAG_COMPLICATED_CONSTANT 2
#define MB_TAG_ENUM 3
#define MB_TAG_NONE 4
typedef MB_Byte
MB_Determinism;
/*
* Possible values for Determinism ...
*/
#define MB_DET_DET 0
#define MB_DET_SEMIDET 1
#define MB_DET_MULTIDET 2
#define MB_DET_NONDET 3
#define MB_DET_CC_MULTIDET 4
#define MB_DET_CC_NONDET 5
#define MB_DET_ERRONEOUS 6
#define MB_DET_FAILURE 7
typedef struct MB_Op_arg_struct {
MB_Byte id;
union {
MB_Short var;
MB_Integer int_const;
MB_Float float_const;
} opt;
} MB_Op_arg;
/*
* Possible values for Op_arg.id
*/
#define MB_ARG_VAR 0
#define MB_ARG_INT_CONST 1
#define MB_ARG_FLOAT_CONST 2
typedef MB_Byte
MB_Direction;
typedef struct MB_Var_dir_struct {
MB_Short var;
MB_Direction dir;
} MB_Var_dir;
/*
* Possible values for Direction ...
*/
#define MB_DIR_TO_ARG 0
#define MB_DIR_TO_VAR 1
#define MB_DIR_TO_NONE 2
typedef struct MB_Cons_id_struct {
MB_Byte id;
union {
struct {
MB_CString module_id;
MB_CString string;
MB_Short arity;
MB_Tag tag;
} cons;
MB_Integer int_const;
MB_CString string_const;
MB_Float float_const;
struct {
MB_CString module_id;
MB_CString pred_id;
MB_Short arity;
MB_Byte proc_id;
} pred_const;
struct {
MB_CString module_id;
MB_CString pred_id;
MB_Short arity;
MB_Byte proc_id;
} code_addr_const;
struct {
MB_CString module_id;
MB_CString type_name;
MB_Byte type_arity;
} base_type_info_const;
struct {
MB_Byte ch;
} char_const;
} opt;
} MB_Cons_id;
/*
* Possible values for Cons_id.id ...
*/
#define MB_CONSID_CONS 0
#define MB_CONSID_INT_CONST 1
#define MB_CONSID_STRING_CONST 2
#define MB_CONSID_FLOAT_CONST 3
#define MB_CONSID_PRED_CONST 4
#define MB_CONSID_CODE_ADDR_CONST 5
#define MB_CONSID_BASE_TYPE_INFO_CONST 6
#define MB_CONSID_CHAR_CONST 7
typedef union MB_Bytecode_Arg_tag {
struct {
MB_CString pred_name; /* XXX: malloc */
MB_Short pred_arity;
MB_Byte is_func;
MB_Short proc_count;
} enter_pred;
struct {
} endof_pred;
struct {
MB_Byte proc_id;
MB_Determinism det;
MB_Short label_count;
MB_Short temp_count;
MB_Short list_length;
MB_CString *var_info_list; /* XXX: malloc */
/* index onto label heap for label indexes
* (not in the file) */
MB_Word label_index;
} enter_proc;
struct {
} endof_proc;
struct {
MB_Short label;
} label;
struct {
MB_Short end_label;
} enter_disjunction;
struct {
} endof_disjunction;
struct {
MB_Short next_label;
} enter_disjunct;
struct {
MB_Short label; /* XXX: what's label for? */
} endof_disjunct;
struct {
MB_Short var;
MB_Short end_label;
} enter_switch;
struct {
} endof_switch;
struct {
MB_Cons_id cons_id;
MB_Short next_label;
} enter_switch_arm;
struct {
MB_Short label; /* XXX: what's this label for? */
} endof_switch_arm;
struct {
MB_Short else_label;
MB_Short end_label;
MB_Short frame_ptr_tmp;
} enter_if;
struct {
MB_Short frame_ptr_tmp;
} enter_then;
struct {
MB_Short follow_label;
} endof_then; /* XXX: should rename to enter_else */
struct {
} endof_if;
struct {
MB_Short end_label;
} enter_negation;
struct {
} endof_negation;
struct {
MB_Short temp;
} enter_commit;
struct {
MB_Short temp;
} endof_commit;
struct {
MB_Short to_var;
MB_Short from_var;
} assign;
struct {
MB_Short var1;
MB_Short var2;
} test;
struct {
MB_Short to_var;
MB_Cons_id consid;
MB_Short list_length;
MB_Short *var_list; /* XXX: malloc */
} construct;
struct {
MB_Short from_var;
MB_Cons_id consid;
MB_Short list_length;
MB_Short *var_list; /* XXX: malloc */
} deconstruct;
struct {
MB_Short to_var;
MB_Cons_id consid;
MB_Short list_length;
MB_Var_dir *var_dir_list;/* XXX: malloc */
} complex_construct;
struct {
MB_Short from_var;
MB_Cons_id consid;
MB_Short list_length;
MB_Var_dir *var_dir_list;/* XXX: malloc */
} complex_deconstruct;
struct {
MB_Byte to_reg;
MB_Short from_var;
} place_arg;
struct {
MB_Byte from_reg;
MB_Short to_var;
} pickup_arg;
struct {
MB_CString module_id; /* XXX: malloc */
MB_CString pred_id; /* XXX: malloc */
MB_Short arity;
MB_Byte proc_id;
/* code address to call (generated when file is loaded) */
MB_Word adr;
} call;
struct {
MB_Short pred_var;
MB_Short in_var_count;
MB_Short out_var_count;
MB_Determinism det;
} higher_order_call;
struct {
MB_Byte binop;
MB_Op_arg arg1;
MB_Op_arg arg2;
MB_Short to_var;
} builtin_binop;
struct {
MB_Byte unop;
MB_Op_arg arg;
MB_Short to_var;
} builtin_unop;
struct {
MB_Byte binop;
MB_Op_arg arg1;
MB_Op_arg arg2;
} builtin_bintest;
struct {
MB_Byte unop;
MB_Op_arg arg;
} builtin_untest;
struct {
} semidet_succeed;
struct {
} semidet_success_check;
struct {
} fail;
struct {
/* XXX: is this int or short?? */
MB_Short line_number;
} context;
struct {
} not_supported;
} MB_Bytecode_Arg;
typedef struct MB_Bytecode_struct {
MB_Byte id; /* Which bytecode instruction. e.g. BC_fail */
MB_Bytecode_Arg opt;
} MB_Bytecode;
/*
** Possible Bytecode.id values
*/
#define MB_BC_enter_pred 0
#define MB_BC_endof_pred 1
#define MB_BC_enter_proc 2
#define MB_BC_endof_proc 3
#define MB_BC_label 4
#define MB_BC_enter_disjunction 5
#define MB_BC_endof_disjunction 6
#define MB_BC_enter_disjunct 7
#define MB_BC_endof_disjunct 8
#define MB_BC_enter_switch 9
#define MB_BC_endof_switch 10
#define MB_BC_enter_switch_arm 11
#define MB_BC_endof_switch_arm 12
#define MB_BC_enter_if 13
#define MB_BC_enter_then 14
/* XXX: enter_else would be a better name than endof_then */
#define MB_BC_endof_then 15
#define MB_BC_endof_if 16
#define MB_BC_enter_negation 17
#define MB_BC_endof_negation 18
#define MB_BC_enter_commit 19
#define MB_BC_endof_commit 20
#define MB_BC_assign 21
#define MB_BC_test 22
#define MB_BC_construct 23
#define MB_BC_deconstruct 24
#define MB_BC_complex_construct 25
#define MB_BC_complex_deconstruct 26
#define MB_BC_place_arg 27
#define MB_BC_pickup_arg 28
#define MB_BC_call 29
#define MB_BC_higher_order_call 30
#define MB_BC_builtin_binop 31
#define MB_BC_builtin_unop 32
#define MB_BC_builtin_bintest 33
#define MB_BC_builtin_untest 34
#define MB_BC_semidet_succeed 35
#define MB_BC_semidet_success_check 36
#define MB_BC_fail 37
#define MB_BC_context 38
#define MB_BC_not_supported 39
/* These are used internally by the interpreter */
/* all codes above MB_BC_debug are debugging values */
#define MB_BC_debug 254
#define MB_BC_debug_trap 254
#define MB_BC_debug_invalid 255
/*#define MB_BC_noop 255*/
/*
* Read the next bytecode from the stream fp.
* If no bytecode can be read, return FALSE.
* Otherwise, return TRUE.
*/
MB_Bool
MB_read_bytecode(FILE *fp, MB_Bytecode *bc_p);
/*
* Read the bytecode version number from the stream fp.
* If the version number cannot be read, return FALSE.
* Otherwise, return TRUE.
*/
MB_Bool
MB_read_bytecode_version_number(FILE *fp, MB_Short *version_number_p);
#endif /* MB_BYTECODE_H */

1005
bytecode/mb_disasm.c Normal file

File diff suppressed because it is too large Load Diff

30
bytecode/mb_disasm.h Normal file
View File

@@ -0,0 +1,30 @@
/*
** Copyright (C) 1997 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
**
** $Id: mb_disasm.h,v 1.1 2001-01-24 07:42:23 lpcam Exp $
*/
#ifndef MB_DISASM_H
#define MB_DISASM_H
#include <stdio.h>
#include "mb_bytecode.h"
#include "mb_machine.h"
/* Fills a string buffer with the name of a bytecode
** returns the new indent level after the instruction
*/
int
MB_str_bytecode(MB_Bytecode bc, char* buffer, int buffer_len, int indent_level);
/* displays a code listing (see source file for argument description) */
void
MB_listing(MB_Machine_State* ms, FILE* fp, MB_Word start, MB_Word end);
#endif /* MB_DISASM_H */

1114
bytecode/mb_machine.c Normal file

File diff suppressed because it is too large Load Diff

198
bytecode/mb_machine.h Normal file
View File

@@ -0,0 +1,198 @@
/*
** Copyright (C) 1997 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
**
** $Id: mb_machine.h,v 1.1 2001-01-24 07:42:25 lpcam Exp $
**
** Abstract mercury machine
**
*/
#ifndef MB_MACHINE_H
#define MB_MACHINE_H
#include <stdio.h>
#include "mb_bytecode.h"
#include "mb_util.h"
#include "mb_stack.h"
#define MB_MACHINEREGS 21
/* Don't directly access data from a machine state; go through the
** wrappers below which provide some measure of error checking
** (C++, C++, oh where art thou C++?)
*/
typedef struct MB_Machine_State_Tag {
MB_Word ip; /* next instruction pointer*/
/* det stack */
struct {
MB_Word succip; /* sucess return address */
MB_Stack stack; /* stack data */
} det;
/* nondet stack */
struct {
MB_Word curfr; /* stack frame of current procedure */
MB_Word maxfr; /* highest frame on nondet stack */
MB_Stack stack; /* stack data */
} nondet;
/* heap */
struct {
/* XXX */
} heap;
/* MB_Bytecode is 44 bytes long - this is obviously very inefficient
** for most instructions.
**
** All code accesses should go through MB_get_code so the following
** is abstracted away:
**
** code_id is an array of bytecode types
** code_index is the index into code_data for the bytecode arguments
** code_data is the bytecode arguments
**
** This way each instruction takes 5 bytes + argument size
** rather than 1 byte + size of largest possible argument
*/
struct {
MB_Word count; /* number of instructions */
MB_Byte* id; /* instruction types */
MB_Stack data_index; /* index into code data for aguments */
MB_Stack data; /* argument data stack */
} code;
#define CODE_DATA_NONE 0 /* If a bytecode's data_index is this
** then we will assume it has no data
*/
MB_Word reg[MB_MACHINEREGS]; /* machine regs */
/* For the simulation only (not part of the abstract machine) */
/* Call stack: each stack frame consists of:
** stack[sp-1]: index into code.data[] containing info on current proc
** stack[sp-2]: index into code.data[] containing info on previous proc
** etc.
*/
struct {
MB_Stack stack;
} call;
/* high-water marked */
struct {
MB_Stack stack;
} label;
} MB_Machine_State;
#define MB_CODE_INVALID_ADR ((MB_Word)-1)
typedef struct MB_Stack_Frame_Tag {
MB_Word prevfr;
MB_Word succfr;
MB_Word redoip;
MB_Word succip;
} MB_Stack_Frame;
/* Get the value of a register */
MB_Word MB_reg_get(MB_Machine_State* ms, MB_Word idx);
/* Set the value of a register */
void MB_reg_set(MB_Machine_State* ms, MB_Word idx, MB_Word value);
/* Get/set the next instruction pointer */
MB_Word MB_ip_get(MB_Machine_State* ms);
void MB_ip_set(MB_Machine_State* ms, MB_Word);
/* Get/set the success instruction pointer */
MB_Word MB_succip_get(MB_Machine_State* ms);
void MB_succip_set(MB_Machine_State* ms, MB_Word);
/* Read the bytecode at a given address */
MB_Bytecode MB_code_get(MB_Machine_State* ms, MB_Word adr);
/* Get the bytecode type at a given address */
MB_Byte MB_code_get_id(MB_Machine_State* ms, MB_Word adr);
/* Get the bytecode argument at a given address */
MB_Bytecode_Arg*MB_code_get_arg(MB_Machine_State* ms, MB_Word adr);
/* Get the predicate in which the following address resides */
MB_Bytecode MB_code_get_pred(MB_Machine_State* ms, MB_Word adr);
MB_Word MB_code_get_pred_adr(MB_Machine_State* ms, MB_Word adr);
/* Get the procedure in which the following address resides */
MB_Bytecode MB_code_get_proc(MB_Machine_State* ms, MB_Word adr);
/* Return how many bytecodes there are */
MB_Word MB_code_size(MB_Machine_State* ms);
/* Get/set a variable on the det stack */
MB_Word MB_var_get(MB_Machine_State* ms, MB_Word idx);
void MB_var_set(MB_Machine_State* ms, MB_Word idx, MB_Word value);
/* The positions of frame variables*/
#define MB_FRAME_PREVFR 0
#define MB_FRAME_REDOIP 1
#define MB_FRAME_REDOFR 2
#define MB_FRAME_SUCCIP 3
#define MB_FRAME_SUCCFR 4
#define MB_FRAME_SIZE 5
#define MB_FRAME_TEMP_SIZE 3
/* Get/set an entry on the nondet stack, relative to curfr */
/* index zero is the topmost element */
MB_Word MB_frame_get(MB_Machine_State* ms, MB_Word idx);
void MB_frame_set(MB_Machine_State* ms, MB_Word idx, MB_Word val);
/* get/set a value inside a temporary frame */
MB_Word MB_frame_temp_get(MB_Machine_State* ms,
MB_Word frame_num, MB_Word idx);
void MB_frame_temp_set(MB_Machine_State* ms,
MB_Word frame_num, MB_Word idx, MB_Word val);
/* Get/set a variable in the current stack frame variable list */
MB_Word MB_frame_var_get(MB_Machine_State* ms, MB_Word idx);
void MB_frame_var_set(MB_Machine_State* ms, MB_Word idx, MB_Word val);
/* add/remove a number of temporary stack frames to the nondet stack */
void MB_frame_temp_add(MB_Machine_State* ms, MB_Word count);
void MB_frame_temp_remove(MB_Machine_State* ms, MB_Word count);
/* add/remove an ordinary nondet stack frame */
void MB_frame_add(MB_Machine_State* ms, MB_Word var_count);
void MB_frame_remove(MB_Machine_State* ms, MB_Word var_count);
/* Load a program from a file */
/* Returns false for failure */
MB_Machine_State*MB_load_program(FILE* fp);
MB_Machine_State*MB_load_program_name(MB_CString filename);
MB_Bool MB_reset_program(MB_Machine_State* ms);
void MB_unload_program(MB_Machine_State* ms);
/* Display the current state of the machine */
void MB_show_state(MB_Machine_State* ms, FILE* fp);
/* Display the call stack of the machine */
void MB_show_call(MB_Machine_State* ms, FILE* fp);
/* Single step execute */
void MB_step(MB_Machine_State* ms);
/* Single step execute over predicates */
void MB_step_over(MB_Machine_State* ms);
/* Run until exception */
void MB_run(MB_Machine_State* ms);
#endif /* MB_MACHINE_H */

304
bytecode/mb_machine_show.c Normal file
View File

@@ -0,0 +1,304 @@
/*
** Copyright (C) 2000 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
**
** $Id: mb_machine_show.c,v 1.1 2001-01-24 07:42:26 lpcam Exp $
*/
/* Imports */
#include <stdio.h>
#include <assert.h>
#include "mb_stack.h"
#include "mb_disasm.h"
#include "mb_machine_show.h"
/* Exported definitions */
void MB_show_state(MB_Machine_State* ms, FILE* fp);
void MB_show_call(MB_Machine_State* ms, FILE* fp);
/* Local declarations */
static char
rcs_id[] = "$Id: mb_machine_show.c,v 1.1 2001-01-24 07:42:26 lpcam Exp $";
#define NREGS 5
#define NSTACK 10
typedef struct {
char reg_name[NREGS][10+1];
char reg[NREGS][8+1];
char succip[9+1];
char succip_str[25+1];
char detsp[8+1];
char det_name[NSTACK][10+1];
char det[NSTACK][8+1];
char det_str[NSTACK][16+1];
char nondetsp[8+1];
char nondet_name[NSTACK][10+1];
char nondet[NSTACK][8+1];
char nondet_str[NSTACK][10+1];
} MB_View_Vars; /* structure containing variable names & values for output */
static void pad_space(char* buffer, MB_Word len);
static MB_View_Vars vars_state(MB_Machine_State* ms);
/* appends spaces to the end of a string so that a buffer is filled (includes null) */
static void
pad_space(char* buffer, MB_Word len)
{
if (buffer == NULL && len == 0) return;
assert(buffer != NULL);
/* find the null terminator */
while (len > 0) {
if (*buffer == 0) break;
buffer++;
len--;
}
while (len > 1) {
buffer++[0] = ' ';
len--;
}
*buffer = 0;
}
/* Returns a structure containing formatted strings with
** various state variables in (so it is easier to print
** multiple columns on stdout)
*/
static MB_View_Vars
vars_state(MB_Machine_State* ms)
{
MB_View_Vars vars;
MB_Word ip = MB_ip_get(ms);
MB_Bytecode cur_proc = MB_code_get_proc(ms, ip);
/* display the succip */
{
MB_Word succip = MB_succip_get(ms);
MB_Bytecode succ_pred = MB_code_get_pred(ms, succip);
if (succip == MB_CODE_INVALID_ADR) {
snprintf(vars.succip, sizeof(vars.succip),
"(invalid)");
snprintf(vars.succip_str, sizeof(vars.succip_str),
" ");
} else {
snprintf(vars.succip, sizeof(vars.succip),
"%08x",
(int)succip);
snprintf(vars.succip_str, sizeof(vars.succip_str),
"(%s/%d)",
succ_pred.opt.enter_pred.pred_name,
(int)succ_pred.opt.enter_pred.pred_arity);
}
}
/* display the register variables */
{
MB_Word j;
for (j = 0; j < NREGS; j++) {
snprintf(vars.reg_name[j], sizeof(vars.reg_name[j]),
"reg[%02x]",
(int)j);
snprintf(vars.reg[j], sizeof(vars.reg[j]),
"%08x",
(int)MB_reg_get(ms, j));
}
}
/* display the det stack */
{
MB_Word j;
snprintf(vars.detsp, sizeof(vars.detsp),
"%08x",
(int)MB_stack_size(&ms->det.stack));
/* display only the local variables on the stack */
if (MB_code_get_id(ms, ip) != MB_BC_enter_proc) {
for (j = 0;
(j < cur_proc.opt.enter_proc.list_length) &&
(j < NSTACK);
j++)
{
snprintf(vars.det_name[j], sizeof(vars.det_name[j]),
"detstack[%1x]",
(int)j);
snprintf(vars.det[j], sizeof(vars.det[j]),
"%08x",
(int)MB_var_get(ms, j));
snprintf(vars.det_str[j], sizeof(vars.det_name[j]),
"%s",
cur_proc.opt.enter_proc.var_info_list[j]);
}
} else {
j = 0;
}
/* fill the rest with blanks*/
for (; j < NSTACK; j++) {
snprintf(vars.det_name[j], sizeof(vars.det_name[j]), " ");
snprintf(vars.det[j], sizeof(vars.det[j]), " ");
snprintf(vars.det_str[j], sizeof(vars.det_name[j]), " ");
}
}
/* display the nondet stack */
{
MB_Word j;
snprintf(vars.nondetsp, sizeof(vars.nondetsp),
"%08x",
ms->nondet.curfr);
for (j = 0;
(j < NSTACK) &&
((ms->nondet.curfr+j) < MB_stack_size(&ms->nondet.stack));
j++)
{
snprintf(vars.nondet_name[j], sizeof(vars.nondet_name[j]),
"nondet[%1x]",
(int)j);
snprintf(vars.nondet[j], sizeof(vars.nondet[j]),
"%08x",
(int)MB_frame_get(ms, j));
snprintf(vars.nondet_str[j], sizeof(vars.nondet_name[j]),
"%s",
( (j == MB_FRAME_PREVFR) ? "prevfr" :
(j == MB_FRAME_REDOIP) ? "redoip" :
(j == MB_FRAME_REDOFR) ? "redofr" :
(j == MB_FRAME_SUCCIP) ? "[succip?]" :
(j == MB_FRAME_SUCCFR) ? "[succfr?]" :
" ")
);
}
/* fill the rest with blanks */
for (; j < NSTACK; j++) {
snprintf(vars.nondet_name[j], sizeof(vars.nondet_name[j]), " ");
snprintf(vars.nondet[j], sizeof(vars.nondet[j]), " ");
snprintf(vars.nondet_str[j], sizeof(vars.nondet_name[j]), " ");
}
}
/* pad with spaces */
{
#define PAD(x) pad_space(vars.##x, sizeof(vars.##x))
MB_Word i;
for (i = 0; i < NREGS; i++) {
PAD(reg_name[i]);
PAD(reg[i]);
}
PAD(succip);
PAD(succip_str);
PAD(detsp);
PAD(nondetsp);
for (i = 0; i < NSTACK; i++) {
PAD(det_name[i]);
PAD(det[i]);
PAD(det_str[i]);
PAD(nondet_name[i]);
PAD(nondet[i]);
PAD(nondet_str[i]);
}
}
return vars;
}
/* Display the current state of the machine */
void
MB_show_state(MB_Machine_State* ms, FILE* fp)
{
char buffer[78];
MB_Word ip = MB_ip_get(ms);
/* Work out what predicate & proc we are in */
MB_Bytecode cur_pred = MB_code_get_pred(ms, ip);
MB_Bytecode cur_proc = MB_code_get_proc(ms, ip);
/* Show the call stack */
MB_show_call(ms, fp);
fprintf(fp, "----------------------------------------------------------------------------\n");
if (ip >= MB_code_size(ms) || ip < 0) {
fprintf(fp, " Invalid execution address\n");
return;
}
/* Show what predicate we are in */
MB_str_bytecode(cur_pred, buffer, sizeof(buffer), 0);
fprintf(fp, "%s\n", buffer);
MB_str_bytecode(cur_proc, buffer, sizeof(buffer), 1);
fprintf(fp, "%s\n", buffer);
fprintf(fp, "\n");
/* show the surrounding lines of code */
MB_listing(ms, fp, ip-2, ip+4);
fprintf(fp, "\n");
/* Print variables */
{
MB_View_Vars vars = vars_state(ms);
MB_Word j;
fprintf(fp, " succip %s %s\n", vars.succip, vars.succip_str);
for (j = 0; j < NREGS; j++) {
fprintf(fp, " %s %s \n",
vars.reg_name[j],
vars.reg[j]
);
}
fprintf(fp, " det.sp %s curfr %s\n",
vars.detsp, vars.nondetsp);
for (j = 0; j < NSTACK; j++) {
fprintf(fp, " %s %s %s %s %s %s\n",
vars.det_name[j],
vars.det[j],
vars.det_str[j],
vars.nondet_name[j],
vars.nondet[j],
vars.nondet_str[j]);
}
}
fprintf(fp, "\n");
} /* MB_show_state */
/* Display the call stack of the machine */
void
MB_show_call(MB_Machine_State* ms, FILE* fp)
{
char buffer[76];
MB_Word i;
MB_Word num_calls = MB_stack_size(&ms->call.stack);
fprintf(fp, "Call stack: \n");
for (i = 0; i < num_calls; i++) {
MB_Bytecode bc = MB_code_get_pred(ms, MB_stack_peek(&ms->call.stack, i));
MB_str_bytecode(bc, buffer, sizeof(buffer), 0);
fprintf(fp, "%2x %s\n", i, buffer);
bc = MB_code_get(ms, MB_stack_peek(&ms->call.stack, i));
MB_str_bytecode(bc, buffer, sizeof(buffer), 0);
fprintf(fp, " %s\n", buffer);
}
}

View File

@@ -0,0 +1,29 @@
/*
** Copyright (C) 1997 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
**
** $Id: mb_machine_show.h,v 1.1 2001-01-24 07:42:27 lpcam Exp $
**
** Abstract mercury machine
**
*/
#ifndef MB_MACHINE_SHOW_H
#define MB_MACHINE_SHOW_H
#include <stdio.h>
#include "mb_machine.h"
/* Display the current state of the machine */
void MB_show_state(MB_Machine_State* ms, FILE* fp);
/* Display the call stack of the machine */
void MB_show_call(MB_Machine_State* ms, FILE* fp);
#endif /* MB_MACHINE_SHOW_H */

108
bytecode/mb_mem.c Normal file
View File

@@ -0,0 +1,108 @@
/*
** Copyright (C) 1997 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
**
** $Id:"
*/
/* Imports */
#include <stdlib.h>
#include <string.h>
#include "mb_mem.h"
#include "mb_util.h"
/* Exported definitions */
/* Local declarations */
static char
rcs_id[] = "$Id:";
/* Implementation */
/*
* Make sure the size of guard_bytes is a multiple of 8 to ensure we
* don't get unaligned accesses, even on 64-bit architectures.
*/
static const unsigned char
guard_bytes[] = {0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5};
/* Implementation */
void*
MB_malloc(size_t size)
{
size_t real_size;
size_t guard_size;
unsigned char *real_mem, *mem;
guard_size = sizeof(guard_bytes) / sizeof(*guard_bytes);
real_size = size + 2 * guard_size;
real_mem = malloc(real_size);
if (real_mem == NULL) {
MB_fatal("mem.MB_alloc: malloc failed");
}
/*
* Now check all allocated memory for corruption.
* XXX: Fill this in later...
*/
mem = real_mem + guard_size;
return mem;
}
void
MB_free(void *mem)
{
size_t guard_size;
unsigned char *real_mem;
/*
* Check that the memory to be freed was actually allocated.
* We can't check for still-remaining references to the
* memory without some sort of memory-marking as done in
* Hans Boehm's conservative garbage collector.
*/
/*
* Check all allocated memory for corruption.
* XXX: Do this later...
*/
guard_size = sizeof(guard_bytes) / sizeof(*guard_bytes);
real_mem = (unsigned char *) mem - guard_size;
free(real_mem);
return;
}
void*
MB_realloc(void *mem, size_t size)
{
void *new_mem;
/*
* Check all allocated memory for corruption.
* XXX: Do this later...
*/
new_mem = MB_malloc(size);
memcpy(new_mem, mem, size);
/*
* Check mem was actually allocated.
* XXX: Do later...
*/
MB_free(mem);
return new_mem;
}

41
bytecode/mb_mem.h Normal file
View File

@@ -0,0 +1,41 @@
/*
** Copyright (C) 2000 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
**
** $$
**
** This file provides basic memory management interfaces
**
*/
#ifndef MB_MEM_H
#define MB_MEM_H
#include <stdlib.h>
/*
** Do not use MB_malloc() or MB_realloc() directly, unless you want
** to allocate raw memory. Normally you should use the macros
** MB_new(), MB_new_array(), and MB_resize_array() instead.
*/
void*
MB_malloc(size_t size);
void*
MB_realloc(void* mem, size_t size);
void
MB_free(void *mem);
#define MB_new(type) ((type *) MB_malloc(sizeof(type)))
#define MB_new_array(type, num) ((type *) MB_malloc((num) * sizeof(type)))
#define MB_resize_array(array, type, num) \
((type *) MB_realloc((array), (num) * sizeof(type)))
#endif /* MB_MEM_H */

148
bytecode/mb_stack.c Normal file
View File

@@ -0,0 +1,148 @@
/*
** Copyright (C) 1997 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
**
** $Id: mb_stack.c,v 1.1 2001-01-24 07:42:28 lpcam Exp $
**
** High-water marked stack of 'MB_Word's
**
*/
/* Imports */
#include <assert.h>
#include "mb_bytecode.h"
#include "mb_mem.h"
#include "mb_stack.h"
/* Exported definitions */
MB_Stack MB_stack_new(MB_Word init_size);
MB_Word MB_stack_size(MB_Stack* s);
void MB_stack_push(MB_Stack* s, MB_Word x);
MB_Word MB_stack_pop(MB_Stack* s);
MB_Word MB_stack_alloc(MB_Stack* s, MB_Word num_words);
void MB_stack_free(MB_Stack* s, MB_Word num_words);
MB_Word MB_stack_peek(MB_Stack* s, MB_Word index);
MB_Word MB_stack_peek_rel(MB_Stack* s, MB_Word rel_index);
MB_Word* MB_stack_peek_p(MB_Stack* s, MB_Word index);
MB_Word* MB_stack_peek_rel_p(MB_Stack* s, MB_Word rel_index);
void MB_stack_poke(MB_Stack* s, MB_Word index, MB_Word x);
void MB_stack_poke_rel(MB_Stack* s, MB_Word rel_idx, MB_Word value);
void MB_stack_delete(MB_Stack* s);
/* Local declarations */
static char
rcs_id[] = "$Id: mb_stack.c,v 1.1 2001-01-24 07:42:28 lpcam Exp $";
/* Implementation */
MB_Stack
MB_stack_new(MB_Word init_size) {
MB_Stack s;
s.max_size = init_size;
s.data = MB_new_array(MB_Word, init_size);
s.sp = 0;
if (s.data == NULL) {
MB_fatal("Unable to allocate memory");
}
return s;
}
MB_Word
MB_stack_size(MB_Stack* s) {
return s->sp;
}
void
MB_stack_push(MB_Stack* s, MB_Word x)
{
if (s->sp == s->max_size) {
s->max_size *= 2;
s->data = MB_resize_array(s->data, MB_Word, s->max_size);
assert(s->data != NULL);
}
s->data[s->sp++] = x;
}
MB_Word
MB_stack_pop(MB_Stack* s) {
assert(s->sp != 0);
s->sp--;
return s->data[s->sp];
}
MB_Word
MB_stack_alloc(MB_Stack* s, MB_Word num_words)
{
MB_Word orig_sp = s->sp;
while (s->sp + num_words > s->max_size) {
num_words -= (s->max_size - s->sp);
s->sp = s->max_size;
num_words--;
MB_stack_push(s, 0);
}
s->sp += num_words;
return orig_sp;
}
void
MB_stack_free(MB_Stack* s, MB_Word num_words) {
s->sp -= num_words;
assert(s->sp >= 0);
}
MB_Word
MB_stack_peek(MB_Stack* s, MB_Word index) {
assert(index >= 0);
assert(index < s->sp);
return s->data[index];
}
MB_Word
MB_stack_peek_rel(MB_Stack* s, MB_Word rel_index) {
return MB_stack_peek(s, s->sp - rel_index);
}
MB_Word*
MB_stack_peek_p(MB_Stack* s, MB_Word index) {
assert(index >= 0);
assert(index < s->sp);
return s->data + index;
}
MB_Word*
MB_stack_peek_rel_p(MB_Stack* s, MB_Word rel_index) {
return MB_stack_peek_p(s, s->sp - rel_index);
}
void
MB_stack_poke(MB_Stack* s, MB_Word index, MB_Word x) {
assert(index >= 0);
assert(index < s->sp);
s->data[index] = x;
}
void
MB_stack_poke_rel(MB_Stack* s, MB_Word rel_idx, MB_Word value) {
MB_stack_poke(s, s->sp - rel_idx, value);
}
void
MB_stack_delete(MB_Stack* s) {
MB_free(s->data);
}

56
bytecode/mb_stack.h Normal file
View File

@@ -0,0 +1,56 @@
/*
** Copyright (C) 1997 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
**
** $Id: mb_stack.h,v 1.1 2001-01-24 07:42:28 lpcam Exp $
**
** High-water marked stack of 'MB_Word's
**
*/
#ifndef MB_STACK_H
#define MB_STACK_H
#include "mb_bytecode.h"
typedef struct {
MB_Word*data;
MB_Word sp;
MB_Word max_size;
} MB_Stack;
/* allocates space for a new stack */
MB_Stack MB_stack_new(MB_Word init_size);
/* get number of words already pushed on stack */
MB_Word MB_stack_size(MB_Stack* s);
/* pushes a value onto the stack */
void MB_stack_push(MB_Stack* s, MB_Word x);
/* removes a value off the stack */
MB_Word MB_stack_pop(MB_Stack* s);
/* allocates space for multiple places on the stack */
/* return value is index of lowest word */
MB_Word MB_stack_alloc(MB_Stack* s, MB_Word num_words);
/* remove multiple items off the stack */
void MB_stack_free(MB_Stack* s, MB_Word num_words);
/* peek at an item at a given stack index*/
MB_Word MB_stack_peek(MB_Stack* s, MB_Word idx);
/* peek at an item index items away from the top of the stack */
MB_Word MB_stack_peek_rel(MB_Stack* s, MB_Word idx);
/* get the address for the item at index
** Note: if you add or remove items, this value could change */
MB_Word* MB_stack_peek_p(MB_Stack* s, MB_Word idx);
/* get the address for the item at index relative to the top of the stack */
MB_Word* MB_stack_peek_rel_p(MB_Stack* s, MB_Word idx);
/* Set the value of an item on the stack */
void MB_stack_poke(MB_Stack* s, MB_Word idx, MB_Word x);
/* Set the value of an item on the stack, idx items from the top */
void MB_stack_poke_rel(MB_Stack* s, MB_Word rel_idx, MB_Word value);
/* deallocate space for the stack */
void MB_stack_delete(MB_Stack* s);
#endif /* MB_STACK_H */

62
bytecode/mb_util.c Normal file
View File

@@ -0,0 +1,62 @@
/*
** Copyright (C) 2000 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
**
** $Id: mb_util.c,v 1.1 2001-01-24 07:42:28 lpcam Exp $
*/
/* Imports */
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "mb_util.h"
/* Exported definitions */
int MB_strcmp(MB_CString_Const a, MB_CString_Const b);
void MB_util_error(const char *fmt, ...);
void MB_fatal(const char* message);
/* Local declarations */
static char
rcs_id[] = "$Id: mb_util.c,v 1.1 2001-01-24 07:42:28 lpcam Exp $";
/* Implementation */
/* Prints an error to standard err (doesn't exit) */
void
MB_util_error(const char *fmt, ...)
{
va_list arg_p;
fprintf(stderr, "Error: ");
va_start(arg_p, fmt);
vfprintf(stderr, fmt, arg_p);
va_end(argp);
fprintf(stderr, "\n");
}
/* prints an error and aborts program */
void
MB_fatal(const char* message)
{
MB_util_error(message);
fprintf(stderr, " NOTE: The program will now abort.\n");
abort();
return; /* not reached */
}
/* compare two strings */
int MB_strcmp(MB_CString_Const a, MB_CString_Const b) {
return strcmp(a, b);
}

42
bytecode/mb_util.h Normal file
View File

@@ -0,0 +1,42 @@
/*
** Copyright (C) 1997 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
**
** $Id: mb_util.h,v 1.1 2001-01-24 07:42:28 lpcam Exp $
*/
#ifndef MB_UTIL_H
#define MB_UTIL_H
typedef char *
MB_CString;
typedef const char *
MB_CString_Const;
#define MB_NULL_STR ((MB_CString)NULL)
/* Standard TRUE & FALSE macros, if not defined */
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/* Prints an error (doesn't exit) */
void
MB_util_error(const char *fmt, ...);
/* Prints an error message and exits */
void
MB_fatal(const char* message);
/* compare two strings */
int MB_strcmp(MB_CString_Const a, MB_CString_Const b);
#endif /* MB_UTIL_H */

View File

@@ -1,51 +1,151 @@
/*
** Copyright (C) 1997 The University of Melbourne.
** Copyright (C) 2000 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
**
** $Id: mbi.c,v 1.9 1997-07-27 14:59:24 fjh Exp $
** $Id: mbi.c,v 1.10 2001-01-24 07:42:28 lpcam Exp $
**
** Mercury bytecode interpreter
**
*/
static char
rcs_id[] = "$Id: mbi.c,v 1.10 2001-01-24 07:42:28 lpcam Exp $";
/* Imports */
/*
** Interface to Mercury runtime must be included first.
*/
#include "imp.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "util.h"
#include "mem.h"
#include "mbi.h"
/* Exports */
#include "mb_util.h"
#include "mb_disasm.h"
#include "mb_machine.h"
/* Exported definitions */
/* Local declarations */
static char
rcs_id[] = "$Id: mbi.c,v 1.9 1997-07-27 14:59:24 fjh Exp $";
static void
usage(void);
static char*
program_name = NULL;
static void usage(const char* program_name, FILE* fp);
static int match(const char* c, const char* controlstr);
static void interactive(MB_Machine_State* ms);
static void show_help(void);
/* Implementation */
int
BC_mbi_main(int argc, char* argv[])
{
int c;
/* We do this in case we change the program name. */
program_name = argv[0];
static void
show_help(void)
{
printf( "\n---------------------------------------"
"\n Mercury Bytecode Interpreter"
"\n"
"\n Interactive mode commands:"
"\n"
"\n ? | help - this screen"
"\n state - show machine state"
"\n next - single step execute into predicates"
"\n over - step execute over predicates"
"\n run - run until exception"
"\n list [from [to]] - source listing"
"\n call - show call stack"
"\n x | exit | quit - exit interpreter"
"\n"
"\n---------------------------------------"
"\n");
}
/* returns true if string pointed to by c could be interpreted
** as matching command (eg: "cyo" will match "cyote" but
** "cyor" will not match "cyote")
**
** White space will be stripped out of c, but should already
** have been taken out of commmand
**
** Strings are not case sensitive
**
*/
static int
match(const char* c, const char* command)
{
/* Remove leading whitespace from c */
while (isspace(*c)) c++;
/* Find where the strings differ */
while (tolower(*c) == tolower(*command)) {
c++;
command++;
}
/* Allow a truncated c to still match */
if (isspace(*c) || *c == 0) return TRUE;
return FALSE;
}
static void
interactive(MB_Machine_State* ms)
{
char buffer[78];
char* c;
printf("Found main/2, proc 0 at %04x\n", MB_ip_get(ms));
/* Show the current machine state */
MB_show_state(ms, stdout);
do {
printf("> ");
fgets(buffer, sizeof(buffer), stdin);
printf("\n");
/* Read the next command */
c = buffer;
while (isspace(*c)) c++;
if (match(c, "next") || (*c == 0)) {
MB_step(ms);
MB_show_state(ms, stdout);
} else if (match(c, "run")) {
MB_run(ms);
MB_show_state(ms, stdout);
} else if (match(c, "over")) {
MB_step_over(ms);
MB_show_state(ms, stdout);
} else if (match(c, "list")) {
int start = 0;
int end = -1;
scanf("list %i %i", &start, &end);
MB_listing(ms, stdout, start, end);
} else if (match(c, "quit")
|| match(c, "exit")
|| match(c, "x"))
{
break;
} else if (match(c, "?") || match(c, "help")) {
show_help();
} else if (match(c, "call")) {
MB_show_call(ms, stdout);
} else if (match(c, "state")) {
MB_show_state(ms, stdout);
} else {
printf("Unrecognised command. Enter ? for Help\n");
}
} while (!feof(stdin));
}
int
main(int argc, char* argv[]) {
int c;
/* Don't use default error messages from getopt() */
opterr = 0;
@@ -54,63 +154,43 @@ BC_mbi_main(int argc, char* argv[])
while ((c = getopt(argc,argv,"h")) != EOF) {
switch (c) {
case 'h':
usage();
usage(argv[0], stderr);
exit(EXIT_SUCCESS);
break;
default:
usage();
usage(argv[0], stdout);
exit(EXIT_FAILURE);
break;
}
}
/* We _must_ have a file argument */
/* If no arguments, then we obviously don't have a filename */
if (optind == argc) {
usage();
usage(argv[0], stdout);
} else {
/* Process each bytecode file in order */
int i;
char *filename;
FILE *fp;
for (i = optind; i < argc; i++) {
filename = argv[i];
if ((fp = fopen(filename, "r")) != NULL) {
#if 0
if (is bytecode file) /* file ext = .mb */
{
read bytecodes into code area
and store label and procedure
entry points, etc.
}
else if (is shared library) /* file ext = .so*/
{
do a dlopen and add to list
of shlibs.
} else {
error: wrong file extension
}
#endif /* 0 */
} else {
MB_Machine_State* ms = MB_load_program_name(argv[optind]);
if (ms == NULL) {
/* XXX: Give better error message */
MB_util_error("can not open file \"%s\"",
filename);
MB_util_error("error reading bytecode file `%s'",
argv[optind]);
} else {
/* Run the interpreter */
interactive(ms);
/* And when finished, unload */
MB_unload_program(ms);
}
} /* end for */
/*
* XXX: Now start the bytecode interpreter
* Fire up the read-eval-print loop?
*/
} /* end else */
exit(EXIT_SUCCESS);
} /* end main() */
/* usage - print a short help screen to given output file */
static void
usage(void)
{
fprintf(stderr, "Usage: %s [-h] files\n", program_name);
usage(const char* program_name, FILE* fp) {
fprintf(fp,
"usage: %s [-h | bytecodefile]\n", program_name);
}

View File

@@ -1,43 +1,35 @@
/*
** Copyright (C) 1997 The University of Melbourne.
** Copyright (C) 2000 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
**
** $Id: mdis.c,v 1.7 1997-07-27 14:59:27 fjh Exp $
** $Id: mdis.c,v 1.8 2001-01-24 07:42:29 lpcam Exp $
*/
/* Imports */
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <util.h>
#include <mem.h>
#include <disasm.h>
#include <mdis.h>
static char
rcs_id[] = "$Id: mdis.c,v 1.7 1997-07-27 14:59:27 fjh Exp $";
rcs_id[] = "$Id: mdis.c,v 1.8 2001-01-24 07:42:29 lpcam Exp $";
/* Imports */
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include "mb_util.h"
#include "mb_disasm.h"
#include "mb_machine.h"
/* Exported definitions */
/* Local declarations */
static void
usage(void);
static char*
program_name = NULL;
usage(const char* program_name, FILE* fp);
/* Implementation */
#if ! defined(UNIT_TESTING)
int
main(int argc, char* argv[])
{
int c;
main(int argc, char* argv[]) {
/* We do this in case we change the program name. */
program_name = argv[0];
int c;
/* Don't use default error messages from getopt() */
opterr = 0;
@@ -46,11 +38,11 @@ main(int argc, char* argv[])
while ((c = getopt(argc,argv,"h")) != EOF) {
switch (c) {
case 'h':
usage();
usage(argv[0], stderr);
exit(EXIT_SUCCESS);
break;
default:
usage();
usage(argv[0], stdout);
exit(EXIT_FAILURE);
break;
}
@@ -58,20 +50,26 @@ main(int argc, char* argv[])
/* If no arguments, then assume bytecode stream is on stdin */
if (optind == argc) {
MB_disassemble(stdin);
printf("<<dissassemble here>>\n");
/*MB_disassemble(stdin);*/
} else {
/* Process each bytecode file in order */
int i;
char *filename;
FILE *fp;
MB_Machine_State* ms;
for (i = optind; i < argc; i++) {
filename = argv[i];
if ((fp = fopen(filename, "r")) != NULL) {
MB_disassemble(fp);
int indent_level = 0;
ms = MB_load_program_name(argv[i]);
if (ms != NULL) {
MB_listing(ms, stdout, 0, MB_code_size(ms)-1);
MB_unload_program(ms);
} else {
/* XXX: Give better error message */
MB_util_error("can not open bytecode file `%s'", filename);
MB_util_error("error reading bytecode file `%s'",
argv[i]);
}
}
} /* end else */
@@ -79,10 +77,11 @@ main(int argc, char* argv[])
exit(EXIT_SUCCESS);
} /* end main() */
#endif /* UNIT_TESTING */
/* usage - print a short help screen to given output file */
static void
usage(void)
{
fprintf(stderr, "usage: %s [-h] [files]\n", program_name);
usage(const char* program_name, FILE* fp) {
fprintf(fp,
"usage: %s [-h | file]\n", program_name);
}