[m-rev.] for review: improve usage and version messages in the slice directory
Julien Fischer
jfischer at opturion.com
Sun Oct 1 12:55:39 AEDT 2023
Improve usage and version messages in the slice directory.
Improve the usage and version messages for the programs in the
slice directory by:
- adding --help and --version options for programs that did
not already have them (Mantis issue #208);
- making version and usage message consistent in form with other
programs in the system;
- on a usage error, writing the short usage message to the standard
error stream and setting a non-zero exit status.
This also prepares the way for creating manual pages for the programs in the
slice directory.
slice/mcov.m:
slice/mslice.m:
slice/mdice.m:
slice/mtc_diff.m:
slice/mtc_union.m:
As above.
Julien.
diff --git a/slice/mcov.m b/slice/mcov.m
index aab3ebd..a74db7e 100644
--- a/slice/mcov.m
+++ b/slice/mcov.m
@@ -140,7 +140,8 @@ do_coverage_testing(OptionTable, Args, !IO) :-
)
;
Args = [],
- short_usage(StdOutStream, !IO)
+ short_usage(StdErrStream, !IO),
+ io.set_exit_status(1, !IO)
).
:- func kind_warning = string.
@@ -439,7 +440,7 @@ write_path_port_for_user(OutStream, port_and_path(Port, Path), !IO) :-
display_version(OutStream, !IO) :-
Version = library.mercury_version,
io.format(OutStream,
- "Mercury Coverage Testing Tool, version %s",
+ "Mercury coverage testing tool, version %s",
[s(Version)], !IO),
Package = library.package_version,
( if Package = "" then
@@ -462,13 +463,18 @@ short_usage(OutStream, !IO) :-
long_usage(OutStream, !IO) :-
io.write_string(OutStream,
- "Name: mcov - Mercury Coverage Testing Tool\n", !IO),
+ "Name: mcov - Mercury coverage testing tool\n", !IO),
write_copyright_notice(OutStream, !IO),
io.write_string(OutStream, "Usage: mcov [<options>] <arguments>\n", !IO),
- io.write_string(OutStream, "Arguments:\n", !IO),
- io.write_string(OutStream,
- "\tArguments are assumed to Mercury trace count files.\n", !IO),
- io.write_string(OutStream, "Options:\n", !IO),
+ io.write_string(OutStream, "\nDescription:\n", !IO),
+ io.write_prefixed_lines(OutStream, "\t", [
+ "`mcov' outputs a test coverage report."
+ ], !IO),
+ io.write_string(OutStream, "\nArguments:\n", !IO),
+ io.write_prefixed_lines(OutStream, "\t", [
+ "Arguments are assumed to Mercury trace count files."
+ ], !IO),
+ io.write_string(OutStream, "\nOptions:\n", !IO),
io.write_prefixed_lines(OutStream, "\t", [
"-?, -h, --help",
"\tPrint help about using mcov (on the standard output) and exit",
@@ -476,7 +482,7 @@ long_usage(OutStream, !IO) :-
"--version",
"\tPrint version information.",
"-v, --verbose",
- "\tPrint the name of each trace count file as it is added to the union",
+ "\tPrint the name of each trace count file as it is added to the union.",
"-d, --detailed",
"\tPrint a report for each label that has not been executed, even",
"\tif some other code has been executed in the same procedure.",
diff --git a/slice/mdice.m b/slice/mdice.m
index f664ca8..484d6c3 100644
--- a/slice/mdice.m
+++ b/slice/mdice.m
@@ -2,6 +2,7 @@
% vim: ft=mercury ts=4 sw=4 expandtab
%---------------------------------------------------------------------------%
% Copyright (C) 2005-2006, 2012 The University of Melbourne.
+% Copyright (C) 2015-2016, 2019-2020, 2022-2023 The Mercury team.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%---------------------------------------------------------------------------%
@@ -29,7 +30,9 @@
:- import_module mdbcomp.slice_and_dice.
:- import_module mdbcomp.shared_utilities.
+:- import_module bool.
:- import_module getopt.
+:- import_module library.
:- import_module maybe.
:- import_module list.
:- import_module string.
@@ -44,67 +47,146 @@ main(!IO) :-
getopt.process_options(OptionOps, Args0, Args, GetoptResult),
(
GetoptResult = ok(OptionTable),
- (
- Args = [],
- usage(StdOutStream, !IO)
- ;
- Args = [_],
- usage(StdOutStream, !IO)
- ;
- Args = [PassFileName, FailFileName],
- lookup_string_option(OptionTable, sort, SortStr),
- lookup_string_option(OptionTable, modulename, Module),
- lookup_int_option(OptionTable, max_row, MaxRow),
- lookup_int_option(OptionTable, max_pred_column, MaxPredColumn),
- lookup_int_option(OptionTable, max_path_column, MaxPathColumn),
- lookup_int_option(OptionTable, max_file_column, MaxFileColumn),
- ( if MaxPredColumn = 0 then
- MaybeMaxPredColumn = no
- else
- MaybeMaxPredColumn = yes(MaxPredColumn)
- ),
- ( if MaxPathColumn = 0 then
- MaybeMaxPathColumn = no
- else
- MaybeMaxPathColumn = yes(MaxPathColumn)
- ),
- ( if MaxFileColumn = 0 then
- MaybeMaxFileColumn = no
- else
- MaybeMaxFileColumn = yes(MaxFileColumn)
- ),
- read_dice_to_string(PassFileName, FailFileName, SortStr, MaxRow,
- MaybeMaxPredColumn, MaybeMaxPathColumn, MaybeMaxFileColumn,
- Module, DiceStr, Problem, !IO),
- ( if Problem = "" then
- io.write_string(StdOutStream, DiceStr, !IO)
- else
- io.write_string(StdOutStream, Problem, !IO),
- io.nl(StdOutStream, !IO),
- io.set_exit_status(1, !IO)
- )
- ;
- Args = [_, _, _ | _],
- usage(StdOutStream, !IO)
+ ( if lookup_bool_option(OptionTable, help, yes) then
+ long_usage(StdOutStream, !IO)
+ else if lookup_bool_option(OptionTable, version, yes) then
+ display_version(StdOutStream, !IO)
+ else
+ main_2(StdOutStream, OptionTable, Args, !IO)
)
;
GetoptResult = error(GetoptError),
GetoptErrorMsg = option_error_to_string(GetoptError),
- io.format(StdOutStream, "%s\n", [s(GetoptErrorMsg)], !IO)
+ io.stderr_stream(StdErrStream, !IO),
+ io.format(StdErrStream, "%s\n", [s(GetoptErrorMsg)], !IO),
+ io.set_exit_status(1, !IO)
).
-:- pred usage(io.text_output_stream::in, io::di, io::uo) is det.
+:- pred main_2(io.text_output_stream::in, option_table::in, list(string)::in,
+ io::di, io::uo) is det.
-usage(OutStream, !IO) :-
+main_2(StdOutStream, OptionTable, Args, !IO) :-
+ (
+ ( Args = []
+ ; Args = [_]
+ ; Args = [_, _, _ | _]
+ ),
+ io.stderr_stream(StdErrStream, !IO),
+ short_usage(StdErrStream, !IO),
+ io.set_exit_status(1, !IO)
+ ;
+ Args = [PassFileName, FailFileName],
+ lookup_string_option(OptionTable, sort, SortStr),
+ lookup_string_option(OptionTable, modulename, Module),
+ lookup_int_option(OptionTable, max_row, MaxRow),
+ lookup_int_option(OptionTable, max_pred_column, MaxPredColumn),
+ lookup_int_option(OptionTable, max_path_column, MaxPathColumn),
+ lookup_int_option(OptionTable, max_file_column, MaxFileColumn),
+ ( if MaxPredColumn = 0 then
+ MaybeMaxPredColumn = no
+ else
+ MaybeMaxPredColumn = yes(MaxPredColumn)
+ ),
+ ( if MaxPathColumn = 0 then
+ MaybeMaxPathColumn = no
+ else
+ MaybeMaxPathColumn = yes(MaxPathColumn)
+ ),
+ ( if MaxFileColumn = 0 then
+ MaybeMaxFileColumn = no
+ else
+ MaybeMaxFileColumn = yes(MaxFileColumn)
+ ),
+ read_dice_to_string(PassFileName, FailFileName, SortStr, MaxRow,
+ MaybeMaxPredColumn, MaybeMaxPathColumn, MaybeMaxFileColumn,
+ Module, DiceStr, Problem, !IO),
+ ( if Problem = "" then
+ io.write_string(StdOutStream, DiceStr, !IO)
+ else
+ io.write_string(StdOutStream, Problem, !IO),
+ io.nl(StdOutStream, !IO),
+ io.set_exit_status(1, !IO)
+ )
+ ).
+
+%---------------------------------------------------------------------------%
+
+:- pred display_version(io.text_output_stream::in, io::di, io::uo) is det.
+
+display_version(OutStream, !IO) :-
+ Version = library.mercury_version,
+ io.format(OutStream, "Mercury dice tool, version %s",
+ [s(Version)], !IO),
+ Package = library.package_version,
+ ( if Package = "" then
+ io.nl(OutStream, !IO)
+ else
+ io.format(OutStream, " (%s)\n", [s(Package)], !IO)
+ ),
+ write_copyright_notice(OutStream, !IO).
+
+:- pred short_usage(io.text_output_stream::in, io::di, io::uo) is det.
+
+short_usage(OutStream, !IO) :-
+ io.write_strings(OutStream, [
+ "Usage: mdice [<options>] <passfile> <failfile>\n",
+ "Use `mdice --help' for more information.\n"
+ ], !IO).
+
+:- pred long_usage(io.text_output_stream::in, io::di, io::uo) is det.
+
+long_usage(OutStream, !IO) :-
+ io.write_string(OutStream, "Name: mdice - Mercury dice tool\n", !IO),
+ write_copyright_notice(OutStream, !IO),
+ io.write_string(OutStream, "\nUsage: mdice [<options>] <passfile> <failfile>\n", !IO),
+ io.write_string(OutStream, "\nDescription:\n", !IO),
+ io.write_prefixed_lines(OutStream, "\t", [
+ "`mdice' creates a comparison between passing and failing runs of a",
+ "program."
+ ], !IO),
+ io.write_string(OutStream, "\nArguments:\n", !IO),
io.write_string(OutStream,
- "Usage: mdice [-s sortspec] [-m module] [-l N] [-n N] [-p N] [-f N] "
- ++ "passfile failfile\n",
- !IO).
+ "\tArguments are assumed to Mercury trace count files.\n", !IO),
+ io.write_string(OutStream, "\nOptions:\n", !IO),
+ io.write_prefixed_lines(OutStream, "\t", [
+ "-?, -h, --help",
+ "\tPrint help about using mdice (on the standard output) and exit",
+ "\twithout doing any further processing.",
+ "--version",
+ "\tPrint version information.",
+ "-s <sortspec>, --sort <sortspec>",
+ "\tSpecify how the output should be sorted.",
+ "\t(See the Mercury User's Guide for details.)",
+ "-l <N>, --limit <N>",
+ "\tLimit the output to at most N lines.",
+ "-m <module>, --module <module>",
+ "\tRestrict the output to the given module and its submodules (if any).",
+ "-n <N>, --max-column-name <N>",
+ "\tThe maximum width of the column containing predicate names.",
+ "\tA value of zero means there is no maximum width.",
+ "-p <N>, --max-path-column <N>",
+ "\tThe maximum width of the column containing ports and goal paths.",
+ "\tA value of zero means there is no maximum width.",
+ "-f <N>, --max-file-column <N>",
+ "\tThe maximum width of the column containing file names and line numbers.",
+ "\tA value of zero means there is no maximum width."
+ ], !IO).
+
+:- pred write_copyright_notice(io.text_output_stream::in, io::di, io::uo)
+ is det.
+
+write_copyright_notice(OutStream, !IO) :-
+ io.write_strings(OutStream, [
+ "Copyright (C) 2005-2006, 2012 The University of Melbourne\n",
+ "Copyright (C) 2015-2016, 2019-2020, 2022-2023 The Mercury team\n"
+ ], !IO).
%---------------------------------------------------------------------------%
:- type option
- ---> sort
+ ---> help
+ ; version
+ ; sort
; max_row
; max_pred_column
; max_path_column
@@ -115,24 +197,30 @@ usage(OutStream, !IO) :-
:- pred short_option(character::in, option::out) is semidet.
-short_option('s', sort).
-short_option('l', max_row).
-short_option('n', max_pred_column).
-short_option('p', max_path_column).
-short_option('f', max_file_column).
-short_option('m', modulename).
+short_option('?', help).
+short_option('h', help).
+short_option('s', sort).
+short_option('l', max_row).
+short_option('n', max_pred_column).
+short_option('p', max_path_column).
+short_option('f', max_file_column).
+short_option('m', modulename).
:- pred long_option(string::in, option::out) is semidet.
-long_option("sort", sort).
-long_option("limit", max_row).
-long_option("max-name-column", max_pred_column).
-long_option("max-path-column", max_path_column).
-long_option("max-file-column", max_file_column).
-long_option("module", modulename).
+long_option("help", help).
+long_option("version", version).
+long_option("sort", sort).
+long_option("limit", max_row).
+long_option("max-name-column", max_pred_column).
+long_option("max-path-column", max_path_column).
+long_option("max-file-column", max_file_column).
+long_option("module", modulename).
:- pred option_default(option::out, option_data::out) is multi.
+option_default(help, bool(no)).
+option_default(version, bool(no)).
option_default(sort, string("S")).
option_default(max_row, int(100)).
option_default(max_pred_column, int(35)).
diff --git a/slice/mslice.m b/slice/mslice.m
index 72cf225..1ebe2da 100644
--- a/slice/mslice.m
+++ b/slice/mslice.m
@@ -2,6 +2,7 @@
% vim: ft=mercury ts=4 sw=4 expandtab
%---------------------------------------------------------------------------%
% Copyright (C) 2005-2006, 2012 The University of Melbourne.
+% Copyright (C) 2015-2016, 2019-2020, 2022-2023 The Mercury team.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%---------------------------------------------------------------------------%
@@ -11,7 +12,6 @@
%---------------------------------------------------------------------------%
:- module mslice.
-
:- interface.
:- import_module io.
@@ -27,11 +27,15 @@
:- import_module mdbcomp.slice_and_dice.
:- import_module mdbcomp.shared_utilities.
+:- import_module bool.
:- import_module getopt.
+:- import_module library.
:- import_module list.
:- import_module maybe.
:- import_module string.
+%---------------------------------------------------------------------------%
+
main(!IO) :-
io.stdout_stream(StdOutStream, !IO),
unlimit_stack(!IO),
@@ -40,64 +44,144 @@ main(!IO) :-
getopt.process_options(OptionOps, Args0, Args, GetoptResult),
(
GetoptResult = ok(OptionTable),
- (
- Args = [],
- usage(StdOutStream, !IO)
- ;
- Args = [FileName],
- lookup_string_option(OptionTable, sort, SortStr),
- lookup_int_option(OptionTable, max_row, MaxRow),
- lookup_int_option(OptionTable, max_pred_column, MaxPredColumn),
- lookup_int_option(OptionTable, max_path_column, MaxPathColumn),
- lookup_int_option(OptionTable, max_file_column, MaxFileColumn),
- lookup_string_option(OptionTable, modulename, Module),
- ( if MaxPredColumn = 0 then
- MaybeMaxPredColumn = no
- else
- MaybeMaxPredColumn = yes(MaxPredColumn)
- ),
- ( if MaxPathColumn = 0 then
- MaybeMaxPathColumn = no
- else
- MaybeMaxPathColumn = yes(MaxPathColumn)
- ),
- ( if MaxFileColumn = 0 then
- MaybeMaxFileColumn = no
- else
- MaybeMaxFileColumn = yes(MaxFileColumn)
- ),
- read_slice_to_string(FileName, SortStr, MaxRow,
- MaybeMaxPredColumn, MaybeMaxPathColumn, MaybeMaxFileColumn,
- Module, SliceStr, Problem, !IO),
- ( if Problem = "" then
- io.write_string(StdOutStream, SliceStr, !IO)
- else
- io.write_string(StdOutStream, Problem, !IO),
- io.nl(StdOutStream, !IO),
- io.set_exit_status(1, !IO)
- )
- ;
- Args = [_, _ | _],
- usage(StdOutStream, !IO)
+ ( if lookup_bool_option(OptionTable, help, yes) then
+ long_usage(StdOutStream, !IO)
+ else if lookup_bool_option(OptionTable, version, yes) then
+ display_version(StdOutStream, !IO)
+ else
+ main_2(StdOutStream, OptionTable, Args, !IO)
)
;
GetoptResult = error(GetoptError),
GetoptErrorMsg = option_error_to_string(GetoptError),
- io.format(StdOutStream, "%s\n", [s(GetoptErrorMsg)], !IO)
+ io.format(StdOutStream, "%s\n", [s(GetoptErrorMsg)], !IO),
+ io.set_exit_status(1, !IO)
+ ).
+
+:- pred main_2(io.text_output_stream::in, option_table::in, list(string)::in,
+ io::di, io::uo) is det.
+
+main_2(StdOutStream, OptionTable, Args, !IO) :-
+ (
+ ( Args = []
+ ; Args = [_, _ | _]
+ ),
+ io.stderr_stream(StdErrStream, !IO),
+ short_usage(StdErrStream, !IO),
+ io.set_exit_status(1, !IO)
+ ;
+ Args = [FileName],
+ lookup_string_option(OptionTable, sort, SortStr),
+ lookup_int_option(OptionTable, max_row, MaxRow),
+ lookup_int_option(OptionTable, max_pred_column, MaxPredColumn),
+ lookup_int_option(OptionTable, max_path_column, MaxPathColumn),
+ lookup_int_option(OptionTable, max_file_column, MaxFileColumn),
+ lookup_string_option(OptionTable, modulename, Module),
+ ( if MaxPredColumn = 0 then
+ MaybeMaxPredColumn = no
+ else
+ MaybeMaxPredColumn = yes(MaxPredColumn)
+ ),
+ ( if MaxPathColumn = 0 then
+ MaybeMaxPathColumn = no
+ else
+ MaybeMaxPathColumn = yes(MaxPathColumn)
+ ),
+ ( if MaxFileColumn = 0 then
+ MaybeMaxFileColumn = no
+ else
+ MaybeMaxFileColumn = yes(MaxFileColumn)
+ ),
+ read_slice_to_string(FileName, SortStr, MaxRow,
+ MaybeMaxPredColumn, MaybeMaxPathColumn, MaybeMaxFileColumn,
+ Module, SliceStr, Problem, !IO),
+ ( if Problem = "" then
+ io.write_string(StdOutStream, SliceStr, !IO)
+ else
+ io.write_string(StdOutStream, Problem, !IO),
+ io.nl(StdOutStream, !IO),
+ io.set_exit_status(1, !IO)
+ )
).
-:- pred usage(io.text_output_stream::in, io::di, io::uo) is det.
+%---------------------------------------------------------------------------%
-usage(OutStream, !IO) :-
- io.write_string(OutStream,
- "Usage: mslice [-s sortspec] [-m module] [-l N] [-n N] [-p N] [-f N] "
- ++ "filename\n",
- !IO).
+:- pred display_version(io.text_output_stream::in, io::di, io::uo) is det.
+
+display_version(OutStream, !IO) :-
+ Version = library.mercury_version,
+ io.format(OutStream, "Mercury slice tool, version %s",
+ [s(Version)], !IO),
+ Package = library.package_version,
+ ( if Package = "" then
+ io.nl(OutStream, !IO)
+ else
+ io.format(OutStream, " (%s)\n", [s(Package)], !IO)
+ ),
+ write_copyright_notice(OutStream, !IO).
+
+:- pred short_usage(io.text_output_stream::in, io::di, io::uo) is det.
+
+short_usage(OutStream, !IO) :-
+ io.write_strings(OutStream, [
+ "Usage: mslice [<options>] <file>\n",
+ "Use `mslice --help' for more information.\n"
+ ], !IO).
+
+:- pred long_usage(io.text_output_stream::in, io::di, io::uo) is det.
+
+long_usage(OutStream, !IO) :-
+ io.write_string(OutStream, "Name: mslice - Mercury slice tool\n", !IO),
+ write_copyright_notice(OutStream, !IO),
+ io.write_string(OutStream, "\nUsage: mslice [<options>] <file>\n", !IO),
+ io.write_string(OutStream, "\nDescription:\n", !IO),
+ io.write_prefixed_lines(OutStream, "\t", [
+ "`mslice' is a tool that outputs views of program slices."
+ ], !IO),
+ io.write_string(OutStream, "\nArguments:\n", !IO),
+ io.write_prefixed_lines(OutStream, "\t", [
+ "The argument is assumed to be a Mercury trace count file."
+ ], !IO),
+ io.write_string(OutStream, "\nOptions:\n", !IO),
+ io.write_prefixed_lines(OutStream, "\t", [
+ "-?, -h, --help",
+ "\tPrint help about using mslice (on the standard output) and exit",
+ "\twithout doing any further processing.",
+ "--version",
+ "\tPrint version information.",
+ "-s <sortspec>, --sort <sortspec>",
+ "\tSpecify how the output should be sorted.",
+ "\t(See the Mercury User's Guide for details.)",
+ "-l <N>, --limit <N>",
+ "\tLimit the output to at most N lines.",
+ "-m <module>, --module <module>",
+ "\tRestrict the output to the given module and its submodules (if any).",
+ "-n <N>, --max-name-column <N>",
+ "\tThe maximum width of the column containing predicate names.",
+ "\tA value of zero means there is no maximum width.",
+ "-p <N>, --max-path-column <N>",
+ "\tThe maximum width of the column containing ports and goal paths.",
+ "\tA value of zero means there is no maximum width.",
+ "-f <N>, --max-file-column <N>",
+ "\tThe maximum width of the column containing file names and line numbers.",
+ "\tA value of zero means there is no maximum width."
+ ], !IO).
+
+:- pred write_copyright_notice(io.text_output_stream::in, io::di, io::uo)
+ is det.
+
+write_copyright_notice(OutStream, !IO) :-
+ io.write_strings(OutStream, [
+ "Copyright (C) 2005-2006, 2012 The University of Melbourne\n",
+ "Copyright (C) 2015-2016, 2019-2020, 2022-2023 The Mercury team\n"
+ ], !IO).
%---------------------------------------------------------------------------%
:- type option
- ---> sort
+ ---> help
+ ; version
+ ; sort
; max_row
; max_pred_column
; max_path_column
@@ -108,24 +192,30 @@ usage(OutStream, !IO) :-
:- pred short_option(character::in, option::out) is semidet.
-short_option('s', sort).
-short_option('l', max_row).
-short_option('n', max_pred_column).
-short_option('p', max_path_column).
-short_option('f', max_file_column).
-short_option('m', modulename).
+short_option('?', help).
+short_option('h', help).
+short_option('s', sort).
+short_option('l', max_row).
+short_option('n', max_pred_column).
+short_option('p', max_path_column).
+short_option('f', max_file_column).
+short_option('m', modulename).
:- pred long_option(string::in, option::out) is semidet.
-long_option("sort", sort).
-long_option("limit", max_row).
-long_option("max-name-column", max_pred_column).
-long_option("max-path-column", max_path_column).
-long_option("max-file-column", max_file_column).
-long_option("module", modulename).
+long_option("help", help).
+long_option("version", version).
+long_option("sort", sort).
+long_option("limit", max_row).
+long_option("max-name-column", max_pred_column).
+long_option("max-path-column", max_path_column).
+long_option("max-file-column", max_file_column).
+long_option("module", modulename).
:- pred option_default(option::out, option_data::out) is multi.
+option_default(help, bool(no)).
+option_default(version, bool(no)).
option_default(sort, string("C")).
option_default(max_row, int(100)).
option_default(max_pred_column, int(35)).
diff --git a/slice/mtc_diff.m b/slice/mtc_diff.m
index 71d2d27..9c55fb3 100644
--- a/slice/mtc_diff.m
+++ b/slice/mtc_diff.m
@@ -2,6 +2,7 @@
% vim: ft=mercury ts=4 sw=4 expandtab
%---------------------------------------------------------------------------%
% Copyright (C) 2006, 2012 The University of Melbourne.
+% Copyright (C) 2015-2017, 2019-2023 The Mercury team.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%---------------------------------------------------------------------------%
@@ -29,7 +30,9 @@
:- import_module mdbcomp.shared_utilities.
:- import_module mdbcomp.trace_counts.
+:- import_module bool.
:- import_module getopt.
+:- import_module library.
:- import_module list.
:- import_module map.
:- import_module string.
@@ -45,81 +48,161 @@ main(!IO) :-
getopt.process_options(OptionOps, Args0, Args, GetoptResult),
(
GetoptResult = ok(OptionTable),
- lookup_string_option(OptionTable, output_filename, OutputFile),
+ ( if lookup_bool_option(OptionTable, help, yes) then
+ long_usage(StdOutStream, !IO)
+ else if lookup_bool_option(OptionTable, version, yes) then
+ display_version(StdOutStream, !IO)
+ else
+ main_2(StdErrStream, OptionTable, Args, !IO)
+ )
+ ;
+ GetoptResult = error(GetoptError),
+ GetoptErrorMsg = option_error_to_string(GetoptError),
+ io.format(StdErrStream, "%s\n", [s(GetoptErrorMsg)], !IO),
+ io.set_exit_status(1, !IO)
+ ).
+
+:- pred main_2(io.text_output_stream::in, option_table::in,
+ list(string)::in, io::di, io::uo) is det.
+
+main_2(StdErrStream, OptionTable, Args, !IO) :-
+ lookup_string_option(OptionTable, output_filename, OutputFile),
+ ( if
+ Args = [Arg1, Arg2],
+ OutputFile \= ""
+ then
+ read_trace_counts_source(Arg1, MaybeTraceCounts1, !IO),
+ (
+ MaybeTraceCounts1 = list_ok(_, _)
+ ;
+ MaybeTraceCounts1 = list_error_message(Msg1),
+ io.write_string(StdErrStream, Msg1, !IO),
+ io.nl(StdErrStream, !IO)
+ ),
+ read_trace_counts_source(Arg2, MaybeTraceCounts2, !IO),
+ (
+ MaybeTraceCounts2 = list_ok(_, _)
+ ;
+ MaybeTraceCounts2 = list_error_message(Msg2),
+ io.write_string(StdErrStream, Msg2, !IO),
+ io.nl(StdErrStream, !IO)
+ ),
( if
- Args = [Arg1, Arg2],
- OutputFile \= ""
+ MaybeTraceCounts1 = list_ok(Type1, TraceCounts1),
+ MaybeTraceCounts2 = list_ok(Type2, TraceCounts2)
then
- read_trace_counts_source(Arg1, MaybeTraceCounts1, !IO),
+ diff_trace_counts(TraceCounts1, TraceCounts2, TraceCounts),
+ write_trace_counts_to_file(diff_file(Type1, Type2),
+ TraceCounts, OutputFile, WriteResult, !IO),
(
- MaybeTraceCounts1 = list_ok(_, _)
+ WriteResult = ok
;
- MaybeTraceCounts1 = list_error_message(Msg1),
- io.write_string(StdErrStream, Msg1, !IO),
- io.nl(StdErrStream, !IO)
- ),
- read_trace_counts_source(Arg2, MaybeTraceCounts2, !IO),
- (
- MaybeTraceCounts2 = list_ok(_, _)
- ;
- MaybeTraceCounts2 = list_error_message(Msg2),
- io.write_string(StdErrStream, Msg2, !IO),
- io.nl(StdErrStream, !IO)
- ),
- ( if
- MaybeTraceCounts1 = list_ok(Type1, TraceCounts1),
- MaybeTraceCounts2 = list_ok(Type2, TraceCounts2)
- then
- diff_trace_counts(TraceCounts1, TraceCounts2, TraceCounts),
- write_trace_counts_to_file(diff_file(Type1, Type2),
- TraceCounts, OutputFile, WriteResult, !IO),
- (
- WriteResult = ok
- ;
- WriteResult = error(WriteErrorMsg),
- io.write_string(StdErrStream, "Error writing to " ++
- "file `" ++ OutputFile ++ "'" ++ ": " ++
- string(WriteErrorMsg), !IO),
- io.nl(StdErrStream, !IO)
- )
- else
- % The error message has already been printed above.
- true
+ WriteResult = error(WriteErrorMsg),
+ io.format(StdErrStream,
+ "Error writing to file`%s': %s\n",
+ [s(OutputFile), s(io.error_message(WriteErrorMsg))],
+ !IO),
+ io.set_exit_status(1, !IO)
)
else
- usage(StdOutStream, !IO)
+ % The error message has already been printed above.
+ true
)
- ;
- GetoptResult = error(GetoptError),
- GetoptErrorMsg = option_error_to_string(GetoptError),
- io.format(StdOutStream, "%s\n", [s(GetoptErrorMsg)], !IO)
+ else
+ short_usage(StdErrStream, !IO),
+ io.set_exit_status(1, !IO)
).
-:- pred usage(io.text_output_stream::in, io::di, io::uo) is det.
+%---------------------------------------------------------------------------%
-usage(OutStream, !IO) :-
- io.write_string(OutStream,
- "Usage: mtc_diff -o outputfile tracecountfile1 tracecountfile2\n",
- !IO).
+:- pred display_version(io.text_output_stream::in, io::di, io::uo) is det.
+
+display_version(OutStream, !IO) :-
+ Version = library.mercury_version,
+ io.format(OutStream, "Mercury trace count diff, version %s",
+ [s(Version)], !IO),
+ Package = library.package_version,
+ ( if Package = "" then
+ io.nl(OutStream, !IO)
+ else
+ io.format(OutStream, " (%s)\n", [s(Package)], !IO)
+ ),
+ write_copyright_notice(OutStream, !IO).
+
+:- pred short_usage(io.text_output_stream::in, io::di, io::uo) is det.
+
+short_usage(OutStream, !IO) :-
+ io.progname_base("mtc_diff", ProgName, !IO),
+ io.format(OutStream,
+ "Usage: %s [<options>] <tracecountfile1> <tracecountfile2>]\n",
+ [s(ProgName)], !IO),
+ io.format(OutStream, "Use `%s --help' for more information.\n",
+ [s(ProgName)], !IO).
+
+:- pred long_usage(io.text_output_stream::in, io::di, io::uo) is det.
+
+long_usage(OutStream, !IO) :-
+ io.progname_base("mtc_diff", ProgName, !IO),
+ io.write_string(OutStream, "Name: mtc_diff - Mercury trace count diff\n", !IO),
+ write_copyright_notice(OutStream, !IO),
+ io.write_strings(OutStream, [
+ "Usage: ", ProgName, " [<options>] <tracecountfile1> <tracecountfile2>\n",
+ "\n",
+ "Description:\n"
+ ], !IO),
+ io.write_prefixed_lines(OutStream, "\t", [
+ "`mtc_diff' combines multiple trace count files into a single trace",
+ "count file."
+ ], !IO),
+ io.write_string(OutStream, "\nArguments:\n", !IO),
+ io.write_prefixed_lines(OutStream, "\t", [
+ "<files> is the trace count files that are to be combined."
+ ], !IO),
+ io.write_string(OutStream, "\nOptions:\n", !IO),
+ io.write_prefixed_lines(OutStream, "\t", [
+ "-?, -h, --help",
+ "\tPrint this usage message.",
+ "--version",
+ "\tPrint version information.",
+ "-o <file>, --out <file>",
+ "\tWrite the diff of the input trace counts to the specified file."
+ ], !IO).
+
+:- pred write_copyright_notice(io.text_output_stream::in, io::di, io::uo)
+ is det.
+
+write_copyright_notice(OutStream, !IO) :-
+ io.write_strings(OutStream, [
+ "Copyright (C) 2006-2012 The University of Melbourne\n",
+ "Copyright (C) 2013-2023 The Mercury team\n"
+ ], !IO).
%---------------------------------------------------------------------------%
:- type option
- ---> output_filename.
+ ---> help
+ ; version
+ ; output_filename.
:- type option_table == option_table(option).
:- pred short_option(character::in, option::out) is semidet.
-short_option('o', output_filename).
+short_option('?', help).
+short_option('h', help).
+short_option('o', output_filename).
:- pred long_option(string::in, option::out) is semidet.
-long_option("out", output_filename).
+long_option("help", help).
+long_option("version", version).
+long_option("out", output_filename).
:- pred option_default(option::out, option_data::out) is multi.
:- pragma no_determinism_warning(pred(option_default/2)).
+option_default(help, bool(no)).
+option_default(version, bool(no)).
option_default(output_filename, string("")).
%---------------------------------------------------------------------------%
diff --git a/slice/mtc_union.m b/slice/mtc_union.m
index 4b3c184..85bb6f1 100644
--- a/slice/mtc_union.m
+++ b/slice/mtc_union.m
@@ -2,6 +2,7 @@
% vim: ft=mercury ts=4 sw=4 expandtab
%---------------------------------------------------------------------------%
% Copyright (C) 2005-2006, 2012 The University of Melbourne.
+% Copyright (C) 2015-2016, 2019-2023 The Mercury team.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%---------------------------------------------------------------------------%
@@ -31,6 +32,7 @@
:- import_module bool.
:- import_module getopt.
+:- import_module library.
:- import_module list.
:- import_module map.
:- import_module maybe.
@@ -48,79 +50,157 @@ main(!IO) :-
getopt.process_options(OptionOps, Args0, Args, GetoptResult),
(
GetoptResult = ok(OptionTable),
- lookup_string_option(OptionTable, output_filename, OutputFile),
- ( if
- Args = [_ | _],
- OutputFile \= ""
- then
- lookup_bool_option(OptionTable, verbose, Verbose),
- (
- Verbose = yes,
- ShowProgress = yes(StdOutStream)
- ;
- Verbose = no,
- ShowProgress = no
- ),
- read_and_union_trace_counts(ShowProgress, Args, NumTests, Kinds,
- TraceCounts, MaybeReadError, !IO),
- (
- MaybeReadError = yes(ReadErrorMsg),
- io.write_string(StdErrStream, ReadErrorMsg, !IO),
- io.nl(StdErrStream, !IO)
- ;
- MaybeReadError = no,
- Type = union_file(NumTests, set.to_sorted_list(Kinds)),
- write_trace_counts_to_file(Type, TraceCounts, OutputFile,
- WriteResult, !IO),
- (
- WriteResult = ok
- ;
- WriteResult = error(WriteErrorMsg),
- io.write_string(StdErrStream,
- "Error writing to file `" ++ OutputFile ++ "'" ++
- ": " ++ string(WriteErrorMsg), !IO),
- io.nl(StdErrStream, !IO)
- )
- )
+ ( if lookup_bool_option(OptionTable, help, yes) then
+ long_usage(StdOutStream, !IO)
+ else if lookup_bool_option(OptionTable, version, yes) then
+ display_version(StdOutStream, !IO)
else
- usage(StdOutStream, !IO)
+ main_2(StdOutStream, StdErrStream, OptionTable, Args, !IO)
)
;
GetoptResult = error(GetoptError),
GetoptErrorMsg = option_error_to_string(GetoptError),
- io.format(StdOutStream, "%s\n", [s(GetoptErrorMsg)], !IO)
+ io.format(StdErrStream, "%s\n", [s(GetoptErrorMsg)], !IO),
+ io.set_exit_status(1, !IO)
).
-:- pred usage(io.text_output_stream::in, io::di, io::uo) is det.
+:- pred main_2(io.text_output_stream::in, io.text_output_stream::in,
+ option_table::in, list(string)::in, io::di, io::uo) is det.
+
+main_2(StdOutStream, StdErrStream, OptionTable, Args, !IO) :-
+ lookup_string_option(OptionTable, output_filename, OutputFile),
+ ( if
+ Args = [_ | _],
+ OutputFile \= ""
+ then
+ lookup_bool_option(OptionTable, verbose, Verbose),
+ (
+ Verbose = yes,
+ ShowProgress = yes(StdOutStream)
+ ;
+ Verbose = no,
+ ShowProgress = no
+ ),
+ read_and_union_trace_counts(ShowProgress, Args, NumTests, Kinds,
+ TraceCounts, MaybeReadError, !IO),
+ (
+ MaybeReadError = yes(ReadErrorMsg),
+ io.write_string(StdErrStream, ReadErrorMsg, !IO),
+ io.nl(StdErrStream, !IO)
+ ;
+ MaybeReadError = no,
+ Type = union_file(NumTests, set.to_sorted_list(Kinds)),
+ write_trace_counts_to_file(Type, TraceCounts, OutputFile,
+ WriteResult, !IO),
+ (
+ WriteResult = ok
+ ;
+ WriteResult = error(WriteErrorMsg),
+ io.format(StdErrStream,
+ "Error writing to file `%s': %s\n",
+ [s(OutputFile), s(io.error_message(WriteErrorMsg))],
+ !IO),
+ io.set_exit_status(1, !IO)
+ )
+ )
+ else
+ short_usage(StdErrStream, !IO),
+ io.set_exit_status(1, !IO)
+ ).
-usage(OutStream, !IO) :-
+%---------------------------------------------------------------------------%
+
+:- pred display_version(io.text_output_stream::in, io::di, io::uo) is det.
+
+display_version(OutStream, !IO) :-
+ Version = library.mercury_version,
+ io.format(OutStream, "Mercury trace count union, version %s",
+ [s(Version)], !IO),
+ Package = library.package_version,
+ ( if Package = "" then
+ io.nl(OutStream, !IO)
+ else
+ io.format(OutStream, " (%s)\n", [s(Package)], !IO)
+ ),
+ write_copyright_notice(OutStream, !IO).
+
+:- pred short_usage(io.text_output_stream::in, io::di, io::uo) is det.
+
+short_usage(OutStream, !IO) :-
+ io.progname_base("mtc_union", ProgName, !IO),
+ io.format(OutStream, "Usage: %s [<options>] [<files>]\n",
+ [s(ProgName)], !IO),
+ io.format(OutStream, "Use `%s --help' for more information.\n",
+ [s(ProgName)], !IO).
+
+:- pred long_usage(io.text_output_stream::in, io::di, io::uo) is det.
+
+long_usage(OutStream, !IO) :-
+ io.progname_base("mtc_union", ProgName, !IO),
+ io.write_string(OutStream, "Name: mtc_union - Mercury trace count union\n", !IO),
+ write_copyright_notice(OutStream, !IO),
+ io.write_strings(OutStream, [
+ "Usage: ", ProgName, " [<options>] [<files>]\n",
+ "\n",
+ "Description:\n"
+ ], !IO),
+ io.write_prefixed_lines(OutStream, "\t", [
+ "`mtc_union' combines multiple trace count files into a single trace",
+ "count file."
+ ], !IO),
+ io.write_string(OutStream, "\nArguments:\n", !IO),
+ io.write_prefixed_lines(OutStream, "\t", [
+ "<files> is the trace count files that are to be combined."
+ ], !IO),
+ io.write_string(OutStream, "\nOptions:\n", !IO),
+ io.write_prefixed_lines(OutStream, "\t", [
+ "-?, -h, --help",
+ "\tPrint this usage message.",
+ "--version",
+ "\tPrint version information.",
+ "-v, --verbose",
+ "\tPrint the name of each trace count file as it is added to the union",
+ "-o <file>, --out <file>",
+ "\tWrite the union of the input trace counts to the specified file."
+ ], !IO).
+
+:- pred write_copyright_notice(io.text_output_stream::in, io::di, io::uo)
+ is det.
+
+write_copyright_notice(OutStream, !IO) :-
io.write_strings(OutStream, [
- "Usage: mtc_union [-v] -o output_file file1 file2 ...\n",
- "The -v or --verbose option causes each trace count file name\n",
- "to be printed as it is added to the union.\n",
- "file1, file2, etc should be trace count files.\n"],
- !IO).
+ "Copyright (C) 2005-2012 The University of Melbourne\n",
+ "Copyright (C) 2013-2023 The Mercury team\n"
+ ], !IO).
%---------------------------------------------------------------------------%
:- type option
- ---> output_filename
+ ---> help
+ ; version
+ ; output_filename
; verbose.
:- type option_table == option_table(option).
:- pred short_option(character::in, option::out) is semidet.
+short_option('?', help).
+short_option('h', help).
short_option('o', output_filename).
short_option('v', verbose).
:- pred long_option(string::in, option::out) is semidet.
+long_option("help", help).
+long_option("version", version).
long_option("out", output_filename).
long_option("verbose", verbose).
:- pred option_default(option::out, option_data::out) is multi.
+option_default(help, bool(no)).
+option_default(version, bool(no)).
option_default(output_filename, string("")).
option_default(verbose, bool(no)).
More information about the reviews
mailing list