Files
mercury/trace/mercury_trace_tables.h
Zoltan Somogyi 8576975c4e Implement breakpoints on user events. Users may specify an event set,
Estimated hours taken: 20
Branches: main

Implement breakpoints on user events. Users may specify an event set,
an event name, both, or neither. Four forms of the mdb "break" command
create such breakpoints:

	break [the usual options] user_event <event_name>
	break [the usual options] user_event <event_set_name> <event_name>
	break [the usual options] user_event_set
	break [the usual options] user_event_set <event_set_name>

In addition, the command

	break [the usual options] user_event

is also accepted, as a synonym for

	break [the usual options] user_event_set

Since user events are not interface events or entry events, add a new, simple
ignore specification, which decrements the ignore count on every match of the
event.

Make the "break_print" mdb command consistent with the other command that
operates on existing breakpoints ("condition") by making it apply by default
to the most recently created breakpoint.

Make "condition" and "break_print" use the same option letter (-b) to introduce
the breakpoint number.

Fix a bug in the implementation of "break_print" that led to printing out
the selected variable, but not the selected *path* within the selected
variable. The reason was that we recorded what to print (variable spec plus
path) in a string, but that the process of using that record to print out
what was wanted destroyed the string (by putting a NULL between the variable
specification and the path), so that *later* uses of that string would find
an empty path. The fix is to record a var_spec/path pair in the print list.

Fix some slightly misleading output: when printing part of a variable, we
printed the name of the variable without any indication that the value printed
wasn't the whole value of the variable. We now print the path as well.

doc/user_guide.texi:
	Document the changes above.

	Document the usage "break_print [options] none", which we have always
	supported, but which was not documented.

runtime/mercury_stack_layout.h:
	Add a utility macro.

trace/mercury_trace.c:
	Fix a bug which left a variable uninitialized.

trace/mercury_trace_cmd_breakpoint.c:
	Implement the new command forms and options described above.

trace/mercury_trace_spy.[ch]:
	Implement data structures for keeping track of the new forms of
	breakpoints, and add the necessary functions for manipulating them.
	Update the function that checks whether the current event matches.
	Factor some common code out of that function, as well as out of the
	functions for adding new breakpoints.

	Change the print list data structure as described above.

	Add some utility functions.

	Add MR_ prefixes to the names of structure fields that previously
	lacked them.

trace/mercury_trace_cmd_misc.c:
	Handle the new breakpoint types.

trace/mercury_trace_tables.c:
trace/mercury_trace_internal.c:
	We used to parse the event set descriptions in module layout structures
	when the debugger was initialized (in mercury_trace_internal.c).
	However, we delay registering all the modules until this is needed,
	so at that time we don't yet *have* the list of module layout
	structures, so we used to parse nothing. This diff moves the code
	for doing the parsing to the time when the module layout structures
	are registered (in mercury_trace_tables.c).

	Don't test whether the module layout structure contains the fields
	for user event descriptions, since that diff has been installed on
	all our systems weeks ago.

trace/mercury_trace_internal.c:
	Conform to the new print list structure.

trace/mercury_trace_vars.[ch]:
	Print any selected path together with a variable name when printing a
	value. (This is the last bug fix mentioned at the top.)

	Export a function for use in mercury_trace_internal.c.

	Add some utility functions.

	Improve some error messages.

trace/mercury_trace_tables.h:
	Add a const qualifier.

tests/debugger/user_event.{inp,exp}:
	Extend this test case to test the new functionality.

tests/debugger/breakpoints.{inp,exp,exp2}:
	Conform to the change to the break_print command.

tests/queens.{inp,exp}:
	Change the input to test the bug fix to the break_print command,
	and the expected output.

tests/browser_test.exp:
tests/field_names.exp:
	Conform to the fact that we now print paths after variables names.
2007-01-19 04:42:52 +00:00

287 lines
9.9 KiB
C

/*
** vim: ts=4 sw=4 expandtab
*/
/*
** Copyright (C) 1998-2002, 2004-2007 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 contains the declarations of the tables that contain
** the identities of the debuggable modules and their procedures.
**
** Main author: Zoltan Somogyi.
*/
#ifndef MERCURY_TRACE_TABLES_H
#define MERCURY_TRACE_TABLES_H
#include "mercury_stack_layout.h"
#include "mercury_trace_completion.h"
#include "mercury_event_spec.h" /* for MR_EventSet */
#include <stdio.h>
/*
** MR_register_all_modules_and_procs gathers all available debugging info
** about the modules and procedures of the program into the module info table.
** If verbose is MR_TRUE, print progress and summary messages.
*/
extern void MR_register_all_modules_and_procs(FILE *fp,
MR_bool verbose);
/*
** MR_register_module_layout_real registers a module layout structure.
** It is called indirectly, through the function pointer
** MR_register_module_layout, by the module initialization code
** of modules compiled with debugging.
*/
extern void MR_register_module_layout_real(
const MR_ModuleLayout *module);
/*
** Every module that generates user defined events has a specification of the
** set of user events it was compiled with in its module layout structure.
** The debugger needs to know what these specifications are, and if they
** are consistent (which means that any two event sets with the same name
** must be identical).
**
** MR_trace_event_sets points to dynamically resizable array of
** MR_TraceEventSets, with MR_trace_event_set_max giving the current size
** of the array and MR_trace_event_set_next giving the number of elements
** currently filled in. The array is not sorted.
**
** The name field of an MR_TraceEventSet gives the name of the event set, while
** the string field will contain the string representation of the event set.
** The is_consistent field will be true iff all modules that use the event set
** with the same name have the same representation. The event_set field
** contains the parsed form of the string field; it is meaningful only if
** is_consistent is true.
*/
typedef struct {
const char *MR_tes_name;
const char *MR_tes_desc;
MR_bool MR_tes_is_consistent;
MR_EventSet MR_tes_event_set;
int MR_tes_num_specs;
const MR_UserEventSpec *MR_tes_specs;
} MR_TraceEventSet;
extern MR_TraceEventSet *MR_trace_event_sets;
extern int MR_trace_event_set_next;
extern int MR_trace_event_set_max;
extern MR_bool MR_trace_event_sets_are_all_consistent;
extern int MR_trace_event_sets_max_num_attr;
/*
** MR_process_file_line_layouts searches all the module layout structures
** of the program for label layout structures corresponding to the given
** filename/linenumber combination. For all such labels, it calls the supplied
** callback function with a pointer to the label's layout structure and
** with the supplied integer callback argument.
*/
typedef void (*MR_file_line_callback)(const MR_LabelLayout *, int);
extern void MR_process_file_line_layouts(const char *file, int line,
MR_file_line_callback callback_func, int callback_arg);
/*
** These functions print (parts of) the module info table.
**
** MR_dump_module_tables lists all procedures in all modules, unless
** module is not NULL, in which case lists only procedures in the named module.
** Its output can be very big; it should be used only by developers,
** for debugging the debugger. The components of procedure names will be
** printed in separate fields if the separate argument is true, while the
** names of compiler-created (unify/compare/index etc) predicates will be
** printed if the uci argument is true.
**
** MR_dump_module_list lists the names of all the modules,
** while MR_dump_module_procs lists the names of all the procs in the named
** module. These are intended for ordinary, non-developer users.
*/
extern void MR_dump_module_tables(FILE *fp, MR_bool separate,
MR_bool uci, char *module);
extern void MR_dump_module_list(FILE *fp);
extern void MR_dump_module_procs(FILE *fp, const char *name);
/*
** Print the names of ambiguous procedures (predicates and functions), types,
** and/or function symbols. The ambiguity may exist because a predicate,
** function, type or (constructor) function symbol with that name is defined
** with more than one arity or in more than one module.
**
** If num_modules is positive, then the search for ambiguities should consider
** only predicates, functions, types and function symbols in the modules whose
** names appear in module_names[0] .. module_names[num_modules-1].
*/
extern void MR_print_ambiguities(FILE *fp, MR_bool print_procs,
MR_bool print_types, MR_bool print_functors,
char **module_names, int num_modules);
/*
** A procedure specification has several components, the meaning of which
** depends on whether the procedure is from a user defined procedure (user)
** or from a unify, compare, index or init procedure (uci).
**
** The meanings of the components are
**
** the name of the module defining the procedure
** the name of the predicate or function (user)
** or the name of the type (uci)
** the arity of the predicate or function (user)
** or the arity of the type constructor (uci)
** the mode of the predicate or function
** whether the procedure is from a predicate or function (user)
** or is a unify, compare or index procedure (uci)
**
** A NULL pointer for the string fields, and a negative number for the other
** fields signifies the absence of information about that field, which should
** therefore be treated as a wildcard.
*/
typedef enum {
MR_PREFIX_PRED,
MR_PREFIX_FUNC,
MR_PREFIX_UNIF,
MR_PREFIX_COMP,
MR_PREFIX_INDX,
MR_PREFIX_INIT
} MR_ProcPrefix;
typedef struct {
const char *MR_proc_module;
const char *MR_proc_name;
int MR_proc_arity;
int MR_proc_mode;
MR_ProcPrefix MR_proc_prefix;
} MR_ProcSpec;
/*
** Given a string containing the specification of a procedure in the form
**
** [`pred*'|`func*']module:name/arity-mode
**
** in which some of the five components (but not the name) may be missing,
** parse it into the more usable form of a MR_ProcSpec. The original string
** may be overwritten in the process.
**
** Returns MR_TRUE if the string was correctly formed, and MR_FALSE otherwise.
*/
extern MR_bool MR_parse_proc_spec(char *str, MR_ProcSpec *spec);
/*
** Search the tables for a procedure that matches the given specification.
** If no procedure matches, return NULL.
** If one procedure matches, return its layout structure,
** and set *unique to MR_TRUE.
** If more than one procedure matches, return the layout structure of one
** and set *unique to MR_FALSE.
*/
extern const MR_ProcLayout *MR_search_for_matching_procedure(
MR_ProcSpec *spec, MR_bool *unique);
/*
** Search the tables for procedures that matches the given specification.
** Return their layout structures in the array in the match_procs field
** of the structure. The match_proc_next field says how many matches there are,
** and the match_proc_max field says how many entries the array has allocated
** for it.
*/
typedef struct {
const MR_ProcLayout **match_procs;
int match_proc_max;
int match_proc_next;
} MR_MatchesInfo;
extern MR_MatchesInfo MR_search_for_matching_procedures(MR_ProcSpec *spec);
/*
** Filter out UCI procs and keep only mode number 0.
*/
extern void MR_filter_user_preds(MR_MatchesInfo *matches);
/*
** MR_process_matching_procedures(spec, f, data):
**
** For each procedure that matches the specification given by `spec',
** call `f(data, entry)', where `entry' is the entry layout for that procedure.
** The argument `data' is a `void *' which can be used to pass any other
** information needed by the function `f'.
*/
extern void MR_process_matching_procedures(MR_ProcSpec *spec,
void f(void *, const MR_ProcLayout *), void *data);
/*
** MR_print_proc_id_and_nl(fp, proc):
**
** Print the id of the procedure identified by proc, followed by a newline.
*/
extern void MR_print_proc_id_and_nl(FILE *fp,
const MR_ProcLayout *proc);
/*
** MR_print_pred_id_and_nl(fp, proc):
**
** Print the id of the predicate/function identified by proc,
** followed by a newline.
*/
extern void MR_print_pred_id_and_nl(FILE *fp,
const MR_ProcLayout *proc);
/*
** MR_get_proc_decl_module(proc):
**
** Return the module name the procedure is declared in.
*/
extern MR_ConstString MR_get_proc_decl_module(const MR_ProcLayout *proc);
/*
** MR_proc_layout_stats(fp):
**
** Prints statistics about the proc layout structures of the program.
*/
extern void MR_proc_layout_stats(FILE *fp);
/*
** MR_label_layout_stats(fp):
**
** Prints statistics about the label layout structures of the program.
*/
extern void MR_label_layout_stats(FILE *fp);
/*
** MR_var_name_stats(fp):
**
** Prints statistics about the space occupied by the variable names
** in the layout structures of the program.
*/
extern void MR_var_name_stats(FILE *fp);
/* A Readline completer for module names. */
extern MR_CompleterList *MR_trace_module_completer(const char *, size_t);
/* A Readline completer for procedure specifications. */
extern MR_CompleterList *MR_trace_proc_spec_completer(const char *, size_t);
#endif /* not MERCURY_TRACE_TABLES_H */