mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-23 21:33:49 +00:00
Estimated hours taken: 5 Use the same method of input for the browser as for the internal tracer. Previously, the browser did input via the Mercury library and the internal tracer did input via readline (if available). This did not work properly if files were redirected into stdin, which meant that test cases could not be written for the browser. This change also adds a test case. browser/util.m: Add a predicate, util__trace_getline/4, which does input via the same method used by the internal debugger. browser/parse.m: Call util__trace_getline/4 instead of io__read_line/3. browser/browse.m: Pass the prompt to browser/parse.m as a string, rather than printing it before calling. trace/mercury_trace_internal.c: trace/mercury_trace_internal.h: Declare MR_trace_getline extern. runtime/mercury_init.h: runtime/mercury_wrapper.c: runtime/mercury_wrapper.h: util/mkinit.c: Make MR_trace_getline available to the browser via a function pointer. tests/debugger/Mmakefile: Add the new test case. tests/debugger/browser_test.m: tests/debugger/browser_test.inp: tests/debugger/browser_test.exp: The new test case. runtime/mercury_trace_base.c: runtime/mercury_trace_base.h: Export MR_tracing_not_enabled() for use by browser/util.m.
178 lines
6.0 KiB
C
178 lines
6.0 KiB
C
/*
|
|
** Copyright (C) 1997-1999 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.
|
|
*/
|
|
|
|
/*
|
|
** mercury_trace_base.h defines the interface between the main part
|
|
** of the runtime system (mainly mercury_wrapper.c) and the part of the
|
|
** tracing subsystem that has to be present even if tracing is not enabled.
|
|
** The part of the tracing system that required only when tracing is enabled
|
|
** is in the trace directory.
|
|
*/
|
|
|
|
#ifndef MERCURY_TRACE_BASE_H
|
|
#define MERCURY_TRACE_BASE_H
|
|
|
|
#include <stdio.h>
|
|
#include "mercury_stack_layout.h"
|
|
#include "mercury_std.h"
|
|
|
|
/*
|
|
** This enum should EXACTLY match the definition of the `trace_port_type' type
|
|
** in browser/debugger_interface.
|
|
*/
|
|
|
|
typedef enum {
|
|
MR_PORT_CALL,
|
|
MR_PORT_EXIT,
|
|
MR_PORT_REDO,
|
|
MR_PORT_FAIL,
|
|
MR_PORT_THEN,
|
|
MR_PORT_ELSE,
|
|
MR_PORT_DISJ,
|
|
MR_PORT_SWITCH,
|
|
MR_PORT_PRAGMA_FIRST,
|
|
MR_PORT_PRAGMA_LATER,
|
|
MR_PORT_EXCEPTION
|
|
} MR_Trace_Port;
|
|
|
|
#define MR_trace_incr_seq() ((Word) ++MR_trace_call_seqno)
|
|
#define MR_trace_incr_depth() ((Word) ++MR_trace_call_depth)
|
|
#define MR_trace_reset_depth(d) (MR_trace_call_depth = (Unsigned) (d))
|
|
|
|
/*
|
|
** This structure holds all the information passed to MR_trace() by the
|
|
** tracing code generated by the compiler. This info is all in one structure
|
|
** to allow calls to MR_trace to simply pass the address of a static data
|
|
** structure. This should be faster than moving several separate arguments
|
|
** into their registers. If tracing is not enabled, the arguments are
|
|
** not looked at anyway. If tracing is enabled, the speed advantage
|
|
** may or may not evaporate, depending on how many of these fields
|
|
** the current trace command looks at.
|
|
*/
|
|
|
|
typedef struct MR_Trace_Call_Info_Struct {
|
|
const MR_Stack_Layout_Label *MR_trace_sll;
|
|
const char *MR_trace_path;
|
|
int MR_trace_max_r_num;
|
|
MR_Trace_Port MR_trace_port;
|
|
} MR_Trace_Call_Info;
|
|
|
|
/*
|
|
** MR_trace is called from Mercury modules compiled with tracing.
|
|
** If the event is supposed to be traced, it performs an indirect call
|
|
** through MR_trace_func_ptr, which will point either to MR_trace_real,
|
|
** which is defined in the trace library, or to MR_trace_fake, defined here,
|
|
** which just prints an error message and aborts.
|
|
**
|
|
** The return value, if not NULL, says where execution should continue
|
|
** after the event. (NULL means it should continue as usual.)
|
|
**
|
|
** MR_trace_struct is the same as MR_trace, except it takes its arguments
|
|
** in a structure (which is not modified by MR_trace_struct).
|
|
*/
|
|
|
|
extern Code *MR_trace(const MR_Stack_Layout_Label *, MR_Trace_Port,
|
|
const char *, int);
|
|
extern Code *MR_trace_struct(const MR_Trace_Call_Info *trace_call_info);
|
|
|
|
extern Code *MR_trace_fake(const MR_Stack_Layout_Label *, MR_Trace_Port,
|
|
Unsigned, Unsigned, const char *, int);
|
|
|
|
/*
|
|
** MR_trace_init() is called from mercury_runtime_init()
|
|
** when the debuggee programs begins, to perform any initialization
|
|
** that must be done before any traced Mercury code is executed.
|
|
** This includes the initialization code written in Mercury as well as main.
|
|
**
|
|
** MR_trace_start(enabled) is called from mercury_runtime_init()
|
|
** after the initialization code written in Mercury is executed,
|
|
** when we are about to start executing main. The argument says
|
|
** whether tracing is enabled for main (it is never enabled for
|
|
** initialization and finalization routines).
|
|
**
|
|
** MR_trace_end() is called from mercury_runtime_terminate() just
|
|
** after main has terminated and just before we call the finalization
|
|
** code written in Mercury.
|
|
**
|
|
** MR_trace_final() is called from mercury_runtime_terminate()
|
|
** after all Mercury code, including finalization code, has terminated.
|
|
*/
|
|
|
|
extern void MR_trace_init(void);
|
|
extern void MR_trace_start(bool enabled);
|
|
extern void MR_trace_end(void);
|
|
extern void MR_trace_final(void);
|
|
|
|
/*
|
|
** The globals that define the interface between the tracing subsystem
|
|
** and compiled code, and which must be initialized in the permanent part
|
|
** of the runtime.
|
|
**
|
|
** XXX They should probably be in MercuryEngine.
|
|
*/
|
|
|
|
extern Unsigned MR_trace_call_seqno;
|
|
extern Unsigned MR_trace_call_depth;
|
|
|
|
typedef enum {
|
|
MR_TRACE_INTERNAL,
|
|
MR_TRACE_EXTERNAL
|
|
} MR_Trace_Type;
|
|
|
|
extern MR_Trace_Type MR_trace_handler;
|
|
extern bool MR_trace_enabled;
|
|
|
|
extern Unsigned MR_trace_event_number;
|
|
extern Bool MR_trace_from_full;
|
|
|
|
/*
|
|
** These functions will report the number of the last event,
|
|
** if there have been some events, and will do nothing otherwise.
|
|
*/
|
|
|
|
extern void MR_trace_report(FILE *fp);
|
|
extern void MR_trace_report_raw(int fd);
|
|
|
|
/*
|
|
** This function prints an error message and aborts. It should be
|
|
** called in situations where tracing is required, but `--trace' was
|
|
** not passed to c2init.
|
|
*/
|
|
|
|
extern void MR_tracing_not_enabled(void);
|
|
|
|
/*
|
|
** If MR_TRACE_HISTOGRAM is defined, MR_trace maintains two arrays of integers,
|
|
** MR_trace_histogram_all and MR_trace_histogram_exp, in which the element
|
|
** with subscript d is incremented when a trace event occurs at depth d.
|
|
** The intention is that the MR_trace_histogram_all records all events
|
|
** and is never reset, which means that it records information about a whole
|
|
** execution of the program. MR_trace_histogram_exp on the other hand can be
|
|
** zeroed by a command from the debugger at e.g a call port, and examined at
|
|
** e.g. an exit port, which means that it can record information about the
|
|
** execution of a call.
|
|
**
|
|
** Both arrays are allocated via malloc, and resized on demand. They are
|
|
** always the same size, and this size is stored in MR_trace_histogram_max.
|
|
** MR_trace_histogram_hwm stores the high water mark, i.e. the biggest
|
|
** depth number that has been encountered so far in the execution of the
|
|
** program.
|
|
*/
|
|
|
|
#ifdef MR_TRACE_HISTOGRAM
|
|
|
|
extern int *MR_trace_histogram_all;
|
|
extern int *MR_trace_histogram_exp;
|
|
extern int MR_trace_histogram_max;
|
|
extern int MR_trace_histogram_hwm;
|
|
|
|
extern void MR_trace_print_histogram(FILE *fp, const char *which,
|
|
int *histogram, int max);
|
|
|
|
#endif /* MR_TRACE_HISTOGRAM */
|
|
|
|
#endif /* MERCURY_TRACE_BASE_H */
|