diff --git a/NEWS.md b/NEWS.md index 8568d269c..7cc7cb291 100644 --- a/NEWS.md +++ b/NEWS.md @@ -308,13 +308,18 @@ Changes to the Mercury standard library * The following function has been marked obsolete: - - func `float_to_doc/1` (replacement: `pretty_printer.float_to_doc/1`) + - func `float_to_doc/1` (replacement: `pretty_printer.float_to_doc/1`) ### Changes to the `getopt` module -* The following predicate has been added: +* The following predicates have been added: - - pred `record_all_arguments/7` + - pred `recognize_options/7` + - pred `recognize_all_options/7` + +* The following predicate has been marked obsolete: + + - pred `record_arguments/7` (replacement: `getopt.recognize_options/7`) ### Changes to the `hash_table` module diff --git a/compiler/make.track_flags.m b/compiler/make.track_flags.m index 7c380dfe1..3fa7ede85 100644 --- a/compiler/make.track_flags.m +++ b/compiler/make.track_flags.m @@ -195,10 +195,10 @@ option_table_hash(ProgressStream, DefaultOptionTable, MaybeStdLibGrades, % of these options will have their default values, which makes % most of that work effectively wasted. % - % A more elegant approach would be to invoke getopt.record_arguments on - % AllOptionArgs, and hash the resulting list of option_values. This would - % require hashing special options (such as -ON) as well as non-special - % values, but the cost of that would be trivial. + % A more elegant approach would be to invoke getopt.recognize_all_options + % on AllOptionArgs, and hash the resulting list of option_values. + % This would require hashing special options (such as -ON) as well as + % non-special values, but the cost of that would be trivial. % % This approach would have two principal differences from the current one. % @@ -236,7 +236,7 @@ option_table_hash(ProgressStream, DefaultOptionTable, MaybeStdLibGrades, % % XXX A somewhat more backwards-compatible version of the above approach % would be to hash both DefaultOptionTable AND the result invoking - % getopt.record_arguments, after filtering inconsequential options + % getopt.recognize_all_options, after filtering inconsequential options % out of both. This would effectively hash the *input* of the call to % handle_given_options, rather than its output. It would also be % logically cleaner, since in some cases, handle_given_options does diff --git a/compiler/mercury_compile_args.m b/compiler/mercury_compile_args.m index 3a411d72e..d04cb4fce 100644 --- a/compiler/mercury_compile_args.m +++ b/compiler/mercury_compile_args.m @@ -274,16 +274,15 @@ process_options_arg_file(ProgressStream, DefaultOptionTable, ArgFile, get_short_option(ShortOption), get_long_option(LongOption), % Separate the option args from the non-option args. - getopt.record_arguments(ShortOption, LongOption, DefaultOptionTable, - Args1, NonOptionArgs, OptionArgs, MaybeError, _OptionValues), + getopt.recognize_all_options(ShortOption, LongOption, + DefaultOptionTable, Args1, Errors, _OptionValues, + OptionArgs, NonOptionArgs), ( - MaybeError = found_option_error(OptionError), - OptionErrorStr = option_error_to_string(OptionError), - Spec = no_ctxt_spec($pred, severity_error, - phase_options, [words(OptionErrorStr), suffix("."), nl]), - Result = opr_failure([Spec]) + Errors = [_ | _], + OptionSpecs = list.map(option_error_to_error_spec, Errors), + Result = opr_failure(OptionSpecs) ; - MaybeError = no_option_error, + Errors = [], Result = opr_success(EnvOptFileVariables, [], OptionArgs, NonOptionArgs, Specs) ) @@ -295,6 +294,13 @@ process_options_arg_file(ProgressStream, DefaultOptionTable, ArgFile, OptionArgs, NonOptionArgs, Specs) ). +:- func option_error_to_error_spec(option_error(option)) = error_spec. + +option_error_to_error_spec(OptionError) = Spec :- + OptionErrorStr = option_error_to_string(OptionError), + Pieces = [words(OptionErrorStr), suffix("."), nl], + Spec = no_ctxt_spec($pred, severity_error, phase_options, Pieces). + %---------------------% :- pred process_options_std(io.text_output_stream::in, diff --git a/library/getopt.m b/library/getopt.m index 2394e73c6..ccb1d74d1 100644 --- a/library/getopt.m +++ b/library/getopt.m @@ -613,8 +613,10 @@ ---> no_option_error ; found_option_error(option_error(OptionType)). - % record_arguments(ShortOptionPred, LongOptionPred, OptionTable, - % Args, NonOptionArgs, OptionArgs, MaybeError, OptionValues): + % recognize_options(ShortOptionPred, LongOptionPred, OptionTable, + % Args, MaybeError, OptionValues, OptionArgs, NonOptionArgs): + % recognize_all_options(ShortOptionPred, LongOptionPred, OptionTable, + % Args, Errors, OptionValues, OptionArgs, NonOptionArgs): % % Given Args, which is a list of command line arguments, % @@ -627,48 +629,61 @@ % - use OptionTable to figure out what kind of value, if any, % each of those user-defined options has as its argument, % - % - find those arguments and convert them to the expected type, and + % - find those arguments and convert them to the expected type, + % and return them OptionValues. % - % - provided no errors occurred in any of the above steps, - % return a list of those options and their values in OptionValues, - % and set MaybeError to no_option_error. + % The two predicates differ in what they do when they find an error. % - % - If some errors *did* occur, then set MaybeError to found_option_error - % wrapped around a description of one of them. This will probably be - % the first, but we do not guarantee that. Also, in this error case, - % OptionValues will probably contain the values of the options processed - % before the error, but we do not guarantee that either. + % - When it finds an error, recognize_options stops processing Args, + % and returns a description of the error in MaybeError. Any arguments + % after the error will not be includes in any of OptionValues, + % OptionsArgs, or NonOptionArgs. + % + % - When it finds an error, recognize_all_options keeps processing Args, + % looking for more errors. It can therefore return more than one error + % in Errors. Any arguments between and after errors *will* be included + % either in OptionValues and OptionArgs, or in NonOptionArgs. + % Note though it is possible for recognize_all_options to mistake + % an argument that what was intended to be an argument of a previous + % option to be something else (either an option in its own right, or + % a nonoption argument) if the previous argument is not recogizable + % as an option that has an argument because of e.g. a typo in its name. + % + % recognize_options indicates the lack of any errors by returning + % no_option_error in MaybeError. recognize_all_options indicates the same + % by returning the empty list as Errors. % % Note that unlike the process_options_... predicates above, - % this predicate does *not* update the option table in any way. - % It also simply returns file_special options in OptionValues; - % it does not process them. That processing can be done by - % expand_file_specials below. + % these predicates do *not* update the option table in any way. + % They also simply return file_special options in OptionValues; + % they does not process them. That processing can be done by + % the expand_file_specials predicate below. + % +:- pred recognize_options(short_option(OptionType)::in(short_option), + long_option(OptionType)::in(long_option), option_table(OptionType)::in, + list(string)::in, maybe_option_error(OptionType)::out, + list(option_value(OptionType))::out, + list(string)::out, list(string)::out) is det. +:- pred recognize_all_options(short_option(OptionType)::in(short_option), + long_option(OptionType)::in(long_option), option_table(OptionType)::in, + list(string)::in, + list(option_error(OptionType))::out, list(option_value(OptionType))::out, + list(string)::out, list(string)::out) is det. + + % record_arguments(ShortOptionPred, LongOptionPred, OptionTable, + % Args, NonOptionArgs, OptionArgs, MaybeError, OptionValues): + % + % This predicate is an obsolete synonym for + % + % recognize_options(ShortOptionPred, LongOptionPred, OptionTable, + % Args, MaybeError, OptionValues, OptionArgs, NonOptionArgs). % :- pred record_arguments(short_option(OptionType)::in(short_option), long_option(OptionType)::in(long_option), option_table(OptionType)::in, list(string)::in, list(string)::out, list(string)::out, maybe_option_error(OptionType)::out, list(option_value(OptionType))::out) is det. - - % record_all_arguments(ShortOptionPred, LongOptionPred, OptionTable, - % Args, Errors, OptionValues, OptionArgs, NonOptionArgs): - % - % The predicate does the same job as record_arguments, and differs - % from it only in - % - % - having an argument order that puts related return values together, and - % - % - not stopping when it finds an error. Instead it keeps going, - % returning in OptionValues, OptionArgs and/or NonOptionArgs - % all the arguments that are not involved in any errors. - % It indicates the absence of any errors by returning [] as Errors. - % -:- pred record_all_arguments(short_option(OptionType)::in(short_option), - long_option(OptionType)::in(long_option), option_table(OptionType)::in, - list(string)::in, - list(option_error(OptionType))::out, list(option_value(OptionType))::out, - list(string)::out, list(string)::out) is det. +:- pragma obsolete(pred(record_arguments/8), [recognize_arguments/8]). %---------------------------------------------------------------------------% @@ -692,16 +707,16 @@ % OptionValues, MaybeError, NonFileSpecialOptionValues, !MaybeIO): % % Given a list of OptionValues as generated for example by - % record_arguments, replace each ov_file_special option value in that list + % recognize_options, replace each ov_file_special option value in that list % with the option values in the file named by that option. % If there are any errors, return a description of one of them % in MaybeError; otherwise, return the fully expanded list of options % in NonFileSpecialOptionValues, and set MaybeError to no_option_error. % % The ShortOptionPred, LongOptionPred and OptionTable arguments - % play the same role as in record_arguments, since expand_file_specials - % must of course record all the options in files named by ov_file_special - % option values. + % play the same role as in recognize_options, since expand_file_specials + % must of course recognize all the options in files named by + % ov_file_special option values. % :- pred expand_file_specials(short_option(OptionType)::in(short_option), long_option(OptionType)::in(long_option), option_table(OptionType)::in, @@ -1013,7 +1028,7 @@ process_arguments(ShortOptionPred, LongOptionPred, SpecialHandler, !OptionTable, !OptionsSet, !UserData, !MaybeIO) :- % We process the argument list in three phases. % - % - In phase 1, record_arguments loops over all the arguments, and + % - In phase 1, recognize_options loops over all the arguments, and % separates them into the option arguments and the non-option arguments, % recognizing and recording the options (and if relevant, their values) % in option arguments. @@ -1038,8 +1053,8 @@ process_arguments(ShortOptionPred, LongOptionPred, SpecialHandler, % run every phase on the outputs of the earlier phases, even if those % outputs are only partial due to earlier failures. % - record_arguments(ShortOptionPred, LongOptionPred, !.OptionTable, - Args, NonOptionArgs, OptionArgs, MaybeRecordError, OptionValues), + recognize_options(ShortOptionPred, LongOptionPred, !.OptionTable, + Args, MaybeRecordError, OptionValues, OptionArgs, NonOptionArgs), ( MaybeRecordError = no_option_error, expand_file_specials_check(ShortOptionPred, LongOptionPred, @@ -1071,16 +1086,16 @@ process_arguments(ShortOptionPred, LongOptionPred, SpecialHandler, %---------------------------------------------------------------------------% -record_arguments(ShortOptionPred, LongOptionPred, OptionTable, Args, - NonOptionArgs, OptionArgs, MaybeError, OptionValues) :- - record_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, +recognize_options(ShortOptionPred, LongOptionPred, OptionTable, Args, + MaybeError, OptionValues, OptionArgs, NonOptionArgs) :- + recognize_options_loop(ShortOptionPred, LongOptionPred, OptionTable, Args, MaybeError, cord.init, OptionValuesCord, cord.init, OptionArgsCord, cord.init, NonOptionArgsCord), OptionValues = cord.to_list(OptionValuesCord), OptionArgs = cord.list(OptionArgsCord), NonOptionArgs = cord.list(NonOptionArgsCord). -record_all_arguments(ShortOptionPred, LongOptionPred, OptionTable, Args, +recognize_all_options(ShortOptionPred, LongOptionPred, OptionTable, Args, Errors, OptionValues, OptionArgs, NonOptionArgs) :- record_all_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, Args, cord.init, ErrorCord, cord.init, OptionValuesCord, @@ -1090,27 +1105,32 @@ record_all_arguments(ShortOptionPred, LongOptionPred, OptionTable, Args, OptionArgs = cord.list(OptionArgsCord), NonOptionArgs = cord.list(NonOptionArgsCord). -:- pred record_arguments_loop(short_option(OptionType)::in(short_option), +record_arguments(ShortOptionPred, LongOptionPred, OptionTable, Args, + NonOptionArgs, OptionArgs, MaybeError, OptionValues) :- + recognize_options(ShortOptionPred, LongOptionPred, OptionTable, Args, + MaybeError, OptionValues, OptionArgs, NonOptionArgs). + +:- pred recognize_options_loop(short_option(OptionType)::in(short_option), long_option(OptionType)::in(long_option), option_table(OptionType)::in, list(string)::in, maybe_option_error(OptionType)::out, cord(option_value(OptionType))::in, cord(option_value(OptionType))::out, cord(string)::in, cord(string)::out, cord(string)::in, cord(string)::out) is det. -record_arguments_loop(_, _, _, [], +recognize_options_loop(_, _, _, [], no_option_error, !OptionValues, !OptionArgs, !NonOptionArgs). -record_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, +recognize_options_loop(ShortOptionPred, LongOptionPred, OptionTable, Args0, MaybeError, !OptionValues, !OptionArgs, !NonOptionArgs) :- Args0 = [_ | _], - record_argument(ShortOptionPred, LongOptionPred, OptionTable, + recognize_option(ShortOptionPred, LongOptionPred, OptionTable, Args0, Args1, Result), ( ( ( - Result = rar_long_option(Arg, MaybeSepOptionArg, OV), + Result = ror_long_option(Arg, MaybeSepOptionArg, OV), OVs = [OV] ; - Result = rar_short_options(Arg, MaybeSepOptionArg, OVs) + Result = ror_short_options(Arg, MaybeSepOptionArg, OVs) ), cord.snoc(Arg, !OptionArgs), ( @@ -1121,18 +1141,18 @@ record_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, ), cord.snoc_list(OVs, !OptionValues) ; - Result = rar_nonoption(Arg), + Result = ror_nonoption(Arg), cord.snoc(Arg, !NonOptionArgs) ), % As a GNU extension, even after we find a non-option argument, % we keep searching for options. - record_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, + recognize_options_loop(ShortOptionPred, LongOptionPred, OptionTable, Args1, MaybeError, !OptionValues, !OptionArgs, !NonOptionArgs) ; - Result = rar_error(Error), + Result = ror_error(Error), MaybeError = found_option_error(Error) ; - Result = rar_end_of_options, + Result = ror_end_of_options, MaybeError = no_option_error ). @@ -1149,15 +1169,15 @@ record_all_arguments_loop(_, _, _, [], record_all_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, Args0, !Errors, !OptionValues, !OptionArgs, !NonOptionArgs) :- Args0 = [_ | _], - record_argument(ShortOptionPred, LongOptionPred, OptionTable, + recognize_option(ShortOptionPred, LongOptionPred, OptionTable, Args0, Args1, Result), ( ( ( - Result = rar_long_option(Arg, MaybeSepOptionArg, OV), + Result = ror_long_option(Arg, MaybeSepOptionArg, OV), OVs = [OV] ; - Result = rar_short_options(Arg, MaybeSepOptionArg, OVs) + Result = ror_short_options(Arg, MaybeSepOptionArg, OVs) ), cord.snoc(Arg, !OptionArgs), ( @@ -1168,10 +1188,10 @@ record_all_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, ), cord.snoc_list(OVs, !OptionValues) ; - Result = rar_nonoption(Arg), + Result = ror_nonoption(Arg), cord.snoc(Arg, !NonOptionArgs) ; - Result = rar_error(Error), + Result = ror_error(Error), cord.snoc(Error, !Errors) ), % As a GNU extension, even after we find a non-option argument, @@ -1179,13 +1199,13 @@ record_all_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, record_all_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, Args1, !Errors, !OptionValues, !OptionArgs, !NonOptionArgs) ; - Result = rar_end_of_options + Result = ror_end_of_options ). %---------------------% -:- type record_argument_result(OptionType) - ---> rar_long_option( +:- type recognize_option_result(OptionType) + ---> ror_long_option( % This command line word represents a long option. % If the option takes an argument, then % - either this string has the form --optionname=VALUE, @@ -1199,7 +1219,7 @@ record_all_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, % The representation of the long option and its value. option_value(OptionType) ) - ; rar_short_options( + ; ror_short_options( % This command line word represents one *or more* % short options. If a short option has an argument, then % the *rest* of the word, if any, becomes its argument, @@ -1229,17 +1249,17 @@ record_all_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, % is concatenate their values.) list(option_value(OptionType)) ) - ; rar_nonoption( + ; ror_nonoption( % This command line word is neither an option, nor % the argument of an option. string ) - ; rar_error( + ; ror_error( % This command line word looks like it should represent % one or more options, but it does not. option_error(OptionType) ) - ; rar_end_of_options. + ; ror_end_of_options. % Either we have come to the end of the command line, % or we have come to the word ("--") that tells us that % we should stop processing any later words. @@ -1261,14 +1281,14 @@ record_all_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, :- type value_or_error(OptionType) == maybe_error(option_value(OptionType), option_error(OptionType)). -:- pred record_argument(short_option(OptionType)::in(short_option), +:- pred recognize_option(short_option(OptionType)::in(short_option), long_option(OptionType)::in(long_option), option_table(OptionType)::in, list(string)::in, list(string)::out, - record_argument_result(OptionType)::out) is det. + recognize_option_result(OptionType)::out) is det. -record_argument(_ShortOptionPred, _LongOptionPred, _OptionTable, - [], [], rar_end_of_options). -record_argument(ShortOptionPred, LongOptionPred, OptionTable, +recognize_option(_ShortOptionPred, _LongOptionPred, _OptionTable, + [], [], ror_end_of_options). +recognize_option(ShortOptionPred, LongOptionPred, OptionTable, [Arg0 | Args0], Args, Result) :- ( if % Test for an initial "--" just this once, instead of doing three @@ -1284,7 +1304,7 @@ record_argument(ShortOptionPred, LongOptionPred, OptionTable, ( if MaybeLongOption = "" then % "--" terminates option processing Args = Args0, - Result = rar_end_of_options + Result = ror_end_of_options else if string.remove_prefix("no-", MaybeLongOption, LongOption) then % A negated long option. Negated options may not have arguments. Args = Args0, @@ -1293,14 +1313,14 @@ record_argument(ShortOptionPred, LongOptionPred, OptionTable, record_negated_option(OptionTable, Flag, OptName, MaybeOption), ( MaybeOption = ok(OptionValue), - Result = rar_long_option(Arg0, no_sep_arg, OptionValue) + Result = ror_long_option(Arg0, no_sep_arg, OptionValue) ; MaybeOption = error(Error), - Result = rar_error(Error) + Result = ror_error(Error) ) else Error = unrecognized_option(Arg0), - Result = rar_error(Error) + Result = ror_error(Error) ) else % An unnegated long option. Unnegated options may have arguments. @@ -1325,12 +1345,12 @@ record_argument(ShortOptionPred, LongOptionPred, OptionTable, else Args = Args0, Error = option_error(Flag, Arg0, unknown_type), - Result = rar_error(Error) + Result = ror_error(Error) ) else Args = Args0, Error = unrecognized_option(OptName), - Result = rar_error(Error) + Result = ror_error(Error) ) ) else if @@ -1347,14 +1367,14 @@ record_argument(ShortOptionPred, LongOptionPred, OptionTable, record_negated_option(OptionTable, Flag, OptName, MaybeOption), ( MaybeOption = ok(OptionValue), - Result = rar_short_options(Arg0, no_sep_arg, [OptionValue]) + Result = ror_short_options(Arg0, no_sep_arg, [OptionValue]) ; MaybeOption = error(Error), - Result = rar_error(Error) + Result = ror_error(Error) ) else Error = unrecognized_option("-" ++ ShortOptions), - Result = rar_error(Error) + Result = ror_error(Error) ) else % One or more unnegated short options `-xyz'. @@ -1370,14 +1390,14 @@ record_argument(ShortOptionPred, LongOptionPred, OptionTable, % We have tested ShortOptions and it contains at least one % short option, so in the absence of an error, there must be % at least one item in OVs. - Result = rar_short_options(Arg0, MaybeShortArg, OVs) + Result = ror_short_options(Arg0, MaybeShortArg, OVs) ; MaybeError = found_option_error(Error), - Result = rar_error(Error) + Result = ror_error(Error) ) ) else - Result = rar_nonoption(Arg0), + Result = ror_nonoption(Arg0), Args = Args0 ). @@ -1430,7 +1450,7 @@ record_negated_option(OptionTable, Flag, OptName, MaybeOptionValue) :- :- pred record_unnegated_long_option(string::in, maybe_after_eq_arg::in, OptionType::in, string::in, option_data::in, list(string)::in, list(string)::out, - record_argument_result(OptionType)::out) is det. + recognize_option_result(OptionType)::out) is det. record_unnegated_long_option(Arg0, MaybeAfterEqArg, Flag, OptName, OptionData, Args0, Args1, Result) :- @@ -1438,7 +1458,7 @@ record_unnegated_long_option(Arg0, MaybeAfterEqArg, Flag, OptName, OptionData, OptionData = special, Args1 = Args0, OV = ov_special(Flag, OptName), - Result0 = rar_long_option(Arg0, no_sep_arg, OV), + Result0 = ror_long_option(Arg0, no_sep_arg, OV), report_any_unexpected_arg(MaybeAfterEqArg, Flag, OptName, Result0, Result) ; @@ -1462,7 +1482,7 @@ record_unnegated_long_option(Arg0, MaybeAfterEqArg, Flag, OptName, OptionData, ; MaybeArg = no, Error = option_error(Flag, OptName, requires_argument), - Result = rar_error(Error) + Result = ror_error(Error) ) ; ( OptionData = string(_) @@ -1480,13 +1500,13 @@ record_unnegated_long_option(Arg0, MaybeAfterEqArg, Flag, OptName, OptionData, ; MaybeArg = no, Error = option_error(Flag, OptName, requires_argument), - Result = rar_error(Error) + Result = ror_error(Error) ) ). :- pred report_any_unexpected_arg(maybe_after_eq_arg::in, - OptionType::in, string::in, record_argument_result(OptionType)::in, - record_argument_result(OptionType)::out) is det. + OptionType::in, string::in, recognize_option_result(OptionType)::in, + recognize_option_result(OptionType)::out) is det. report_any_unexpected_arg(MaybeAfterEqArg, Flag, OptName, Result0, Result) :- % Note that there cannot ever be any unexpected *separate* arguments, @@ -1501,7 +1521,7 @@ report_any_unexpected_arg(MaybeAfterEqArg, Flag, OptName, Result0, Result) :- MaybeAfterEqArg = after_eq_arg(Arg), ErrorReason = does_not_allow_argument(Arg), Error = option_error(Flag, OptName, ErrorReason), - Result = rar_error(Error) + Result = ror_error(Error) ). :- pred get_option_arg(list(string)::in, maybe_after_eq_arg::in, @@ -1653,12 +1673,12 @@ option_none_to_ov(Flag, OptName, OptionData, OV) :- :- pred record_option_bool(string::in, OptionType::in, string::in, option_data::in(option_data_bool), - bool::in, record_argument_result(OptionType)::out) is det. + bool::in, recognize_option_result(OptionType)::out) is det. record_option_bool(Arg0, Flag, OptName, OptionData, BoolValue, Result) :- option_bool_to_ov(Flag, OptName, OptionData, BoolValue, OV), - Result = rar_long_option(Arg0, no_sep_arg, OV). + Result = ror_long_option(Arg0, no_sep_arg, OV). :- pred option_bool_to_ov( OptionType::in, string::in, option_data::in(option_data_bool), @@ -1675,17 +1695,17 @@ option_bool_to_ov(Flag, OptName, OptionData, BoolValue, OV) :- :- pred record_option_int(string::in, maybe_sep_arg::in, OptionType::in, string::in, option_data::in(option_data_int), - string::in, record_argument_result(OptionType)::out) is det. + string::in, recognize_option_result(OptionType)::out) is det. record_option_int(Arg0, MaybeSepArg, Flag, OptName, OptionData, Arg, Result) :- option_int_to_maybe_ov(Flag, OptName, OptionData, Arg, MaybeOV), ( MaybeOV = yes(OV), - Result = rar_long_option(Arg0, MaybeSepArg, OV) + Result = ror_long_option(Arg0, MaybeSepArg, OV) ; MaybeOV = no, numeric_argument_error(Flag, OptName, Arg, Error), - Result = rar_error(Error) + Result = ror_error(Error) ). :- pred option_int_to_maybe_ov( @@ -1711,12 +1731,12 @@ option_int_to_maybe_ov(Flag, OptName, OptionData, Arg, MaybeOV) :- :- pred record_option_string(string::in, maybe_sep_arg::in, OptionType::in, string::in, option_data::in(option_data_string), - string::in, record_argument_result(OptionType)::out) is det. + string::in, recognize_option_result(OptionType)::out) is det. record_option_string(Arg0, MaybeSepArg, Flag, OptName, OptionData, Arg, Result) :- option_string_to_ov(Flag, OptName, OptionData, Arg, OV), - Result = rar_long_option(Arg0, MaybeSepArg, OV). + Result = ror_long_option(Arg0, MaybeSepArg, OV). :- pred option_string_to_ov( OptionType::in, string::in, option_data::in(option_data_string), @@ -1836,8 +1856,8 @@ expand_file_special_option(ShortOptionPred, LongOptionPred, OptionTable, ( ReadFromFileResult = read_success(Contents), Words = string.words(Contents), - record_arguments(ShortOptionPred, LongOptionPred, OptionTable, - Words, NonOptionArgs, _OptionArgs, FileMaybeError, FileOVs), + recognize_options(ShortOptionPred, LongOptionPred, OptionTable, + Words, FileMaybeError, FileOVs, _OptionArgs, NonOptionArgs), ( FileMaybeError = no_option_error, ( diff --git a/library/getopt_io.m b/library/getopt_io.m index 332aa01b5..fe65d0f3d 100644 --- a/library/getopt_io.m +++ b/library/getopt_io.m @@ -617,8 +617,10 @@ ---> no_option_error ; found_option_error(option_error(OptionType)). - % record_arguments(ShortOptionPred, LongOptionPred, OptionTable, - % Args, NonOptionArgs, OptionArgs, MaybeError, OptionValues): + % recognize_options(ShortOptionPred, LongOptionPred, OptionTable, + % Args, MaybeError, OptionValues, OptionArgs, NonOptionArgs): + % recognize_all_options(ShortOptionPred, LongOptionPred, OptionTable, + % Args, Errors, OptionValues, OptionArgs, NonOptionArgs): % % Given Args, which is a list of command line arguments, % @@ -631,48 +633,61 @@ % - use OptionTable to figure out what kind of value, if any, % each of those user-defined options has as its argument, % - % - find those arguments and convert them to the expected type, and + % - find those arguments and convert them to the expected type, + % and return them OptionValues. % - % - provided no errors occurred in any of the above steps, - % return a list of those options and their values in OptionValues, - % and set MaybeError to no_option_error. + % The two predicates differ in what they do when they find an error. % - % - If some errors *did* occur, then set MaybeError to found_option_error - % wrapped around a description of one of them. This will probably be - % the first, but we do not guarantee that. Also, in this error case, - % OptionValues will probably contain the values of the options processed - % before the error, but we do not guarantee that either. + % - When it finds an error, recognize_options stops processing Args, + % and returns a description of the error in MaybeError. Any arguments + % after the error will not be includes in any of OptionValues, + % OptionsArgs, or NonOptionArgs. + % + % - When it finds an error, recognize_all_options keeps processing Args, + % looking for more errors. It can therefore return more than one error + % in Errors. Any arguments between and after errors *will* be included + % either in OptionValues and OptionArgs, or in NonOptionArgs. + % Note though it is possible for recognize_all_options to mistake + % an argument that what was intended to be an argument of a previous + % option to be something else (either an option in its own right, or + % a nonoption argument) if the previous argument is not recogizable + % as an option that has an argument because of e.g. a typo in its name. + % + % recognize_options indicates the lack of any errors by returning + % no_option_error in MaybeError. recognize_all_options indicates the same + % by returning the empty list as Errors. % % Note that unlike the process_options_... predicates above, - % this predicate does *not* update the option table in any way. - % It also simply returns file_special options in OptionValues; - % it does not process them. That processing can be done by - % expand_file_specials below. + % these predicates do *not* update the option table in any way. + % They also simply return file_special options in OptionValues; + % they does not process them. That processing can be done by + % the expand_file_specials predicate below. + % +:- pred recognize_options(short_option(OptionType)::in(short_option), + long_option(OptionType)::in(long_option), option_table(OptionType)::in, + list(string)::in, maybe_option_error(OptionType)::out, + list(option_value(OptionType))::out, + list(string)::out, list(string)::out) is det. +:- pred recognize_all_options(short_option(OptionType)::in(short_option), + long_option(OptionType)::in(long_option), option_table(OptionType)::in, + list(string)::in, + list(option_error(OptionType))::out, list(option_value(OptionType))::out, + list(string)::out, list(string)::out) is det. + + % record_arguments(ShortOptionPred, LongOptionPred, OptionTable, + % Args, NonOptionArgs, OptionArgs, MaybeError, OptionValues): + % + % This predicate is an obsolete synonym for + % + % recognize_options(ShortOptionPred, LongOptionPred, OptionTable, + % Args, MaybeError, OptionValues, OptionArgs, NonOptionArgs). % :- pred record_arguments(short_option(OptionType)::in(short_option), long_option(OptionType)::in(long_option), option_table(OptionType)::in, list(string)::in, list(string)::out, list(string)::out, maybe_option_error(OptionType)::out, list(option_value(OptionType))::out) is det. - - % record_all_arguments(ShortOptionPred, LongOptionPred, OptionTable, - % Args, Errors, OptionValues, OptionArgs, NonOptionArgs): - % - % The predicate does the same job as record_arguments, and differs - % from it only in - % - % - having an argument order that puts related return values together, and - % - % - not stopping when it finds an error. Instead it keeps going, - % returning in OptionValues, OptionArgs and/or NonOptionArgs - % all the arguments that are not involved in any errors. - % It indicates the absence of any errors by returning [] as Errors. - % -:- pred record_all_arguments(short_option(OptionType)::in(short_option), - long_option(OptionType)::in(long_option), option_table(OptionType)::in, - list(string)::in, - list(option_error(OptionType))::out, list(option_value(OptionType))::out, - list(string)::out, list(string)::out) is det. +:- pragma obsolete(pred(record_arguments/8), [recognize_arguments/8]). %---------------------------------------------------------------------------% @@ -696,16 +711,16 @@ % OptionValues, MaybeError, NonFileSpecialOptionValues, !MaybeIO): % % Given a list of OptionValues as generated for example by - % record_arguments, replace each ov_file_special option value in that list + % recognize_options, replace each ov_file_special option value in that list % with the option values in the file named by that option. % If there are any errors, return a description of one of them % in MaybeError; otherwise, return the fully expanded list of options % in NonFileSpecialOptionValues, and set MaybeError to no_option_error. % % The ShortOptionPred, LongOptionPred and OptionTable arguments - % play the same role as in record_arguments, since expand_file_specials - % must of course record all the options in files named by ov_file_special - % option values. + % play the same role as in recognize_options, since expand_file_specials + % must of course recognize all the options in files named by + % ov_file_special option values. % :- pred expand_file_specials(short_option(OptionType)::in(short_option), long_option(OptionType)::in(long_option), option_table(OptionType)::in, @@ -1017,7 +1032,7 @@ process_arguments(ShortOptionPred, LongOptionPred, SpecialHandler, !OptionTable, !OptionsSet, !UserData, !MaybeIO) :- % We process the argument list in three phases. % - % - In phase 1, record_arguments loops over all the arguments, and + % - In phase 1, recognize_options loops over all the arguments, and % separates them into the option arguments and the non-option arguments, % recognizing and recording the options (and if relevant, their values) % in option arguments. @@ -1042,8 +1057,8 @@ process_arguments(ShortOptionPred, LongOptionPred, SpecialHandler, % run every phase on the outputs of the earlier phases, even if those % outputs are only partial due to earlier failures. % - record_arguments(ShortOptionPred, LongOptionPred, !.OptionTable, - Args, NonOptionArgs, OptionArgs, MaybeRecordError, OptionValues), + recognize_options(ShortOptionPred, LongOptionPred, !.OptionTable, + Args, MaybeRecordError, OptionValues, OptionArgs, NonOptionArgs), ( MaybeRecordError = no_option_error, expand_file_specials_check(ShortOptionPred, LongOptionPred, @@ -1075,16 +1090,16 @@ process_arguments(ShortOptionPred, LongOptionPred, SpecialHandler, %---------------------------------------------------------------------------% -record_arguments(ShortOptionPred, LongOptionPred, OptionTable, Args, - NonOptionArgs, OptionArgs, MaybeError, OptionValues) :- - record_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, +recognize_options(ShortOptionPred, LongOptionPred, OptionTable, Args, + MaybeError, OptionValues, OptionArgs, NonOptionArgs) :- + recognize_options_loop(ShortOptionPred, LongOptionPred, OptionTable, Args, MaybeError, cord.init, OptionValuesCord, cord.init, OptionArgsCord, cord.init, NonOptionArgsCord), OptionValues = cord.to_list(OptionValuesCord), OptionArgs = cord.list(OptionArgsCord), NonOptionArgs = cord.list(NonOptionArgsCord). -record_all_arguments(ShortOptionPred, LongOptionPred, OptionTable, Args, +recognize_all_options(ShortOptionPred, LongOptionPred, OptionTable, Args, Errors, OptionValues, OptionArgs, NonOptionArgs) :- record_all_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, Args, cord.init, ErrorCord, cord.init, OptionValuesCord, @@ -1094,27 +1109,32 @@ record_all_arguments(ShortOptionPred, LongOptionPred, OptionTable, Args, OptionArgs = cord.list(OptionArgsCord), NonOptionArgs = cord.list(NonOptionArgsCord). -:- pred record_arguments_loop(short_option(OptionType)::in(short_option), +record_arguments(ShortOptionPred, LongOptionPred, OptionTable, Args, + NonOptionArgs, OptionArgs, MaybeError, OptionValues) :- + recognize_options(ShortOptionPred, LongOptionPred, OptionTable, Args, + MaybeError, OptionValues, OptionArgs, NonOptionArgs). + +:- pred recognize_options_loop(short_option(OptionType)::in(short_option), long_option(OptionType)::in(long_option), option_table(OptionType)::in, list(string)::in, maybe_option_error(OptionType)::out, cord(option_value(OptionType))::in, cord(option_value(OptionType))::out, cord(string)::in, cord(string)::out, cord(string)::in, cord(string)::out) is det. -record_arguments_loop(_, _, _, [], +recognize_options_loop(_, _, _, [], no_option_error, !OptionValues, !OptionArgs, !NonOptionArgs). -record_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, +recognize_options_loop(ShortOptionPred, LongOptionPred, OptionTable, Args0, MaybeError, !OptionValues, !OptionArgs, !NonOptionArgs) :- Args0 = [_ | _], - record_argument(ShortOptionPred, LongOptionPred, OptionTable, + recognize_option(ShortOptionPred, LongOptionPred, OptionTable, Args0, Args1, Result), ( ( ( - Result = rar_long_option(Arg, MaybeSepOptionArg, OV), + Result = ror_long_option(Arg, MaybeSepOptionArg, OV), OVs = [OV] ; - Result = rar_short_options(Arg, MaybeSepOptionArg, OVs) + Result = ror_short_options(Arg, MaybeSepOptionArg, OVs) ), cord.snoc(Arg, !OptionArgs), ( @@ -1125,18 +1145,18 @@ record_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, ), cord.snoc_list(OVs, !OptionValues) ; - Result = rar_nonoption(Arg), + Result = ror_nonoption(Arg), cord.snoc(Arg, !NonOptionArgs) ), % As a GNU extension, even after we find a non-option argument, % we keep searching for options. - record_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, + recognize_options_loop(ShortOptionPred, LongOptionPred, OptionTable, Args1, MaybeError, !OptionValues, !OptionArgs, !NonOptionArgs) ; - Result = rar_error(Error), + Result = ror_error(Error), MaybeError = found_option_error(Error) ; - Result = rar_end_of_options, + Result = ror_end_of_options, MaybeError = no_option_error ). @@ -1153,15 +1173,15 @@ record_all_arguments_loop(_, _, _, [], record_all_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, Args0, !Errors, !OptionValues, !OptionArgs, !NonOptionArgs) :- Args0 = [_ | _], - record_argument(ShortOptionPred, LongOptionPred, OptionTable, + recognize_option(ShortOptionPred, LongOptionPred, OptionTable, Args0, Args1, Result), ( ( ( - Result = rar_long_option(Arg, MaybeSepOptionArg, OV), + Result = ror_long_option(Arg, MaybeSepOptionArg, OV), OVs = [OV] ; - Result = rar_short_options(Arg, MaybeSepOptionArg, OVs) + Result = ror_short_options(Arg, MaybeSepOptionArg, OVs) ), cord.snoc(Arg, !OptionArgs), ( @@ -1172,10 +1192,10 @@ record_all_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, ), cord.snoc_list(OVs, !OptionValues) ; - Result = rar_nonoption(Arg), + Result = ror_nonoption(Arg), cord.snoc(Arg, !NonOptionArgs) ; - Result = rar_error(Error), + Result = ror_error(Error), cord.snoc(Error, !Errors) ), % As a GNU extension, even after we find a non-option argument, @@ -1183,13 +1203,13 @@ record_all_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, record_all_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, Args1, !Errors, !OptionValues, !OptionArgs, !NonOptionArgs) ; - Result = rar_end_of_options + Result = ror_end_of_options ). %---------------------% -:- type record_argument_result(OptionType) - ---> rar_long_option( +:- type recognize_option_result(OptionType) + ---> ror_long_option( % This command line word represents a long option. % If the option takes an argument, then % - either this string has the form --optionname=VALUE, @@ -1203,7 +1223,7 @@ record_all_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, % The representation of the long option and its value. option_value(OptionType) ) - ; rar_short_options( + ; ror_short_options( % This command line word represents one *or more* % short options. If a short option has an argument, then % the *rest* of the word, if any, becomes its argument, @@ -1233,17 +1253,17 @@ record_all_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, % is concatenate their values.) list(option_value(OptionType)) ) - ; rar_nonoption( + ; ror_nonoption( % This command line word is neither an option, nor % the argument of an option. string ) - ; rar_error( + ; ror_error( % This command line word looks like it should represent % one or more options, but it does not. option_error(OptionType) ) - ; rar_end_of_options. + ; ror_end_of_options. % Either we have come to the end of the command line, % or we have come to the word ("--") that tells us that % we should stop processing any later words. @@ -1265,14 +1285,14 @@ record_all_arguments_loop(ShortOptionPred, LongOptionPred, OptionTable, :- type value_or_error(OptionType) == maybe_error(option_value(OptionType), option_error(OptionType)). -:- pred record_argument(short_option(OptionType)::in(short_option), +:- pred recognize_option(short_option(OptionType)::in(short_option), long_option(OptionType)::in(long_option), option_table(OptionType)::in, list(string)::in, list(string)::out, - record_argument_result(OptionType)::out) is det. + recognize_option_result(OptionType)::out) is det. -record_argument(_ShortOptionPred, _LongOptionPred, _OptionTable, - [], [], rar_end_of_options). -record_argument(ShortOptionPred, LongOptionPred, OptionTable, +recognize_option(_ShortOptionPred, _LongOptionPred, _OptionTable, + [], [], ror_end_of_options). +recognize_option(ShortOptionPred, LongOptionPred, OptionTable, [Arg0 | Args0], Args, Result) :- ( if % Test for an initial "--" just this once, instead of doing three @@ -1288,7 +1308,7 @@ record_argument(ShortOptionPred, LongOptionPred, OptionTable, ( if MaybeLongOption = "" then % "--" terminates option processing Args = Args0, - Result = rar_end_of_options + Result = ror_end_of_options else if string.remove_prefix("no-", MaybeLongOption, LongOption) then % A negated long option. Negated options may not have arguments. Args = Args0, @@ -1297,14 +1317,14 @@ record_argument(ShortOptionPred, LongOptionPred, OptionTable, record_negated_option(OptionTable, Flag, OptName, MaybeOption), ( MaybeOption = ok(OptionValue), - Result = rar_long_option(Arg0, no_sep_arg, OptionValue) + Result = ror_long_option(Arg0, no_sep_arg, OptionValue) ; MaybeOption = error(Error), - Result = rar_error(Error) + Result = ror_error(Error) ) else Error = unrecognized_option(Arg0), - Result = rar_error(Error) + Result = ror_error(Error) ) else % An unnegated long option. Unnegated options may have arguments. @@ -1329,12 +1349,12 @@ record_argument(ShortOptionPred, LongOptionPred, OptionTable, else Args = Args0, Error = option_error(Flag, Arg0, unknown_type), - Result = rar_error(Error) + Result = ror_error(Error) ) else Args = Args0, Error = unrecognized_option(OptName), - Result = rar_error(Error) + Result = ror_error(Error) ) ) else if @@ -1351,14 +1371,14 @@ record_argument(ShortOptionPred, LongOptionPred, OptionTable, record_negated_option(OptionTable, Flag, OptName, MaybeOption), ( MaybeOption = ok(OptionValue), - Result = rar_short_options(Arg0, no_sep_arg, [OptionValue]) + Result = ror_short_options(Arg0, no_sep_arg, [OptionValue]) ; MaybeOption = error(Error), - Result = rar_error(Error) + Result = ror_error(Error) ) else Error = unrecognized_option("-" ++ ShortOptions), - Result = rar_error(Error) + Result = ror_error(Error) ) else % One or more unnegated short options `-xyz'. @@ -1374,14 +1394,14 @@ record_argument(ShortOptionPred, LongOptionPred, OptionTable, % We have tested ShortOptions and it contains at least one % short option, so in the absence of an error, there must be % at least one item in OVs. - Result = rar_short_options(Arg0, MaybeShortArg, OVs) + Result = ror_short_options(Arg0, MaybeShortArg, OVs) ; MaybeError = found_option_error(Error), - Result = rar_error(Error) + Result = ror_error(Error) ) ) else - Result = rar_nonoption(Arg0), + Result = ror_nonoption(Arg0), Args = Args0 ). @@ -1434,7 +1454,7 @@ record_negated_option(OptionTable, Flag, OptName, MaybeOptionValue) :- :- pred record_unnegated_long_option(string::in, maybe_after_eq_arg::in, OptionType::in, string::in, option_data::in, list(string)::in, list(string)::out, - record_argument_result(OptionType)::out) is det. + recognize_option_result(OptionType)::out) is det. record_unnegated_long_option(Arg0, MaybeAfterEqArg, Flag, OptName, OptionData, Args0, Args1, Result) :- @@ -1442,7 +1462,7 @@ record_unnegated_long_option(Arg0, MaybeAfterEqArg, Flag, OptName, OptionData, OptionData = special, Args1 = Args0, OV = ov_special(Flag, OptName), - Result0 = rar_long_option(Arg0, no_sep_arg, OV), + Result0 = ror_long_option(Arg0, no_sep_arg, OV), report_any_unexpected_arg(MaybeAfterEqArg, Flag, OptName, Result0, Result) ; @@ -1466,7 +1486,7 @@ record_unnegated_long_option(Arg0, MaybeAfterEqArg, Flag, OptName, OptionData, ; MaybeArg = no, Error = option_error(Flag, OptName, requires_argument), - Result = rar_error(Error) + Result = ror_error(Error) ) ; ( OptionData = string(_) @@ -1484,13 +1504,13 @@ record_unnegated_long_option(Arg0, MaybeAfterEqArg, Flag, OptName, OptionData, ; MaybeArg = no, Error = option_error(Flag, OptName, requires_argument), - Result = rar_error(Error) + Result = ror_error(Error) ) ). :- pred report_any_unexpected_arg(maybe_after_eq_arg::in, - OptionType::in, string::in, record_argument_result(OptionType)::in, - record_argument_result(OptionType)::out) is det. + OptionType::in, string::in, recognize_option_result(OptionType)::in, + recognize_option_result(OptionType)::out) is det. report_any_unexpected_arg(MaybeAfterEqArg, Flag, OptName, Result0, Result) :- % Note that there cannot ever be any unexpected *separate* arguments, @@ -1505,7 +1525,7 @@ report_any_unexpected_arg(MaybeAfterEqArg, Flag, OptName, Result0, Result) :- MaybeAfterEqArg = after_eq_arg(Arg), ErrorReason = does_not_allow_argument(Arg), Error = option_error(Flag, OptName, ErrorReason), - Result = rar_error(Error) + Result = ror_error(Error) ). :- pred get_option_arg(list(string)::in, maybe_after_eq_arg::in, @@ -1657,12 +1677,12 @@ option_none_to_ov(Flag, OptName, OptionData, OV) :- :- pred record_option_bool(string::in, OptionType::in, string::in, option_data::in(option_data_bool), - bool::in, record_argument_result(OptionType)::out) is det. + bool::in, recognize_option_result(OptionType)::out) is det. record_option_bool(Arg0, Flag, OptName, OptionData, BoolValue, Result) :- option_bool_to_ov(Flag, OptName, OptionData, BoolValue, OV), - Result = rar_long_option(Arg0, no_sep_arg, OV). + Result = ror_long_option(Arg0, no_sep_arg, OV). :- pred option_bool_to_ov( OptionType::in, string::in, option_data::in(option_data_bool), @@ -1679,17 +1699,17 @@ option_bool_to_ov(Flag, OptName, OptionData, BoolValue, OV) :- :- pred record_option_int(string::in, maybe_sep_arg::in, OptionType::in, string::in, option_data::in(option_data_int), - string::in, record_argument_result(OptionType)::out) is det. + string::in, recognize_option_result(OptionType)::out) is det. record_option_int(Arg0, MaybeSepArg, Flag, OptName, OptionData, Arg, Result) :- option_int_to_maybe_ov(Flag, OptName, OptionData, Arg, MaybeOV), ( MaybeOV = yes(OV), - Result = rar_long_option(Arg0, MaybeSepArg, OV) + Result = ror_long_option(Arg0, MaybeSepArg, OV) ; MaybeOV = no, numeric_argument_error(Flag, OptName, Arg, Error), - Result = rar_error(Error) + Result = ror_error(Error) ). :- pred option_int_to_maybe_ov( @@ -1715,12 +1735,12 @@ option_int_to_maybe_ov(Flag, OptName, OptionData, Arg, MaybeOV) :- :- pred record_option_string(string::in, maybe_sep_arg::in, OptionType::in, string::in, option_data::in(option_data_string), - string::in, record_argument_result(OptionType)::out) is det. + string::in, recognize_option_result(OptionType)::out) is det. record_option_string(Arg0, MaybeSepArg, Flag, OptName, OptionData, Arg, Result) :- option_string_to_ov(Flag, OptName, OptionData, Arg, OV), - Result = rar_long_option(Arg0, MaybeSepArg, OV). + Result = ror_long_option(Arg0, MaybeSepArg, OV). :- pred option_string_to_ov( OptionType::in, string::in, option_data::in(option_data_string), @@ -1840,8 +1860,8 @@ expand_file_special_option(ShortOptionPred, LongOptionPred, OptionTable, ( ReadFromFileResult = read_success(Contents), Words = string.words(Contents), - record_arguments(ShortOptionPred, LongOptionPred, OptionTable, - Words, NonOptionArgs, _OptionArgs, FileMaybeError, FileOVs), + recognize_options(ShortOptionPred, LongOptionPred, OptionTable, + Words, FileMaybeError, FileOVs, _OptionArgs, NonOptionArgs), ( FileMaybeError = no_option_error, (