mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-19 07:45:09 +00:00
trace/mercury_trace.h:
Avoid a warning from the C compiler about casting -1 to an enum
by adding bool next to the enum that says whether the enum is actually
defined, or is supposed to be set later (the latter is what the cast -1
meant).
trace/mercury_trace_cmds.h:
Rename the type MR_Trace_Command_Info to MR_TraceCmdTableEntry,
since this (a) says more about the values of the type, (b) avoids
confusion with the separate MR_TraceCmdInfo type (the one that
contained the enum mentioned above), and (c) avoids combining
underscores with CamelCase.
trace/mercury_trace_spy.c:
Avoid some warnings about switches on enums specifying -1 as a case.
trace/mercury_trace.c:
trace/mercury_trace_*.[ch]:
Conform to the above changes.
600 lines
20 KiB
C
600 lines
20 KiB
C
/*
|
|
** vim: ts=4 sw=4 expandtab
|
|
*/
|
|
/*
|
|
** Copyright (C) 1998-2008,2012 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 "forward" 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_forward.h"
|
|
#include "mercury_trace_cmd_parameter.h"
|
|
#include "mercury_trace_util.h"
|
|
|
|
/****************************************************************************/
|
|
|
|
static MR_bool MR_trace_options_movement_cmd(MR_TraceCmdInfo *cmd,
|
|
char ***words, int *word_count);
|
|
|
|
/****************************************************************************/
|
|
|
|
MR_Next
|
|
MR_trace_cmd_step(char **words, int word_count, MR_TraceCmdInfo *cmd,
|
|
MR_EventInfo *event_info, MR_Code **jumpaddr)
|
|
{
|
|
MR_Unsigned n;
|
|
|
|
cmd->MR_trace_strict = MR_FALSE;
|
|
cmd->MR_trace_print_level_specified = MR_FALSE;
|
|
cmd->MR_trace_print_level = MR_default_print_level;
|
|
MR_init_trace_check_integrity(cmd);
|
|
if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
|
|
; /* the usage message has already been printed */
|
|
} else if (word_count == 1) {
|
|
cmd->MR_trace_cmd = MR_CMD_STEP;
|
|
return STOP_INTERACTING;
|
|
} else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
|
|
cmd->MR_trace_cmd = MR_CMD_GOTO;
|
|
cmd->MR_trace_stop_event = MR_trace_event_number + n;
|
|
return STOP_INTERACTING;
|
|
} else {
|
|
MR_trace_usage_cur_cmd();
|
|
}
|
|
|
|
return KEEP_INTERACTING;
|
|
}
|
|
|
|
MR_Next
|
|
MR_trace_cmd_goto(char **words, int word_count, MR_TraceCmdInfo *cmd,
|
|
MR_EventInfo *event_info, MR_Code **jumpaddr)
|
|
{
|
|
MR_Unsigned n;
|
|
const char *generator_name;
|
|
|
|
cmd->MR_trace_strict = MR_TRUE;
|
|
cmd->MR_trace_print_level_specified = MR_FALSE;
|
|
cmd->MR_trace_print_level = MR_default_print_level;
|
|
MR_init_trace_check_integrity(cmd);
|
|
if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
|
|
; /* the usage message has already been printed */
|
|
} else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
|
|
generator_name = NULL;
|
|
if (MR_trace_event_number < n
|
|
|| !MR_cur_generator_is_named(generator_name))
|
|
{
|
|
cmd->MR_trace_cmd = MR_CMD_GOTO;
|
|
cmd->MR_trace_stop_event = n;
|
|
cmd->MR_trace_stop_generator = generator_name;
|
|
return STOP_INTERACTING;
|
|
} else {
|
|
/* XXX this message is misleading */
|
|
fflush(MR_mdb_out);
|
|
fprintf(MR_mdb_err, "The debugger cannot go to a past event.\n");
|
|
}
|
|
#ifdef MR_USE_MINIMAL_MODEL_OWN_STACKS
|
|
} else if (word_count == 3 && MR_trace_is_natural_number(words[1], &n)) {
|
|
generator_name = words[2];
|
|
if (MR_trace_event_number < n
|
|
|| !MR_cur_generator_is_named(generator_name))
|
|
{
|
|
cmd->MR_trace_cmd = MR_CMD_GOTO;
|
|
cmd->MR_trace_stop_event = n;
|
|
/*
|
|
** We don't ever deallocate the memory allocated here,
|
|
** but this memory leak leaks only negligible amounts of memory.
|
|
*/
|
|
cmd->MR_trace_stop_generator = strdup(generator_name);
|
|
return STOP_INTERACTING;
|
|
} else {
|
|
/* XXX this message is misleading */
|
|
fflush(MR_mdb_out);
|
|
fprintf(MR_mdb_err, "The debugger cannot go to a past event.\n");
|
|
}
|
|
#endif
|
|
} else {
|
|
MR_trace_usage_cur_cmd();
|
|
}
|
|
|
|
return KEEP_INTERACTING;
|
|
}
|
|
|
|
MR_Next
|
|
MR_trace_cmd_next(char **words, int word_count, MR_TraceCmdInfo *cmd,
|
|
MR_EventInfo *event_info, MR_Code **jumpaddr)
|
|
{
|
|
const MR_ProcLayout *proc_layout;
|
|
const MR_LabelLayout *ancestor_layout;
|
|
MR_Unsigned depth;
|
|
MR_Unsigned stop_depth;
|
|
MR_Unsigned n;
|
|
MR_TracePort port;
|
|
MR_Word *base_sp;
|
|
MR_Word *base_curfr;
|
|
MR_Unsigned reused_frames;
|
|
MR_Level actual_level;
|
|
const char *problem; /* not used */
|
|
|
|
depth = event_info->MR_call_depth;
|
|
cmd->MR_trace_strict = MR_TRUE;
|
|
cmd->MR_trace_print_level_specified = MR_FALSE;
|
|
cmd->MR_trace_print_level = MR_default_print_level;
|
|
MR_init_trace_check_integrity(cmd);
|
|
if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
|
|
; /* the usage message has already been printed */
|
|
return KEEP_INTERACTING;
|
|
} else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
|
|
stop_depth = depth - n;
|
|
} else if (word_count == 1) {
|
|
n = 0;
|
|
stop_depth = depth;
|
|
} else {
|
|
MR_trace_usage_cur_cmd();
|
|
return KEEP_INTERACTING;
|
|
}
|
|
|
|
base_sp = MR_saved_sp(event_info->MR_saved_regs);
|
|
base_curfr = MR_saved_curfr(event_info->MR_saved_regs);
|
|
proc_layout = event_info->MR_event_sll->MR_sll_entry;
|
|
MR_trace_find_reused_frames(proc_layout, base_sp, reused_frames);
|
|
port = event_info->MR_trace_port;
|
|
|
|
if (depth == stop_depth &&
|
|
(MR_port_is_final(port) || port == MR_PORT_TAILREC_CALL))
|
|
{
|
|
MR_trace_do_noop();
|
|
} else if (depth - reused_frames <= stop_depth && stop_depth < depth) {
|
|
MR_trace_do_noop_tail_rec();
|
|
} else {
|
|
ancestor_layout = MR_find_nth_ancestor(event_info->MR_event_sll,
|
|
n, &base_sp, &base_curfr, &actual_level, &problem);
|
|
if (ancestor_layout == NULL) {
|
|
fflush(MR_mdb_out);
|
|
if (problem != NULL) {
|
|
fprintf(MR_mdb_err, "mdb: %s\n", problem);
|
|
} else {
|
|
fprintf(MR_mdb_err, "mdb: not that many ancestors.\n");
|
|
}
|
|
return KEEP_INTERACTING;
|
|
} else if (actual_level != n) {
|
|
fflush(MR_mdb_out);
|
|
fprintf(MR_mdb_err,
|
|
"mdb: that stack frame has been reused, "
|
|
"will stop in reusing call.\n");
|
|
} else {
|
|
cmd->MR_trace_cmd = MR_CMD_NEXT;
|
|
cmd->MR_trace_stop_depth = stop_depth;
|
|
return STOP_INTERACTING;
|
|
}
|
|
}
|
|
|
|
return KEEP_INTERACTING;
|
|
}
|
|
|
|
MR_Next
|
|
MR_trace_cmd_finish(char **words, int word_count, MR_TraceCmdInfo *cmd,
|
|
MR_EventInfo *event_info, MR_Code **jumpaddr)
|
|
{
|
|
const MR_ProcLayout *proc_layout;
|
|
const MR_LabelLayout *ancestor_layout;
|
|
MR_Unsigned depth;
|
|
MR_Unsigned stop_depth;
|
|
MR_Unsigned n;
|
|
MR_Level ancestor_level;
|
|
MR_TracePort port;
|
|
MR_Word *base_sp;
|
|
MR_Word *base_curfr;
|
|
MR_Unsigned reused_frames;
|
|
MR_Level actual_level;
|
|
const char *problem; /* not used */
|
|
|
|
depth = event_info->MR_call_depth;
|
|
cmd->MR_trace_strict = MR_TRUE;
|
|
cmd->MR_trace_print_level_specified = MR_FALSE;
|
|
cmd->MR_trace_print_level = MR_default_print_level;
|
|
MR_init_trace_check_integrity(cmd);
|
|
if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
|
|
; /* the usage message has already been printed */
|
|
return KEEP_INTERACTING;
|
|
} else if (word_count == 2 &&
|
|
( MR_streq(words[1], "entry") || MR_streq(words[1], "clentry")))
|
|
{
|
|
if (MR_find_clique_entry_mdb(event_info, MR_CLIQUE_ENTRY_FRAME,
|
|
&ancestor_level))
|
|
{
|
|
/* the error message has already been printed */
|
|
return KEEP_INTERACTING;
|
|
}
|
|
} else if (word_count == 2 && MR_streq(words[1], "clparent"))
|
|
{
|
|
if (MR_find_clique_entry_mdb(event_info, MR_CLIQUE_ENTRY_PARENT_FRAME,
|
|
&ancestor_level))
|
|
{
|
|
/* the error message has already been printed */
|
|
return KEEP_INTERACTING;
|
|
}
|
|
} else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
|
|
ancestor_level = n;
|
|
} else if (word_count == 1) {
|
|
ancestor_level = 0;
|
|
} else {
|
|
MR_trace_usage_cur_cmd();
|
|
return KEEP_INTERACTING;
|
|
}
|
|
|
|
base_sp = MR_saved_sp(event_info->MR_saved_regs);
|
|
base_curfr = MR_saved_curfr(event_info->MR_saved_regs);
|
|
proc_layout = event_info->MR_event_sll->MR_sll_entry;
|
|
MR_trace_find_reused_frames(proc_layout, base_sp, reused_frames);
|
|
port = event_info->MR_trace_port;
|
|
|
|
stop_depth = depth - ancestor_level;
|
|
if (MR_port_is_final(port) && depth == stop_depth) {
|
|
MR_trace_do_noop();
|
|
} else if (MR_port_is_final(port) &&
|
|
depth - reused_frames <= stop_depth && stop_depth < depth)
|
|
{
|
|
MR_trace_do_noop_tail_rec();
|
|
} else {
|
|
ancestor_layout = MR_find_nth_ancestor(event_info->MR_event_sll,
|
|
ancestor_level, &base_sp, &base_curfr, &actual_level, &problem);
|
|
if (ancestor_layout == NULL) {
|
|
fflush(MR_mdb_out);
|
|
if (problem != NULL) {
|
|
fprintf(MR_mdb_err, "mdb: %s\n", problem);
|
|
} else {
|
|
fprintf(MR_mdb_err, "mdb: not that many ancestors.\n");
|
|
}
|
|
return KEEP_INTERACTING;
|
|
} else if (actual_level != ancestor_level) {
|
|
fflush(MR_mdb_out);
|
|
fprintf(MR_mdb_err, "%d %d\n",
|
|
(int) ancestor_level, (int) actual_level);
|
|
fprintf(MR_mdb_err,
|
|
"mdb: that stack frame has been reused, "
|
|
"will stop at finish of reusing call.\n");
|
|
} else {
|
|
cmd->MR_trace_cmd = MR_CMD_FINISH;
|
|
cmd->MR_trace_stop_depth = stop_depth;
|
|
return STOP_INTERACTING;
|
|
}
|
|
}
|
|
|
|
return KEEP_INTERACTING;
|
|
}
|
|
|
|
MR_Next
|
|
MR_trace_cmd_fail(char **words, int word_count, MR_TraceCmdInfo *cmd,
|
|
MR_EventInfo *event_info, MR_Code **jumpaddr)
|
|
{
|
|
MR_Determinism detism;
|
|
MR_Unsigned depth;
|
|
MR_Unsigned stop_depth;
|
|
MR_Unsigned n;
|
|
|
|
detism = event_info->MR_event_sll->MR_sll_entry->MR_sle_detism;
|
|
depth = event_info->MR_call_depth;
|
|
|
|
cmd->MR_trace_strict = MR_TRUE;
|
|
cmd->MR_trace_print_level_specified = MR_FALSE;
|
|
cmd->MR_trace_print_level = MR_default_print_level;
|
|
MR_init_trace_check_integrity(cmd);
|
|
if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
|
|
; /* the usage message has already been printed */
|
|
return KEEP_INTERACTING;
|
|
} else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
|
|
stop_depth = depth - n;
|
|
} else if (word_count == 1) {
|
|
stop_depth = depth;
|
|
} else {
|
|
MR_trace_usage_cur_cmd();
|
|
return KEEP_INTERACTING;
|
|
}
|
|
|
|
if (MR_DETISM_DET_STACK(detism)) {
|
|
fflush(MR_mdb_out);
|
|
fprintf(MR_mdb_err, "mdb: cannot continue until failure: "
|
|
"selected procedure has determinism %s.\n",
|
|
MR_detism_names[detism]);
|
|
return KEEP_INTERACTING;
|
|
}
|
|
|
|
/*
|
|
** A procedure that lives on the nondet stack cannot have its stack frame
|
|
** reused by tail recursive calls (at least not when any kind of debugging
|
|
** is enabled).
|
|
*/
|
|
|
|
if (depth == stop_depth && event_info->MR_trace_port == MR_PORT_FAIL) {
|
|
MR_trace_do_noop();
|
|
} else if (depth == stop_depth &&
|
|
event_info->MR_trace_port == MR_PORT_EXCEPTION)
|
|
{
|
|
fflush(MR_mdb_out);
|
|
fprintf(MR_mdb_err, "mdb: cannot continue until failure: "
|
|
"the call has raised an exception.\n");
|
|
} else {
|
|
cmd->MR_trace_cmd = MR_CMD_FAIL;
|
|
cmd->MR_trace_stop_depth = stop_depth;
|
|
return STOP_INTERACTING;
|
|
}
|
|
|
|
return KEEP_INTERACTING;
|
|
}
|
|
|
|
MR_Next
|
|
MR_trace_cmd_exception(char **words, int word_count, MR_TraceCmdInfo *cmd,
|
|
MR_EventInfo *event_info, MR_Code **jumpaddr)
|
|
{
|
|
cmd->MR_trace_strict = MR_TRUE;
|
|
cmd->MR_trace_print_level_specified = MR_FALSE;
|
|
cmd->MR_trace_print_level = MR_default_print_level;
|
|
MR_init_trace_check_integrity(cmd);
|
|
if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
|
|
; /* the usage message has already been printed */
|
|
} else if (word_count == 1) {
|
|
if (event_info->MR_trace_port != MR_PORT_EXCEPTION) {
|
|
cmd->MR_trace_cmd = MR_CMD_EXCP;
|
|
return STOP_INTERACTING;
|
|
} else {
|
|
MR_trace_do_noop();
|
|
}
|
|
} else {
|
|
MR_trace_usage_cur_cmd();
|
|
}
|
|
|
|
return KEEP_INTERACTING;
|
|
}
|
|
|
|
MR_Next
|
|
MR_trace_cmd_return(char **words, int word_count, MR_TraceCmdInfo *cmd,
|
|
MR_EventInfo *event_info, MR_Code **jumpaddr)
|
|
{
|
|
cmd->MR_trace_strict = MR_TRUE;
|
|
cmd->MR_trace_print_level_specified = MR_FALSE;
|
|
cmd->MR_trace_print_level = MR_default_print_level;
|
|
MR_init_trace_check_integrity(cmd);
|
|
if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
|
|
; /* the usage message has already been printed */
|
|
} else if (word_count == 1) {
|
|
if (event_info->MR_trace_port == MR_PORT_EXIT) {
|
|
cmd->MR_trace_cmd = MR_CMD_RETURN;
|
|
return STOP_INTERACTING;
|
|
} else {
|
|
MR_trace_do_noop();
|
|
}
|
|
} else {
|
|
MR_trace_usage_cur_cmd();
|
|
}
|
|
|
|
return KEEP_INTERACTING;
|
|
}
|
|
|
|
MR_Next
|
|
MR_trace_cmd_user(char **words, int word_count, MR_TraceCmdInfo *cmd,
|
|
MR_EventInfo *event_info, MR_Code **jumpaddr)
|
|
{
|
|
cmd->MR_trace_strict = MR_TRUE;
|
|
cmd->MR_trace_print_level_specified = MR_FALSE;
|
|
cmd->MR_trace_print_level = MR_default_print_level;
|
|
MR_init_trace_check_integrity(cmd);
|
|
if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
|
|
; /* the usage message has already been printed */
|
|
} else if (word_count == 1) {
|
|
cmd->MR_trace_cmd = MR_CMD_USER;
|
|
return STOP_INTERACTING;
|
|
} else {
|
|
MR_trace_usage_cur_cmd();
|
|
}
|
|
|
|
return KEEP_INTERACTING;
|
|
}
|
|
|
|
MR_Next
|
|
MR_trace_cmd_forward(char **words, int word_count, MR_TraceCmdInfo *cmd,
|
|
MR_EventInfo *event_info, MR_Code **jumpaddr)
|
|
{
|
|
cmd->MR_trace_strict = MR_TRUE;
|
|
cmd->MR_trace_print_level_specified = MR_FALSE;
|
|
cmd->MR_trace_print_level = MR_default_print_level;
|
|
MR_init_trace_check_integrity(cmd);
|
|
if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
|
|
; /* the usage message has already been printed */
|
|
} else if (word_count == 1) {
|
|
MR_TracePort port;
|
|
|
|
port = event_info->MR_trace_port;
|
|
if (port == MR_PORT_FAIL ||
|
|
port == MR_PORT_REDO ||
|
|
port == MR_PORT_EXCEPTION)
|
|
{
|
|
cmd->MR_trace_cmd = MR_CMD_RESUME_FORWARD;
|
|
return STOP_INTERACTING;
|
|
} else {
|
|
MR_trace_do_noop();
|
|
}
|
|
} else {
|
|
MR_trace_usage_cur_cmd();
|
|
}
|
|
|
|
return KEEP_INTERACTING;
|
|
}
|
|
|
|
MR_Next
|
|
MR_trace_cmd_mindepth(char **words, int word_count, MR_TraceCmdInfo *cmd,
|
|
MR_EventInfo *event_info, MR_Code **jumpaddr)
|
|
{
|
|
MR_Unsigned newdepth;
|
|
|
|
cmd->MR_trace_strict = MR_TRUE;
|
|
cmd->MR_trace_print_level_specified = MR_FALSE;
|
|
cmd->MR_trace_print_level = MR_default_print_level;
|
|
MR_init_trace_check_integrity(cmd);
|
|
if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
|
|
; /* the usage message has already been printed */
|
|
} else if (word_count == 2 &&
|
|
MR_trace_is_natural_number(words[1], &newdepth))
|
|
{
|
|
cmd->MR_trace_cmd = MR_CMD_MIN_DEPTH;
|
|
cmd->MR_trace_stop_depth = newdepth;
|
|
return STOP_INTERACTING;
|
|
} else {
|
|
MR_trace_usage_cur_cmd();
|
|
}
|
|
|
|
return KEEP_INTERACTING;
|
|
}
|
|
|
|
MR_Next
|
|
MR_trace_cmd_maxdepth(char **words, int word_count, MR_TraceCmdInfo *cmd,
|
|
MR_EventInfo *event_info, MR_Code **jumpaddr)
|
|
{
|
|
MR_Unsigned newdepth;
|
|
|
|
cmd->MR_trace_strict = MR_TRUE;
|
|
cmd->MR_trace_print_level_specified = MR_FALSE;
|
|
cmd->MR_trace_print_level = MR_default_print_level;
|
|
MR_init_trace_check_integrity(cmd);
|
|
if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
|
|
; /* the usage message has already been printed */
|
|
} else if (word_count == 2 &&
|
|
MR_trace_is_natural_number(words[1], &newdepth))
|
|
{
|
|
cmd->MR_trace_cmd = MR_CMD_MAX_DEPTH;
|
|
cmd->MR_trace_stop_depth = newdepth;
|
|
return STOP_INTERACTING;
|
|
} else {
|
|
MR_trace_usage_cur_cmd();
|
|
}
|
|
|
|
return KEEP_INTERACTING;
|
|
}
|
|
|
|
MR_Next
|
|
MR_trace_cmd_continue(char **words, int word_count, MR_TraceCmdInfo *cmd,
|
|
MR_EventInfo *event_info, MR_Code **jumpaddr)
|
|
{
|
|
cmd->MR_trace_strict = MR_FALSE;
|
|
cmd->MR_trace_print_level_specified = MR_FALSE;
|
|
cmd->MR_trace_print_level = MR_default_print_level;
|
|
MR_init_trace_check_integrity(cmd);
|
|
if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
|
|
; /* the usage message has already been printed */
|
|
} else if (word_count == 1) {
|
|
cmd->MR_trace_cmd = MR_CMD_TO_END;
|
|
if (! cmd->MR_trace_print_level_specified) {
|
|
/*
|
|
** The user did not specify the print level;
|
|
** select the intelligent default.
|
|
*/
|
|
if (cmd->MR_trace_strict) {
|
|
cmd->MR_trace_print_level = MR_PRINT_LEVEL_NONE;
|
|
} else {
|
|
cmd->MR_trace_print_level = MR_PRINT_LEVEL_SOME;
|
|
}
|
|
}
|
|
return STOP_INTERACTING;
|
|
} else {
|
|
MR_trace_usage_cur_cmd();
|
|
}
|
|
|
|
return KEEP_INTERACTING;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
const char *const MR_trace_movement_cmd_args[] =
|
|
{ "-N", "-S", "-a", "-i", "-n", "-s",
|
|
"--none", "--some", "--all", "--integrity",
|
|
"--strict", "--no-strict", NULL };
|
|
|
|
/****************************************************************************/
|
|
|
|
static struct MR_option MR_trace_movement_cmd_opts[] =
|
|
{
|
|
{ "all", MR_no_argument, NULL, 'a' },
|
|
{ "none", MR_no_argument, NULL, 'n' },
|
|
{ "some", MR_no_argument, NULL, 's' },
|
|
{ "nostrict", MR_no_argument, NULL, 'N' },
|
|
{ "strict", MR_no_argument, NULL, 'S' },
|
|
#ifdef MR_TRACE_CHECK_INTEGRITY
|
|
{ "integrity", MR_no_argument, NULL, 'i' },
|
|
#endif
|
|
{ NULL, MR_no_argument, NULL, 0 }
|
|
};
|
|
|
|
static MR_bool
|
|
MR_trace_options_movement_cmd(MR_TraceCmdInfo *cmd,
|
|
char ***words, int *word_count)
|
|
{
|
|
int c;
|
|
|
|
#ifdef MR_TRACE_CHECK_INTEGRITY
|
|
#define MR_TRACE_MOVEMENT_OPTS "NSains"
|
|
#else
|
|
#define MR_TRACE_MOVEMENT_OPTS "NSans"
|
|
#endif
|
|
|
|
MR_optind = 0;
|
|
while ((c = MR_getopt_long(*word_count, *words, MR_TRACE_MOVEMENT_OPTS,
|
|
MR_trace_movement_cmd_opts, NULL)) != EOF)
|
|
{
|
|
switch (c) {
|
|
|
|
case 'N':
|
|
cmd->MR_trace_strict = MR_FALSE;
|
|
break;
|
|
|
|
case 'S':
|
|
cmd->MR_trace_strict = MR_TRUE;
|
|
break;
|
|
|
|
case 'a':
|
|
cmd->MR_trace_print_level_specified = MR_TRUE;
|
|
cmd->MR_trace_print_level = MR_PRINT_LEVEL_ALL;
|
|
break;
|
|
|
|
case 'n':
|
|
cmd->MR_trace_print_level_specified = MR_TRUE;
|
|
cmd->MR_trace_print_level = MR_PRINT_LEVEL_NONE;
|
|
break;
|
|
|
|
case 's':
|
|
cmd->MR_trace_print_level_specified = MR_TRUE;
|
|
cmd->MR_trace_print_level = MR_PRINT_LEVEL_SOME;
|
|
break;
|
|
|
|
#ifdef MR_TRACE_CHECK_INTEGRITY
|
|
case 'i':
|
|
cmd->MR_trace_check_integrity = MR_TRUE;
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
MR_trace_usage_cur_cmd();
|
|
return MR_FALSE;
|
|
}
|
|
}
|
|
|
|
*words = *words + MR_optind - 1;
|
|
*word_count = *word_count - MR_optind + 1;
|
|
return MR_TRUE;
|
|
}
|