mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-14 13:23:53 +00:00
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:
@@ -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
|
||||
|
||||
#-----------------------------------------------------------------------------#
|
||||
|
||||
|
||||
@@ -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
1218
bytecode/mb_bytecode.c
Normal file
File diff suppressed because it is too large
Load Diff
439
bytecode/mb_bytecode.h
Normal file
439
bytecode/mb_bytecode.h
Normal 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
1005
bytecode/mb_disasm.c
Normal file
File diff suppressed because it is too large
Load Diff
30
bytecode/mb_disasm.h
Normal file
30
bytecode/mb_disasm.h
Normal 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
1114
bytecode/mb_machine.c
Normal file
File diff suppressed because it is too large
Load Diff
198
bytecode/mb_machine.h
Normal file
198
bytecode/mb_machine.h
Normal 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
304
bytecode/mb_machine_show.c
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
29
bytecode/mb_machine_show.h
Normal file
29
bytecode/mb_machine_show.h
Normal 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
108
bytecode/mb_mem.c
Normal 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
41
bytecode/mb_mem.h
Normal 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
148
bytecode/mb_stack.c
Normal 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
56
bytecode/mb_stack.h
Normal 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
62
bytecode/mb_util.c
Normal 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
42
bytecode/mb_util.h
Normal 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 */
|
||||
|
||||
226
bytecode/mbi.c
226
bytecode/mbi.c
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user