Files
mercury/trace/mercury_trace_cmd_misc.c
Julien Fischer 70ba4db53d Fix a problem introduced in my previous change to the trace directory
Estimated hours taken: 4
Branches: main

Fix a problem introduced in my previous change to the trace directory
which introduced a dependency between the runtime and the trace directory
which broke compilation of the former in high-level C grades.

Fix up conversion specifiers in the printf control strings in the
trace directory.

runtime/mercury_stack_trace.h:
	Define MR_FrameLimit, MR_SpecLineLimit and MR_AncestorLevel here rather
	than in the trace directory because the code in the runtime for
	stack tracing refers to them.  (Some code that was only enabled
	in high-level C grades and referred to the above types was
	added as part of my last change; this is what broke compilation
	in those grades.)

	Rename MR_AncestorLevel to (the more general) MR_Level in the
	process.

runtime/mercury_stack_trace.c:
	Use MR_FrameLimit and friends in place of ints here.

trace/mercury_trace.h:
	Delete the typedefs for MR_FrameLimit and friends.

trace/mercury_trace_cmd_backward.c:
trace/mercury_trace_external.c:
	Conform to the above change.

trace/*.c:
	Change the signedness of conversion specifiers to conform
	to recent type changes.
2007-10-02 17:04:38 +00:00

340 lines
9.6 KiB
C

/*
** vim: ts=4 sw=4 expandtab
*/
/*
** Copyright (C) 1998-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 module implements the mdb commands in the "misc" category.
**
** The structure of these files is:
**
** - all the #includes
** - local macros and declarations of local static functions
** - one function for each command in the category
** - any auxiliary functions
** - any command argument strings
** - option processing functions.
*/
#include "mercury_std.h"
#include "mercury_getopt.h"
#include "mercury_trace_internal.h"
#include "mercury_trace_cmds.h"
#include "mercury_trace_cmd_misc.h"
#include "mercury_trace_cmd_parameter.h"
#include "mercury_trace_alias.h"
#include "mercury_trace_declarative.h"
#include "mercury_trace_spy.h"
#include "mdb.listing.mh"
/****************************************************************************/
static MR_bool MR_trace_options_ignore(MR_bool *ignore_errors,
char ***words, int *word_count);
static MR_bool MR_trace_options_confirmed(MR_bool *confirmed,
char ***words, int *word_count);
/****************************************************************************/
MR_Next
MR_trace_cmd_source(char **words, int word_count, MR_TraceCmdInfo *cmd,
MR_EventInfo *event_info, MR_Code **jumpaddr)
{
MR_bool ignore_errors;
char **args;
ignore_errors = MR_FALSE;
if (! MR_trace_options_ignore(&ignore_errors, &words, &word_count)) {
; /* the usage message has already been printed */
} else if (word_count >= 2) {
/*
** If the source fails, the error message
** will have already been printed by MR_trace_source
** (unless ignore_errors suppresses the message).
*/
if (word_count == 2) {
args = NULL;
} else {
args = &words[2];
}
(void) MR_trace_source(words[1], ignore_errors, args,
word_count - 2);
} else {
MR_trace_usage_cur_cmd();
}
return KEEP_INTERACTING;
}
MR_Next
MR_trace_cmd_save(char **words, int word_count, MR_TraceCmdInfo *cmd,
MR_EventInfo *event_info, MR_Code **jumpaddr)
{
if (word_count == 2) {
FILE *fp;
MR_bool found_error;
MR_Word path_list;
fp = fopen(words[1], "w");
if (fp == NULL) {
fflush(MR_mdb_out);
fprintf(MR_mdb_err, "mdb: error opening `%s': %s.\n",
words[1], strerror(errno));
return KEEP_INTERACTING;
}
MR_trace_print_all_aliases(fp, MR_TRUE);
switch (MR_default_print_level) {
case MR_PRINT_LEVEL_NONE:
fprintf(fp, "printlevel none\n");
break;
case MR_PRINT_LEVEL_SOME:
fprintf(fp, "printlevel some\n");
break;
case MR_PRINT_LEVEL_ALL:
fprintf(fp, "printlevel all\n");
break;
}
if (MR_echo_commands) {
fprintf(fp, "echo on\n");
} else {
fprintf(fp, "echo off\n");
}
if (MR_scroll_control) {
fprintf(fp, "scroll on\n");
} else {
fprintf(fp, "scroll off\n");
}
fprintf(fp, "scroll %" MR_INTEGER_LENGTH_MODIFIER "u\n",
MR_scroll_limit);
fprintf(fp, "stack_default_limit %d\n", MR_stack_default_line_limit);
switch (MR_context_position) {
case MR_CONTEXT_NOWHERE:
fprintf(fp, "context nowhere\n");
break;
case MR_CONTEXT_AFTER:
fprintf(fp, "context after\n");
break;
case MR_CONTEXT_BEFORE:
fprintf(fp, "context before\n");
break;
case MR_CONTEXT_PREVLINE:
fprintf(fp, "context prevline\n");
break;
case MR_CONTEXT_NEXTLINE:
fprintf(fp, "context nextline\n");
break;
}
if (MR_print_goal_paths) {
fprintf(fp, "goal_paths on\n");
} else {
fprintf(fp, "goal_paths off\n");
}
found_error = MR_save_spy_points(fp, MR_mdb_err);
switch (MR_default_breakpoint_scope) {
case MR_SPY_ALL:
fprintf(fp, "scope all\n");
break;
case MR_SPY_INTERFACE:
fprintf(fp, "scope interface\n");
break;
case MR_SPY_ENTRY:
fprintf(fp, "scope entry\n");
break;
case MR_SPY_LINENO:
case MR_SPY_SPECIFIC:
case MR_SPY_USER_EVENT:
case MR_SPY_USER_EVENT_SET:
MR_fatal_error("save cmd: invalid default scope");
}
MR_trace_print_all_browser_params(fp, MR_TRUE);
MR_decl_print_all_trusted(fp, MR_TRUE);
if (MR_dice_fail_trace_counts_file != NULL) {
fprintf(fp, "fail_trace_counts %s\n",
MR_dice_fail_trace_counts_file);
}
if (MR_dice_pass_trace_counts_file != NULL) {
fprintf(fp, "pass_trace_counts %s\n",
MR_dice_pass_trace_counts_file);
}
fprintf(fp, "list_context_lines %" MR_INTEGER_LENGTH_MODIFIER "u\n",
MR_num_context_lines);
MR_TRACE_CALL_MERCURY(
path_list = ML_LISTING_get_list_path(MR_listing_path);
if (! MR_list_is_empty(path_list)) {
fprintf(fp, "list_path");
while (! MR_list_is_empty(path_list)) {
fprintf(fp, " %s", (const char *) MR_list_head(path_list));
path_list = MR_list_tail(path_list);
}
fprintf(fp, "\n");
}
);
if (found_error) {
fflush(MR_mdb_out);
fprintf(MR_mdb_err, "mdb: could not save debugger state to %s.\n",
words[1]);
(void) fclose(fp);
} else if (fclose(fp) != 0) {
fflush(MR_mdb_out);
fprintf(MR_mdb_err, "mdb: error closing `%s': %s.\n",
words[1], strerror(errno));
} else {
fprintf(MR_mdb_out, "Debugger state saved to %s.\n", words[1]);
}
} else {
MR_trace_usage_cur_cmd();
}
return KEEP_INTERACTING;
}
MR_Next
MR_trace_cmd_quit(char **words, int word_count, MR_TraceCmdInfo *cmd,
MR_EventInfo *event_info, MR_Code **jumpaddr)
{
MR_bool confirmed;
confirmed = MR_FALSE;
if (! MR_trace_options_confirmed(&confirmed, &words, &word_count)) {
; /* the usage message has already been printed */
} else if (word_count == 1) {
if (! confirmed) {
char *line2;
line2 = MR_trace_getline("mdb: are you sure you want to quit? ",
MR_mdb_in, MR_mdb_out);
if (line2 == NULL) {
/* This means the user input EOF. */
confirmed = MR_TRUE;
} else {
int i = 0;
while (line2[i] != '\0' && MR_isspace(line2[i])) {
i++;
}
if (line2[i] == 'y' || line2[i] == 'Y') {
confirmed = MR_TRUE;
}
MR_free(line2);
}
}
if (confirmed) {
MR_trace_maybe_close_source_window(MR_FALSE);
exit(EXIT_SUCCESS);
}
} else {
MR_trace_usage_cur_cmd();
}
return KEEP_INTERACTING;
}
/****************************************************************************/
/*
** It's better to have a single completion where possible,
** so don't include `-i' here.
*/
const char *const MR_trace_source_cmd_args[] =
{ "--ignore-errors", NULL };
const char *const MR_trace_quit_cmd_args[] =
{ "-y", NULL };
/****************************************************************************/
static struct MR_option MR_trace_ignore_opts[] =
{
{ "ignore-errors", MR_no_argument, NULL, 'i' },
{ NULL, MR_no_argument, NULL, 0 }
};
static MR_bool
MR_trace_options_ignore(MR_bool *ignore_errors, char ***words, int *word_count)
{
int c;
MR_optind = 0;
while ((c = MR_getopt_long(*word_count, *words, "i",
MR_trace_ignore_opts, NULL)) != EOF)
{
switch (c) {
case 'i':
*ignore_errors = MR_TRUE;
break;
default:
MR_trace_usage_cur_cmd();
return MR_FALSE;
}
}
*words = *words + MR_optind - 1;
*word_count = *word_count - MR_optind + 1;
return MR_TRUE;
}
static MR_bool
MR_trace_options_confirmed(MR_bool *confirmed, char ***words, int *word_count)
{
int c;
MR_optind = 0;
while ((c = MR_getopt(*word_count, *words, "NYny")) != EOF) {
switch (c) {
case 'n':
case 'N':
*confirmed = MR_FALSE;
break;
case 'y':
case 'Y':
*confirmed = MR_TRUE;
break;
default:
MR_trace_usage_cur_cmd();
return MR_FALSE;
}
}
*words = *words + MR_optind - 1;
*word_count = *word_count - MR_optind + 1;
return MR_TRUE;
}
/****************************************************************************/