mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 01:13:30 +00:00
The crash that this diff fixes occurred when giving a command such as
"print Var^1" to mdb, where the first argument of Var is a direct arg.
runtime/mercury_ml_expand_body.h:
When deconstructing a term with a direct arg, return NULL
as the value of expand_info->chosen_arg_word_sized_ptr.
The crash occurred when we returned a non-null pointer,
which violated the expectations of trace/mercury_trace_vars.c
and its callers. (Not surprising, since those that function and
its callers were written long before the direct_arg optimization
was added to the system.)
runtime/mercury_deconstruct.h:
Document the rationale behind the above changes. (The contents of
mercury_ml_expand_body.h are #included in mercury_deconstruct.c.)
trace/mercury_trace_vars.c:
Add the debugging code I used to track down this issue, in disabled form.
Fix missing copyright year.
trace/mercury_trace_browse.c:
Delete obsolete comment.
Fix missing copyright years.
tests/debugger/direct_arg_test.{m,inp,exp}:
A test case for this bug.
tests/debugger/Mmakefile:
Enable the new test case.
compiler/hlds_out_type_table.m:
When dumping out the data constructors in the type table,
if a constructor has names for some of its fields,
put the name and the type of each field on different lines.
In the original test case for this bug, of which direct_arg_test.m
is an extreme simplification, pretty much every line overflows
without this.
Also, factor out some duplicated code, and replace bools with values
of a bespoke type.
436 lines
12 KiB
C
436 lines
12 KiB
C
// vim: ts=4 sw=4 expandtab ft=c
|
|
|
|
// Copyright (C) 1998-2006 The University of Melbourne.
|
|
// Copyright (C) 2017-2018, 2020-2023, 2026 The Mercury team.
|
|
// This file is distributed under the terms specified in COPYING.LIB.
|
|
|
|
// mercury_trace_browse.c
|
|
//
|
|
// Main author: fjh
|
|
//
|
|
// This file provides the C interface to browser/browse.m
|
|
// and browser/interactive_query.m.
|
|
|
|
// Some header files refer to files automatically generated by the Mercury
|
|
// compiler for modules in the browser and library directories.
|
|
|
|
#include "mercury_imp.h"
|
|
#include "mercury_deep_copy.h"
|
|
|
|
#include "mercury_trace_browse.h"
|
|
#include "mercury_trace_util.h"
|
|
#include "mercury_trace_internal.h"
|
|
#include "mercury_trace_external.h"
|
|
|
|
#include "mdb.browse.mh"
|
|
#include "mdb.browser_info.mh"
|
|
#include "mdb.browser_term.mh"
|
|
#include "mdb.interactive_query.mh"
|
|
#include "mdb.save_term.mh"
|
|
|
|
#include "type_desc.mh"
|
|
|
|
#include <stdio.h>
|
|
|
|
MR_TypeInfo MR_trace_browser_persistent_state_type;
|
|
|
|
MR_Word MR_trace_browser_persistent_state;
|
|
|
|
MR_Word
|
|
MR_type_value_to_browser_term(MR_TypeInfo type_info, MR_Word value)
|
|
{
|
|
MR_Word browser_term;
|
|
|
|
MR_TRACE_CALL_MERCURY(
|
|
browser_term = ML_BROWSE_plain_term_to_browser_term(
|
|
(MR_Word) type_info, value);
|
|
);
|
|
return browser_term;
|
|
}
|
|
|
|
MR_Word
|
|
MR_univ_to_browser_term(MR_Word univ)
|
|
{
|
|
MR_Word browser_term;
|
|
|
|
MR_TRACE_CALL_MERCURY(
|
|
browser_term = ML_BROWSE_univ_to_browser_term(univ);
|
|
);
|
|
return browser_term;
|
|
}
|
|
|
|
MR_Word
|
|
MR_synthetic_to_browser_term(const char *functor, MR_Word arg_list,
|
|
MR_bool is_func)
|
|
{
|
|
MR_Word browser_term;
|
|
|
|
MR_TRACE_CALL_MERCURY(
|
|
browser_term = ML_BROWSE_synthetic_term_to_browser_term(
|
|
(MR_String) (MR_Integer) functor, arg_list, is_func);
|
|
);
|
|
return browser_term;
|
|
}
|
|
|
|
void
|
|
MR_trace_save_term(const char *filename, MR_Word browser_term)
|
|
{
|
|
MercuryFile mdb_out;
|
|
MR_String mercury_filename;
|
|
MR_String mercury_format;
|
|
|
|
MR_trace_browse_ensure_init();
|
|
|
|
// cast away const
|
|
mercury_filename = (MR_String) (MR_Integer) filename;
|
|
mercury_format = (MR_String) (MR_Integer) "default";
|
|
MR_c_file_to_mercury_file(MR_mdb_out, &mdb_out);
|
|
MR_TRACE_CALL_MERCURY(
|
|
ML_BROWSE_save_term_to_file(MR_wrap_output_stream(&mdb_out),
|
|
mercury_filename, mercury_format, browser_term);
|
|
);
|
|
}
|
|
|
|
void
|
|
MR_trace_save_term_xml(const char *filename, MR_Word browser_term)
|
|
{
|
|
MercuryFile mdb_out;
|
|
MR_String mercury_filename;
|
|
|
|
// cast away const
|
|
mercury_filename = (MR_String) (MR_Integer) filename;
|
|
|
|
MR_c_file_to_mercury_file(MR_mdb_out, &mdb_out);
|
|
MR_TRACE_CALL_MERCURY(
|
|
ML_BROWSE_save_term_to_file_xml(MR_wrap_output_stream(&mdb_out),
|
|
mercury_filename, browser_term);
|
|
);
|
|
}
|
|
|
|
void
|
|
MR_trace_save_term_doc(const char *filename, MR_Word browser_term)
|
|
{
|
|
MercuryFile mdb_out;
|
|
MR_String mercury_filename;
|
|
|
|
MR_trace_browse_ensure_init();
|
|
|
|
// cast away const
|
|
mercury_filename = (MR_String) (MR_Integer) filename;
|
|
|
|
MR_c_file_to_mercury_file(MR_mdb_out, &mdb_out);
|
|
MR_TRACE_CALL_MERCURY(
|
|
ML_BROWSE_save_term_to_file_doc(MR_wrap_output_stream(&mdb_out),
|
|
mercury_filename, browser_term);
|
|
);
|
|
}
|
|
|
|
void
|
|
MR_trace_save_and_invoke_web_browser(MR_Word browser_term)
|
|
{
|
|
MercuryFile mdb_out;
|
|
MercuryFile mdb_err;
|
|
|
|
MR_c_file_to_mercury_file(MR_mdb_out, &mdb_out);
|
|
MR_c_file_to_mercury_file(MR_mdb_err, &mdb_err);
|
|
|
|
MR_TRACE_CALL_MERCURY(
|
|
ML_BROWSE_save_and_browse_browser_term_web(
|
|
MR_wrap_output_stream(&mdb_out),
|
|
MR_wrap_output_stream(&mdb_err),
|
|
browser_term, MR_trace_browser_persistent_state);
|
|
);
|
|
}
|
|
|
|
MR_bool
|
|
MR_trace_is_portray_format(const char *str, MR_BrowseFormat *format)
|
|
{
|
|
*format = MR_BROWSE_DEFAULT_FORMAT;
|
|
|
|
if (MR_streq(str, "flat")) {
|
|
*format = MR_BROWSE_FORMAT_FLAT;
|
|
return MR_TRUE;
|
|
} else if (MR_streq(str, "raw_pretty")) {
|
|
*format = MR_BROWSE_FORMAT_RAW_PRETTY;
|
|
return MR_TRUE;
|
|
} else if (MR_streq(str, "verbose")) {
|
|
*format = MR_BROWSE_FORMAT_VERBOSE;
|
|
return MR_TRUE;
|
|
} else if (MR_streq(str, "pretty")) {
|
|
*format = MR_BROWSE_FORMAT_PRETTY;
|
|
return MR_TRUE;
|
|
}
|
|
|
|
return MR_FALSE;
|
|
}
|
|
|
|
void
|
|
MR_trace_browse(MR_Word type_info, MR_Word value, MR_BrowseFormat format)
|
|
{
|
|
MercuryFile mdb_in;
|
|
MercuryFile mdb_out;
|
|
MR_Word maybe_mark;
|
|
MR_Word browser_term;
|
|
|
|
MR_trace_browse_ensure_init();
|
|
|
|
MR_c_file_to_mercury_file(MR_mdb_in, &mdb_in);
|
|
MR_c_file_to_mercury_file(MR_mdb_out, &mdb_out);
|
|
|
|
browser_term = MR_type_value_to_browser_term((MR_TypeInfo) type_info,
|
|
value);
|
|
|
|
if (format != MR_BROWSE_DEFAULT_FORMAT) {
|
|
MR_TRACE_CALL_MERCURY(
|
|
ML_BROWSE_browse_browser_term_format_no_modes(
|
|
MR_wrap_input_stream(&mdb_in),
|
|
MR_wrap_output_stream(&mdb_out),
|
|
(MR_Word) format, browser_term,
|
|
MR_trace_browser_persistent_state,
|
|
&MR_trace_browser_persistent_state);
|
|
);
|
|
} else {
|
|
MR_TRACE_CALL_MERCURY(
|
|
ML_BROWSE_browse_browser_term_no_modes(
|
|
MR_wrap_input_stream(&mdb_in),
|
|
MR_wrap_output_stream(&mdb_out),
|
|
browser_term, &maybe_mark,
|
|
MR_trace_browser_persistent_state,
|
|
&MR_trace_browser_persistent_state);
|
|
);
|
|
}
|
|
MR_trace_browser_persistent_state =
|
|
MR_make_permanent(MR_trace_browser_persistent_state,
|
|
MR_trace_browser_persistent_state_type);
|
|
}
|
|
|
|
void
|
|
MR_trace_browse_goal(MR_ConstString name, MR_Word arg_list, MR_Word is_func,
|
|
MR_BrowseFormat format)
|
|
{
|
|
MercuryFile mdb_in;
|
|
MercuryFile mdb_out;
|
|
MR_Word maybe_mark;
|
|
MR_Word browser_term;
|
|
|
|
MR_trace_browse_ensure_init();
|
|
|
|
MR_c_file_to_mercury_file(MR_mdb_in, &mdb_in);
|
|
MR_c_file_to_mercury_file(MR_mdb_out, &mdb_out);
|
|
|
|
browser_term = MR_synthetic_to_browser_term(name, arg_list, is_func);
|
|
|
|
if (format != MR_BROWSE_DEFAULT_FORMAT) {
|
|
MR_TRACE_CALL_MERCURY(
|
|
ML_BROWSE_browse_browser_term_format_no_modes(
|
|
MR_wrap_input_stream(&mdb_in),
|
|
MR_wrap_output_stream(&mdb_out),
|
|
(MR_Word) format, browser_term,
|
|
MR_trace_browser_persistent_state,
|
|
&MR_trace_browser_persistent_state);
|
|
);
|
|
} else {
|
|
MR_TRACE_CALL_MERCURY(
|
|
ML_BROWSE_browse_browser_term_no_modes(
|
|
MR_wrap_input_stream(&mdb_in),
|
|
MR_wrap_output_stream(&mdb_out),
|
|
browser_term, &maybe_mark,
|
|
MR_trace_browser_persistent_state,
|
|
&MR_trace_browser_persistent_state);
|
|
);
|
|
}
|
|
MR_trace_browser_persistent_state =
|
|
MR_make_permanent(MR_trace_browser_persistent_state,
|
|
MR_trace_browser_persistent_state_type);
|
|
}
|
|
|
|
// MR_trace_browse_external() is the same as MR_trace_browse() except it
|
|
// uses debugger_socket_in and debugger_socket_out to read program-readable
|
|
// terms, whereas MR_trace_browse() uses mdb_in and mdb_out to read
|
|
// human-readable strings.
|
|
|
|
#ifdef MR_USE_EXTERNAL_DEBUGGER
|
|
|
|
void
|
|
MR_trace_browse_external(MR_Word type_info, MR_Word value,
|
|
MR_BrowseCallerType caller, MR_BrowseFormat format)
|
|
{
|
|
MR_trace_browse_ensure_init();
|
|
|
|
MR_TRACE_CALL_MERCURY(
|
|
ML_BROWSE_browse_external_no_modes(type_info,
|
|
MR_wrap_input_stream(&MR_debugger_socket_in),
|
|
MR_wrap_output_stream(&MR_debugger_socket_out),
|
|
value,
|
|
MR_trace_browser_persistent_state,
|
|
&MR_trace_browser_persistent_state);
|
|
);
|
|
MR_trace_browser_persistent_state =
|
|
MR_make_permanent(MR_trace_browser_persistent_state,
|
|
MR_trace_browser_persistent_state_type);
|
|
}
|
|
|
|
#endif
|
|
|
|
void
|
|
MR_trace_print(MR_Word type_info, MR_Word value,
|
|
MR_BrowseCallerType caller_type, MR_BrowseFormat format)
|
|
{
|
|
MercuryFile mdb_out;
|
|
MR_Word browser_term;
|
|
|
|
MR_trace_browse_ensure_init();
|
|
|
|
MR_c_file_to_mercury_file(MR_mdb_out, &mdb_out);
|
|
|
|
browser_term =
|
|
MR_type_value_to_browser_term((MR_TypeInfo) type_info, value);
|
|
|
|
if (format != MR_BROWSE_DEFAULT_FORMAT) {
|
|
MR_TRACE_CALL_MERCURY(
|
|
ML_BROWSE_print_browser_term_format(
|
|
MR_wrap_output_stream(&mdb_out),
|
|
(MR_Word) caller_type, (MR_Word) format, browser_term,
|
|
MR_trace_browser_persistent_state);
|
|
);
|
|
} else {
|
|
MR_TRACE_CALL_MERCURY(
|
|
ML_BROWSE_print_browser_term(
|
|
MR_wrap_output_stream(&mdb_out),
|
|
(MR_Word) caller_type, browser_term,
|
|
MR_trace_browser_persistent_state);
|
|
);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_trace_print_goal(MR_ConstString name, MR_Word arg_list, MR_Word is_func,
|
|
MR_BrowseCallerType caller, MR_BrowseFormat format)
|
|
{
|
|
MercuryFile mdb_out;
|
|
MR_Word browser_term;
|
|
|
|
MR_trace_browse_ensure_init();
|
|
|
|
MR_c_file_to_mercury_file(MR_mdb_out, &mdb_out);
|
|
|
|
browser_term = MR_synthetic_to_browser_term(name, arg_list, is_func);
|
|
|
|
if (format != MR_BROWSE_DEFAULT_FORMAT) {
|
|
MR_TRACE_CALL_MERCURY(
|
|
ML_BROWSE_print_browser_term_format(
|
|
MR_wrap_output_stream(&mdb_out),
|
|
(MR_Word) caller, (MR_Word) format, browser_term,
|
|
MR_trace_browser_persistent_state);
|
|
);
|
|
} else {
|
|
MR_TRACE_CALL_MERCURY(
|
|
ML_BROWSE_print_browser_term(
|
|
MR_wrap_output_stream(&mdb_out),
|
|
(MR_Word) caller, browser_term,
|
|
MR_trace_browser_persistent_state);
|
|
);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_trace_print_all_browser_params(FILE *fp)
|
|
{
|
|
MR_String param_string;
|
|
|
|
MR_trace_browse_ensure_init();
|
|
MR_TRACE_CALL_MERCURY(
|
|
ML_BROWSE_browser_params_to_string(MR_trace_browser_persistent_state,
|
|
¶m_string);
|
|
);
|
|
|
|
fputs(param_string, fp);
|
|
}
|
|
|
|
void
|
|
MR_trace_browse_ensure_init(void)
|
|
{
|
|
static MR_bool done = MR_FALSE;
|
|
MR_Word typeinfo_type_word;
|
|
MR_Word MR_trace_browser_persistent_state_type_word;
|
|
|
|
if (! done) {
|
|
MR_TRACE_CALL_MERCURY(
|
|
typeinfo_type_word = ML_get_type_info_for_type_info();
|
|
ML_BROWSE_browser_persistent_state_type(
|
|
&MR_trace_browser_persistent_state_type_word);
|
|
ML_BROWSE_init_persistent_state(
|
|
&MR_trace_browser_persistent_state);
|
|
);
|
|
|
|
MR_trace_browser_persistent_state_type =
|
|
(MR_TypeInfo) MR_make_permanent(
|
|
MR_trace_browser_persistent_state_type_word,
|
|
(MR_TypeInfo) typeinfo_type_word);
|
|
MR_trace_browser_persistent_state = MR_make_permanent(
|
|
MR_trace_browser_persistent_state,
|
|
MR_trace_browser_persistent_state_type);
|
|
done = MR_TRUE;
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_trace_query(MR_QueryType type, const char *options, int num_imports,
|
|
char *imports[])
|
|
{
|
|
MR_ConstString options_on_heap;
|
|
MR_Word imports_list;
|
|
MR_Word names_list;
|
|
MR_Word values_list;
|
|
MercuryFile mdb_in;
|
|
MercuryFile mdb_out;
|
|
int i;
|
|
|
|
MR_c_file_to_mercury_file(MR_mdb_in, &mdb_in);
|
|
MR_c_file_to_mercury_file(MR_mdb_out, &mdb_out);
|
|
|
|
if (options == NULL) {
|
|
options = "";
|
|
}
|
|
|
|
MR_TRACE_USE_HP(
|
|
MR_make_aligned_string(options_on_heap, options);
|
|
|
|
imports_list = MR_list_empty();
|
|
for (i = num_imports; i > 0; i--) {
|
|
MR_ConstString this_import;
|
|
MR_make_aligned_string(this_import, imports[i - 1]);
|
|
imports_list = MR_string_list_cons((MR_Word) this_import,
|
|
imports_list);
|
|
}
|
|
);
|
|
|
|
MR_trace_return_bindings(&names_list, &values_list);
|
|
|
|
MR_TRACE_CALL_MERCURY(
|
|
ML_query(type, imports_list, (MR_String) options_on_heap,
|
|
names_list, values_list, MR_wrap_input_stream(&mdb_in),
|
|
MR_wrap_output_stream(&mdb_out));
|
|
);
|
|
}
|
|
|
|
#ifdef MR_USE_EXTERNAL_DEBUGGER
|
|
|
|
void
|
|
MR_trace_query_external(MR_QueryType type, MR_String options, int num_imports,
|
|
MR_Word imports_list)
|
|
{
|
|
MR_Word names_list;
|
|
MR_Word values_list;
|
|
|
|
MR_trace_return_bindings(&names_list, &values_list);
|
|
|
|
MR_TRACE_CALL_MERCURY(
|
|
ML_query_external(type, imports_list, options, names_list, values_list,
|
|
MR_wrap_input_stream(&MR_debugger_socket_in),
|
|
MR_wrap_output_stream(&MR_debugger_socket_out));
|
|
);
|
|
}
|
|
|
|
#endif
|