singe/thirdparty/arg_parser/doc/arg_parser.texi

669 lines
26 KiB
Text

\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename arg_parser.info
@documentencoding ISO-8859-15
@settitle Arg_parser Manual
@finalout
@c %**end of header
@set UPDATED 10 March 2026
@set VERSION 1.21
@dircategory Libraries
@direntry
* Arg_parser: (arg_parser). A POSIX/GNU command-line argument parser
@end direntry
@ifnothtml
@titlepage
@title Arg_parser
@subtitle A POSIX/GNU command-line argument parser
@subtitle for Arg_parser version @value{VERSION}, @value{UPDATED}
@author by Antonio Diaz Diaz
@page
@vskip 0pt plus 1filll
@end titlepage
@contents
@end ifnothtml
@ifnottex
@node Top
@top
This manual is for Arg_parser (version @value{VERSION}, @value{UPDATED}).
@menu
* Introduction:: Purpose and features of Arg_parser
* Argument syntax:: By convention, options start with a hyphen
* C++ version:: Using the C++ version of Arg_parser
* C version:: Using the C version of Arg_parser
* C++ example:: Tutorial for the C++ version
* C example:: Tutorial for the C version
* Problems:: Reporting bugs
* Concept index:: Index of concepts
* Function index:: Index of functions, constants, and variables
@end menu
@sp 1
Copyright @copyright{} 2006-2026 Antonio Diaz Diaz.
This manual is free documentation: you have unlimited permission to copy,
distribute, and modify it.
@end ifnottex
@node Introduction
@chapter Introduction
@cindex introduction
@uref{http://www.nongnu.org/arg-parser/arg_parser.html,,Arg_parser}
is an argument parser that follows POSIX and GNU conventions for
command-line arguments. There exist C++ and C versions of Arg_parser. The
C++ version is implemented as a C++ class, while the C version is
implemented as a single struct plus associated functions. Both are simpler,
easier to use, and safer than @samp{getopt_long}.
For maximum stability, Arg_parser is self-contained. It extracts all the
information it needs from its arguments to avoid referring to them later.
This avoids index-out-of-bounds errors and allows the parser object to be
passed as argument to other functions for further analysis.
Arg_parser does not modify its arguments (argc, argv), nor uses any global
variables.
The C++ version of Arg_parser can also parse options from configuration
files.
Arg_parser was developed as the argument parser for
@uref{http://www.gnu.org/software/moe/moe.html,,GNU moe}, because moe's
argument parsing is rather complex. Then I used it in my other projects,
including
@uref{http://www.gnu.org/software/ddrescue/ddrescue.html,,GNU ddrescue},
@uref{http://www.gnu.org/software/ed/ed.html,,GNU ed},
@uref{http://www.nongnu.org/lzip/lzip.html,,lzip},
@uref{http://www.gnu.org/software/ocrad/ocrad.html,,GNU ocrad},
@uref{http://www.nongnu.org/lzip/tarlz.html,,tarlz}, and
@uref{http://www.nongnu.org/zutils/zutils.html,,zutils}, with excellent
results.
@section Differences with @samp{getopt} and @samp{getopt_long}.
@samp{getopt} parses the options one by one, which requires internal state.
Part of this state is stored in several global variables, and part of it is
hidden. For example, the POSIX specification of @samp{getopt} states that:
@quotation
When an element of argv[] contains multiple option characters, it is
unspecified how getopt() determines which options have already been
processed.
@end quotation
Parsing the options one by one is also a lot of work for the application,
which must check for errors (invalid option, missing option argument, etc)
for each option. @samp{getopt} is the 1970s way of parsing command-line
arguments.
@samp{getopt_long} is a not-very-well-designed extension on top of
@samp{getopt}. In addition to parsing the options one by one as
@samp{getopt} does, @samp{getopt_long} accepts configuration data from two
overlapping sources, which makes it easy for errors in the configuration to
remain undetected. For example, a certain long option can be declared to be
equivalent to a given short option, but both forms of the option may contain
contradictory requirements for the option's argument.
OTOH, Arg_parser parses the whole command line at once and fills a struct
with the results, like @samp{gmtime_r} and @samp{stat} do. This way, errors
are checked once, there is no need to permute the elements of argv, and the
struct returned can be used undisturbed by later changes in argv.
Finally, using Arg_parser instead of @samp{getopt_long} reduces the size of
your source code because, as @samp{getopt_long} is not available on all
systems, a portable program using it needs to ship its (larger) source
anyway.
@node Argument syntax
@chapter Syntax of command-line arguments
@cindex argument syntax
POSIX recommends these conventions for command-line arguments.
Arg_parser makes it easy to implement them.
@itemize @bullet
@item A command-line argument is an option if it begins with a hyphen
(@samp{-}).
@item Option names are single alphanumeric characters.
@item Certain options require an argument.
@item An option and its argument may or may not appear as separate tokens.
(In other words, the whitespace separating them is optional, unless the
argument is the empty string).
Thus, @w{@option{-o foo}} and @option{-ofoo} are equivalent.
@item One or more options without arguments, followed by at most one option
that takes an argument, may follow a hyphen in a single token.
Thus, @option{-abc} is equivalent to @w{@option{-a -b -c}}.
@item Options typically precede other non-option arguments.
Arg_parser normally makes it appear as if all the options were specified
before all the non-option arguments for the purposes of parsing, even if the
user of your program intermixed options and non-option arguments. If you
want the arguments in the exact order the user typed them, call
@samp{Arg_parser} with @w{@var{flags} = @samp{in_order}}.
@item The argument @samp{--} terminates all options; any following arguments
are treated as non-option arguments, even if they begin with a hyphen.
@item A token consisting of a single hyphen character is interpreted as an
ordinary non-option argument. By convention, it is used to specify standard
input, standard output, or a file named @samp{-}.
@item Options may be supplied in any order, or appear multiple times.
The interpretation is left up to the particular application program.
@end itemize
GNU adds @dfn{long options} to these conventions:
@itemize @bullet
@item A long option consists of two hyphens (@samp{--}) followed by a name
made of alphanumeric characters and hyphens. Option names are typically one
to three words long, with hyphens to separate words. Abbreviations can be
used for the long option names as long as the abbreviations are unique.
@item A long option and its argument may or may not appear as separate
tokens. In the latter case they must be separated by an equal sign @samp{=}.
Thus, @w{@option{--foo bar}} and @option{--foo=bar} are equivalent.
@end itemize
The syntax of options with an optional argument is
@option{-<short_option><argument>} (without whitespace), or
@option{--<long_option>=<argument>}.
The syntax of options with an empty argument is @option{-<short_option> ""},
@option{--<long_option> ""}, or @option{--<long_option>=""}.
@node C++ version
@chapter Using the C++ version of Arg_parser
@cindex C++ version
The C++ version of Arg_parser is provided in the files @file{arg_parser.h}
and @file{arg_parser.cc}. To learn how to use Arg_parser in your C++
programs, @pxref{C++ example}, and the file @file{main.cc} in the
@uref{http://download.savannah.nongnu.org/releases/arg-parser/,,source tarball}.
@section Parsing arguments and reporting errors
The class @samp{Arg_parser} has two constructors; one to parse command-line
arguments from @var{argv}, and the other to parse a single token from a
configuration file or other source.
@anchor{struct Option}
@deftp {Data Type} struct Option
This structure describes a single option for the sake of @samp{Arg_parser}.
The argument @var{options} must be an array of these structures, one for
each option. Terminate the array with an element containing a code which is
zero. @samp{struct Option} has the following members:
@deftypevr Member @code{int} code
This member is the code that identifies the option, normally the
short-option character. Must be different from 0. A code value outside the
unsigned char range means a long-only option.
@end deftypevr
@deftypevr Member @code{const char *} long_name
This member is the long option name. It is a zero-terminated string. A null
or empty long_name means a short-only option.
@end deftypevr
@deftypevr Member @code{enum Has_arg} has_arg
This member says whether the option takes an argument. It has four valid
values: @samp{no}, @samp{yes}, @samp{maybe}, and @samp{yesme}, meaning
respectively @samp{no argument}, @samp{non-empty argument required},
@samp{optional argument}, and @samp{argument required, but it may be the
empty string}. @samp{yesme} is not recommended.
If an empty argument is passed to an option specified as @samp{yesme}, it
must be in a separate command-line argument or specified as a long option
with the empty string after the @samp{=} character. It can't be specified as
the empty string after the short option.
@end deftypevr
@end deftp
@anchor{enum Flags}
@deftp {Data Type} enum Flags
The argument @var{flags} is a bit mask. You can bitwise-OR the following
constants and assign them to @var{flags} to modify the way in which the
arguments are parsed. @w{@var{flags} = 0} chooses the default behavior
(reorder the options to put them before the non-option arguments).
@deftypevr Constant @code{Flags} in_order
Store the arguments in the exact order the user typed them, without
reordering the options to put them before the non-option arguments.
@end deftypevr
@deftypevr Constant @code{Flags} in_order_stop
Stop option processing when finding the first non-option argument as if the
argument @samp{--} had been found before it. Store the first non-option
argument and all the arguments following it as non-option arguments, even if
they begin with a hyphen. This is similar to the POSIX function @samp{getopt},
which stops option processing after finding the first non-option argument.
@end deftypevr
@deftypevr Constant @code{Flags} in_order_skip
Parse only the heading options. Skip the first non-option argument and all
the arguments following it; do not parse nor store them. The function
@samp{argv_index} returns the index in @var{argv} of the first argument
skipped (the first non-option argument), or @var{argc} if no arguments were
skipped. This mode is useful for parsing the command line of programs that
invoke other programs, like @command{timeout}, @command{xargs}, or
@command{valgrind}.
@end deftypevr
@deftypevr Constant @code{Flags} neg_non_opt
Parse the negative numbers, including @samp{-inf}, @samp{-Inf}, and
@samp{-INF}, as non-option arguments without reordering them. Numbers start
with a digit or a period and a digit. This mode is useful for parsing the
command line of tools like @command{seq} which take negative numbers as
arguments.
@end deftypevr
@end deftp
@defun Arg_parser ( const int @var{argc}, const char * const @var{argv}[], const Option @var{options}[], const int @var{flags} = 0 )
Constructor. Reads the arguments in @var{argv} and parses all options,
option arguments, and non-option arguments contained in them. In case of
error, @samp{error().size()} returns nonzero.
@end defun
@defun Arg_parser ( const char * const @var{opt}, const char * const @var{arg}, const Option @var{options}[] )
Restricted constructor. Parses a single token (plus an optional second token
in case an argument is needed for an option parsed). Can be used to parse
options from a configuration file one at a time. Be warned that a single
token may produce an undefined number of short options. In case of error,
@samp{error().size()} returns nonzero.
@end defun
@deftypefun {const std::string &} error () const
Use this funtion to check that the arguments have been correctly parsed by
the constructor. If there was an error parsing the arguments, @samp{error}
returns an error message explaining the cause, else it returns an empty
string.
@end deftypefun
@deftypefun {int} argv_index () const
Return the index in @var{argv} of the first argument skipped (the first
non-option argument) when @var{flags} was set to @samp{in_order_skip}. If no
arguments were skipped, @var{argc} is returned instead.
@end deftypefun
@section Reading the options and arguments parsed
After a successful call to the constructor, which must be checked by calling
@samp{error}, the options and arguments parsed can be accessed by means of
the following functions:
@deftypefun int arguments () const
This function returns the number of options and non-option arguments parsed.
This number is usually different from argc.
@end deftypefun
@deftypefun int code ( const int @var{i} ) const
This function returns the code of the option at position @var{i}. Valid
values for @var{i} range from 0 to @w{@samp{arguments() - 1}}. If the code
returned is nonzero, @samp{argument(@var{i})} is the option's argument (or
is empty if the option does not have an argument). If the code returned is
zero, @samp{argument(@var{i})} is a non-option argument.
@end deftypefun
@deftypefun {const std::string &} parsed_name ( const int @var{i} ) const
This function returns the full name of the option parsed (short or long) at
position @var{i}. It may be useful to produce more accurate diagnostic
messages. For non-option arguments it returns the empty string.
@end deftypefun
@deftypefun {const std::string &} argument ( const int @var{i} ) const
This function returns the argument at position @var{i}. It may be the
argument of an option or a non-option argument, depending on the value
returned by @samp{code(@var{i})}. Valid values for @var{i} range from 0 to
@w{@samp{arguments() - 1}}. If the argument does not exist, the empty string
is returned.
@end deftypefun
@node C version
@chapter Using the C version of Arg_parser
@cindex C version
The C version of Arg_parser is provided in the files @file{carg_parser.h}
and @file{carg_parser.c}. To learn how to use Arg_parser in your C programs,
@pxref{C example}, and the file @file{cmain.c} in the
@uref{http://download.savannah.nongnu.org/releases/arg-parser/,,source tarball}.
@section Parsing arguments and reporting errors
You need to declare a variable of type @samp{Arg_parser}, pass its address
to @samp{ap_init} to initialize it, and check that @samp{ap_error} returns 0.
@samp{struct ap_Option} is identical to @samp{struct Option}, except that
@samp{Has_arg} becomes @samp{ap_Has_arg}, and the names of its four values
are also prefixed with @samp{ap_}. @xref{struct Option}, for details about
the members.
@samp{enum ap_Flags} is identical to @samp{enum Flags}, except that its
constants are also prefixed with @samp{ap_}. @xref{enum Flags}, for a
description of the constants.
@deftypefun char ap_init ( Arg_parser * const @var{ap}, const int @var{argc}, const char * const @var{argv}[], const ap_Option @var{options}[], const int @var{flags} )
Reads the arguments in @var{argv} and parses all options, option arguments,
and non-option arguments contained in them. Returns 0 if there is not enough
memory, else 1 (even if errors are found). In case of error, @samp{ap_error}
returns a non-null pointer.
@end deftypefun
@deftypefun void ap_free ( Arg_parser * const @var{ap} )
Frees all dynamically allocated data structures.
@end deftypefun
@deftypefun {const char *} ap_error ( const Arg_parser * const @var{ap} )
Use this funtion to check that the arguments have been correctly parsed by
@samp{ap_init}. If there was an error parsing the arguments, @samp{ap_error}
returns a pointer to an error message explaining the cause, else it returns
a null pointer.
@end deftypefun
@deftypefun {int} ap_argv_index ( const Arg_parser * const @var{ap} )
Return the index in @var{argv} of the first argument skipped (the first
non-option argument) when @var{flags} was set to @samp{ap_in_order_skip}. If
no arguments were skipped, @var{argc} is returned instead.
@end deftypefun
@section Reading the options and arguments parsed
After a successful call to @samp{ap_init}, which must be checked by calling
@samp{ap_error}, the options and arguments parsed can be accessed by means
of the following functions:
@deftypefun int ap_arguments ( const Arg_parser * const @var{ap} )
This function returns the number of options and non-option arguments parsed.
This number is usually different from argc.
@end deftypefun
@deftypefun int ap_code ( const Arg_parser * const @var{ap}, const int @var{i} )
This function returns the code of the option at position @var{i}. Valid
values for @var{i} range from 0 to @w{@samp{ap_arguments() - 1}}. If the
code returned is nonzero, @samp{ap_argument(@var{i})} is the option's
argument (or is empty if the option does not have an argument). If the code
returned is zero, @samp{ap_argument(@var{i})} is a non-option argument.
@end deftypefun
@deftypefun {const char *} ap_parsed_name ( const Arg_parser * const @var{ap}, const int @var{i} )
This function returns the full name of the option parsed (short or long) at
position @var{i}. It may be useful to produce more accurate diagnostic
messages. For non-option arguments it returns the empty string.
@end deftypefun
@deftypefun {const char *} ap_argument ( const Arg_parser * const @var{ap}, const int @var{i} )
This function returns the argument at position @var{i}. It may be the
argument of an option or a non-option argument, depending on the value
returned by @samp{ap_code(@var{i})}. Valid values for @var{i} range from 0
to @w{@samp{ap_arguments() - 1}}. If the argument does not exist, the empty
string is returned.
@end deftypefun
When you are finished, you should free all dynamically allocated data
structures by calling @samp{ap_free}.
@node C++ example
@chapter Tutorial for the C++ version
@cindex C++ example
This tutorial uses @uref{http://www.nongnu.org/lzip/lzip.html,,lzip} as an
example of how to use Arg_parser in a C++ program. You need to follow these
6 steps:
First copy the files @file{arg_parser.h} and @file{arg_parser.cc} in your
source tree, in the same directory as the file containing the function
@samp{main} of your program. In lzip, @samp{main} is in @file{main.cc}.
Second, include these header files near the top of @file{main.cc}:
@verbatim
#include <string>
#include <vector>
#include "arg_parser.h"
@end verbatim
Third, define inside @samp{main} the option names and argument requirements.
Lzip defines the following options:
@verbatim
const Arg_parser::Option options[] = {
{ '0', "fast", Arg_parser::no },
{ '1', 0, Arg_parser::no },
{ '2', 0, Arg_parser::no },
{ '3', 0, Arg_parser::no },
{ '4', 0, Arg_parser::no },
{ '5', 0, Arg_parser::no },
{ '6', 0, Arg_parser::no },
{ '7', 0, Arg_parser::no },
{ '8', 0, Arg_parser::no },
{ '9', "best", Arg_parser::no },
{ 'a', "trailing-error", Arg_parser::no },
{ 'b', "member-size", Arg_parser::yes },
{ 'c', "stdout", Arg_parser::no },
{ 'd', "decompress", Arg_parser::no },
{ 'f', "force", Arg_parser::no },
{ 'F', "recompress", Arg_parser::no },
{ 'h', "help", Arg_parser::no },
{ 'k', "keep", Arg_parser::no },
{ 'l', "list", Arg_parser::no },
{ 'm', "match-length", Arg_parser::yes },
{ 'n', "threads", Arg_parser::yes },
{ 'o', "output", Arg_parser::yes },
{ 'q', "quiet", Arg_parser::no },
{ 's', "dictionary-size", Arg_parser::yes },
{ 'S', "volume-size", Arg_parser::yes },
{ 't', "test", Arg_parser::no },
{ 'v', "verbose", Arg_parser::no },
{ 'V', "version", Arg_parser::no },
{ opt_lt, "loose-trailing", Arg_parser::no },
{ 0, 0, Arg_parser::no } };
@end verbatim
Fourth, declare and initialize the parser:
@verbatim
const Arg_parser parser( argc, argv, options );
if( parser.error().size() ) // bad option
{ show_error( parser.error().c_str(), 0, true ); return 1; }
@end verbatim
Fifth, perform the actions corresponding to each option parsed. Lzip
performs the following actions:
@verbatim
int argind = 0;
for( ; argind < parser.arguments(); ++argind )
{
const int code = parser.code( argind );
if( !code ) break; // no more options
const char * const pn = parser.parsed_name( argind ).c_str();
const std::string & sarg = parser.argument( argind );
const char * const arg = sarg.c_str();
switch( code )
{
case '0': case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9': zero = code == '0';
encoder_options = option_mapping[code-'0']; break;
case 'a': cl_opts.ignore_trailing = false; break;
case 'b': member_size = getnum(arg, pn, 100000, max_member_size); break;
case 'c': to_stdout = true; break;
case 'd': set_mode( program_mode, m_decompress ); break;
case 'f': force = true; break;
case 'F': recompress = true; break;
case 'h': show_help(); return 0;
case 'k': keep_input_files = true; break;
case 'l': set_mode( program_mode, m_list ); break;
case 'm': encoder_options.match_len_limit =
getnum( arg, pn, min_match_len_limit, max_match_len );
zero = false; break;
case 'n': break; // ignored
case 'o': if( sarg == "-" ) to_stdout = true;
else { default_output_filename = sarg; } break;
case 'q': verbosity = -1; break;
case 's': encoder_options.dictionary_size = get_dict_size( arg, pn );
zero = false; break;
case 'S': volume_size = getnum(arg, pn, 100000, max_volume_size); break;
case 't': set_mode( program_mode, m_test ); break;
case 'v': if( verbosity < 4 ) ++verbosity; break;
case 'V': show_version(); return 0;
case opt_lt: cl_opts.loose_trailing = true; break;
default: internal_error( "uncaught option." );
}
} // end process options
@end verbatim
Sixth, process any remaining non-option arguments (file names in the case of
lzip):
@verbatim
std::vector< std::string > filenames;
bool filenames_given = false;
for( ; argind < parser.arguments(); ++argind )
{
filenames.push_back( parser.argument( argind ) );
if( filenames.back() != "-" ) filenames_given = true;
}
if( filenames.empty() ) filenames.push_back("-");
// do something with 'filenames'
@end verbatim
@node C example
@chapter Tutorial for the C version
@cindex C example
This tutorial uses @uref{http://www.gnu.org/software/ed/ed.html,,GNU ed} as
an example of how to use Arg_parser in a C program. You need to follow these
6 steps:
First copy the files @file{carg_parser.h} and @file{carg_parser.c} in your
source tree, in the same directory as the file containing the function
@samp{main} of your program. In GNU ed, @samp{main} is in @file{main.c}.
Second, include the header @file{carg_parser.h} near the top of @file{main.c}:
@verbatim
#include "carg_parser.h"
@end verbatim
Third, define inside @samp{main} the option names and argument requirements.
Ed defines the following options:
@verbatim
const ap_Option options[] = {
{ 'E', "extended-regexp", ap_no },
{ 'G', "traditional", ap_no },
{ 'h', "help", ap_no },
{ 'l', "loose-exit-status", ap_no },
{ 'p', "prompt", ap_yes },
{ 'q', "quiet", ap_no },
{ 'q', "silent", ap_no },
{ 'r', "restricted", ap_no },
{ 's', "script", ap_no },
{ 'v', "verbose", ap_no },
{ 'V', "version", ap_no },
{ opt_cr, "strip-trailing-cr", ap_no },
{ opt_un, "unsafe-names", ap_no },
{ 0, 0, ap_no } };
@end verbatim
Fourth, declare and initialize the parser:
@verbatim
Arg_parser parser;
if( !ap_init( &parser, argc, argv, options, 0 ) )
{ show_error( "Memory exhausted.", 0, false ); return 1; }
if( ap_error( &parser ) ) /* bad option */
{ show_error( ap_error( &parser ), 0, true ); return 1; }
@end verbatim
Fifth, perform the actions corresponding to each option parsed. Ed performs
the following actions:
@verbatim
int argind = 0;
for( ; argind < ap_arguments( &parser ); ++argind )
{
const int code = ap_code( &parser, argind );
if( !code ) break; /* no more options */
const char * const arg = ap_argument( &parser, argind );
switch( code )
{
case 'E': extended_regexp_ = true; break;
case 'G': traditional_ = true; break; /* backward compatibility */
case 'h': show_help(); return 0;
case 'l': loose = true; break;
case 'p': if( set_prompt( arg ) ) break; else return 1;
case 'q': quiet = true; break;
case 'r': restricted_ = true; break;
case 's': scripted_ = true; break;
case 'v': set_verbose(); break;
case 'V': show_version(); return 0;
case opt_cr: strip_cr_ = true; break;
case opt_un: safe_names = false; break;
default: show_error( "internal error: uncaught option.", 0, false );
return 3;
}
} /* end process options */
@end verbatim
Sixth, process any remaining non-option arguments (line number and file
name in the case of ed):
@verbatim
for( ; argind < ap_arguments( &parser ); ++argind )
{
const char * const arg = ap_argument( &parser, argind );
/* do something with 'arg' */
}
@end verbatim
@node Problems
@chapter Reporting bugs
@cindex bugs
@cindex getting help
There are probably bugs in Arg_parser. There are certainly errors and
omissions in this manual. If you report them, they will get fixed. If
you don't, no one will ever know about them and they will remain unfixed
for all eternity, if not longer.
If you find a bug in Arg_parser, please send electronic mail to
@email{arg-parser-bug@@nongnu.org}. Include the version number, which
you can find by running @w{@samp{arg_parser --version}}.
@node Concept index
@unnumbered Concept index
@printindex cp
@node Function index
@unnumbered Index of constants and variables
@printindex vr
@sp 1
@unnumbered Index of functions
@printindex fn
@bye