diff: interface to external opium-style debugger (round 2)
Fergus Henderson
fjh at cs.mu.OZ.AU
Fri Mar 13 06:51:03 AEDT 1998
On 12-Mar-1998, Erwan Jahier <Erwan.Jahier at irisa.fr> wrote:
> Fergus Henderson wrote:
>
> > library/debugger_interface.m:
> > New file. Declares the Mercury types used for the debugger
> > socket interface and defines support routines used by
> > runtime/mercury_trace.c.
>
> You forgot to include the diff for this file. I'd like to see it.
Oops, sorry about that. Here it is.
%-----------------------------------------------------------------------------%
% Copyright (C) 1998 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.
%-----------------------------------------------------------------------------%
% File: debugger_interface.m
% Authors: fjh, jahier
% Purpose:
% This module provide support routines needed by runtime/mercury_trace.c
% for interfacing to an external (in a different process) debugger,
% in particular an Opium-style debugger.
%
% This module corresponds to what is called the "Query Handler" in Opium.
:- module debugger_interface.
:- interface.
% This module exports the following C functions:
% ML_DI_output_current
% ML_DI_found_match
% ML_DI_read_request_from_socket
% These are used by runtime/mercury_trace.c.
:- pred dummy_pred_to_avoid_warning_about_nothing_exported is det.
:- implementation.
:- import_module io, require.
:- import_module list, bool, std_util.
dummy_pred_to_avoid_warning_about_nothing_exported.
% The stuff defined below is also defined in modules prog_data, hlds_data.
:- type arity == int.
:- type determinism == int.
% encoded as specified in ../runtime/mercury_accurate_gc.h
% The stuff defined below is similar to types goal_path and trace_port
% defined in modules compiler/hlds_goal.m and compiler/trace.m.
:- type trace_port_type
---> call
; exit
; fail
; ite_then
; ite_else
; switch
; disj
.
:- type goal_path_string == string.
% This is known as "debugger_query" in the Opium documentation.
% The debugger_request type is used for request sent
% from the debugger process to the Mercury program being debugged.
% This type would need to be extended to handle spypoints, etc.
:- type debugger_request
---> hello_reply % yes, I'm here
% A `forward_move' request instructs the debuggee
% to step forward until we reach a trace event
% which matches the specified attributes.
; forward_move(
match(event_number),
match(call_number),
match(depth_number),
match(trace_port_type),
match(string), % module name
match(string), % pred name
match(arity),
match(int), % mode number
match(determinism),
match(list(univ)), % the arguments
% XXX we could provide better ways of
% matching on arguments
match(goal_path_string)
)
% A `current' request instructs the debuggee to
% retrieve the specified attributes of the current
% trace event and report them to the debugger
% via the socket.
; current(
wanted, % event_number
wanted, % call_number
wanted, % depth_number
wanted, % port
wanted, % module name
wanted, % pred name
wanted, % arity
wanted, % proc_id (mode number)
wanted, % determinism
wanted, % arguments
% XXX should provide a way of getting
% just part of the arguments
% (to reduce unnecessary socket traffic)
wanted % goal_path_string
)
; abort_prog
% just abort the program
; no_trace
% stop tracing, and run the program to completion
; error(string)
% something went wrong when trying to get the
% next request
.
:- type event_number == int.
:- type call_number == int.
:- type depth_number == int.
% `match' is called "get status" in the Opium documentation.
% This type defines a unary predicate which determines whether
% or not a particular value will be selected.
:- type match(T)
---> nop % nop: value = -
; exact(T) % exact(X): value = X
; neg(T) % neg(X): value \= X
; list(list(T)) % list(L): list__member(value, L)
; interval(T,T) % interval(Low, High): Low =< X, X =< High
.
% The debugger_response type is used for response sent
% to the debugger process from the Mercury program being debugged.
% This type would need to be extended.
:- type debugger_response
% sending hello
---> hello % are you there?
% start the synchronous communication with the debugger
; start
% responses to forward_move
; forward_move_match_found
; forward_move_match_not_found
% responses to current
; current(
maybe(event_number),
maybe(call_number),
maybe(depth_number),
maybe(trace_port_type),
maybe(string), % module name
maybe(string), % pred name
maybe(arity),
maybe(int), % mode number
maybe(determinism),
maybe(list(univ)),
maybe(goal_path_string)
)
; last_event
% responses to abort_prog or no_trace
; ok
% responses to anything
; error(string)
.
% `wanted' is called "current status" in the Opium documentation
:- type wanted == bool.
%-----------------------------------------------------------------------------%
% output_currentML_DI_output_current":
% send to the debugger (e.g. Opium) the wanted features.
:- pragma export(output_current(in, in, in, in, in, in, in, in, in, in,
in, in, in, di, uo), "ML_DI_output_current").
:- pred output_current(event_number, call_number, depth_number, trace_port_type,
/* module name */ string, /* pred name */ string, arity,
/* mode num */ int, determinism, /* the arguments */ list(univ),
goal_path_string, debugger_request,
io__output_stream, io__state, io__state).
:- mode output_current(in, in, in, in, in, in, in, in, in, in, in, in, in,
di, uo) is det.
output_current(EventNumber, CallNumber, DepthNumber, Port,
ModuleName, PredName, Arity, ModeNum, Determinism, Args,
Path, DebuggerRequest, OutputStream) -->
(
{ DebuggerRequest = current(WantEventNumber,
WantCallNumber, WantDepthNumber, WantPort,
WantModuleName, WantPredName, WantArity,
WantModeNum, WantDeterminism, WantArgs, WantPath) }
->
{
get_if_wanted(WantEventNumber, EventNumber,
MaybeEventNumber),
get_if_wanted(WantCallNumber, CallNumber, MaybeCallNumber),
get_if_wanted(WantDepthNumber, DepthNumber,
MaybeDepthNumber),
get_if_wanted(WantPort, Port, MaybePort),
get_if_wanted(WantModuleName, ModuleName, MaybeModuleName),
get_if_wanted(WantPredName, PredName, MaybePredName),
get_if_wanted(WantArity, Arity, MaybeArity),
get_if_wanted(WantModeNum, ModeNum, MaybeModeNum),
get_if_wanted(WantDeterminism, Determinism,
MaybeDeterminism),
get_if_wanted(WantArgs, Args, MaybeArgs),
get_if_wanted(WantPath, Path, MaybePath),
CurrentTraceInfo = current(MaybeEventNumber,
MaybeCallNumber, MaybeDepthNumber, MaybePort,
MaybeModuleName, MaybePredName, MaybeArity,
MaybeModeNum, MaybeDeterminism, MaybeArgs,
MaybePath)
},
/****
io__print("debugger_interface: Send to Opium: "),
io__write(CurrentTraceInfo),
io__print(".\n"),
****/
io__write(OutputStream, CurrentTraceInfo),
io__print(OutputStream, ".\n"),
io__flush_output(OutputStream)
;
{ error("output_current: current expected") }
).
:- pred get_if_wanted(wanted, T, maybe(T)).
:- mode get_if_wanted(in, in, out) is det.
% get_if_wanted(Wanted, Value, MaybeValue).
get_if_wanted(yes, X, yes(X)).
get_if_wanted(no, _, no).
%-----------------------------------------------------------------------------%
:- pragma export(found_match(in, in, in, in, in, in, in, in, in, in,
in, in), "ML_DI_found_match").
:- pred found_match(event_number, call_number, depth_number, trace_port_type,
/* module name */ string, /* pred name */ string, arity,
/* mode num */ int, determinism, /* the arguments */ list(univ),
% XXX we could provide better ways of
% matching on arguments
goal_path_string, debugger_request).
:- mode found_match(in, in, in, in, in, in, in, in, in, in, in, in)
is semidet.
found_match(EventNumber, CallNumber, DepthNumber, Port,
ModuleName, PredName, Arity, ModeNum, Determinism, Args,
Path, DebuggerRequest) :-
(
DebuggerRequest = forward_move(MatchEventNumber,
MatchCallNumber, MatchDepthNumber, MatchPort,
MatchModuleName, MatchPredName, MatchArity,
MatchModeNum, MatchDeterminism, MatchArgs, MatchPath)
->
match(MatchEventNumber, EventNumber),
match(MatchCallNumber, CallNumber),
match(MatchDepthNumber, DepthNumber),
match(MatchPort, Port),
match(MatchModuleName, ModuleName),
match(MatchPredName, PredName),
match(MatchArity, Arity),
match(MatchModeNum, ModeNum),
match(MatchDeterminism, Determinism),
match(MatchArgs, Args),
match(MatchPath, Path)
;
error("found_match: forward_move expected")
).
% match(MatchPattern, Value) is true iff Value matches the specified pattern.
:- pred match(match(T), T).
:- mode match(in, in) is semidet.
match(nop, _).
match(exact(X), X).
match(neg(X), Y) :- X \= Y.
match(list(L), X) :- list__member(X, L).
match(interval(Low, High), X) :-
% X >= Low, X =< High
compare(LE, X, High),
(LE = (<) ; LE = (=)),
compare(GE, X, Low),
(GE = (>) ; GE = (=)).
%-----------------------------------------------------------------------------%
:- pred read_request_from_socket(io__input_stream, debugger_request, int,
io__state, io__state).
:- mode read_request_from_socket(in, out, out, di, uo) is det.
:- pragma export(read_request_from_socket(in, out, out, di, uo),
"ML_DI_read_request_from_socket").
read_request_from_socket(SocketStream, Request, RequestType) -->
io__read(SocketStream, MaybeRequest),
( { MaybeRequest = ok(Request0) },
{ Request = Request0 }
; { MaybeRequest = error(ErrorMsg, _LineNum) },
{ Request = error(ErrorMsg) }
; { MaybeRequest = eof },
{ Request = error("end of file") }
),
{ classify_request(Request, RequestType) }.
/***********
% debugging stuff.
io__stderr_stream(StdErr),
io__print(StdErr, "debugger_interface: Receive the Request:+"),
io__print(StdErr, Request),
io__print(StdErr, "+ from opium\ndebugger_interface: RequestType = "),
io__print(StdErr, RequestType),
io__print(StdErr, ".\n").
***********/
:- pred classify_request(debugger_request, int).
:- mode classify_request(in, out) is det.
% the numbers here should match the definition of
% MR_debugger_request_type in runtime/mercury_trace.c.
classify_request(hello_reply, 0).
classify_request(forward_move(_, _, _, _, _, _, _, _, _, _, _), 1).
classify_request(current(_, _, _, _, _, _, _, _, _, _, _), 2).
classify_request(abort_prog, 3).
classify_request(no_trace, 4).
classify_request(error(_), 5).
%-----------------------------------------------------------------------------%
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
More information about the developers
mailing list