[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Some questions about argp

From: Herbert Euler
Subject: Some questions about argp
Date: Wed, 01 Aug 2007 09:44:54 +0800


I have some questions on the argp implementation.  Please take a look
at them.  Thanks.


The document of this macro, in the libc document, says:

    If a parser function returns `ARGP_ERR_UNKNOWN' for
    `ARGP_KEY_ARG', it is immediately called again with the key
    `ARGP_KEY_ARGS', which has a similar meaning, but is slightly more
    convenient for consuming all remaining arguments.  ARG is 0, and
    the tail of the argument vector may be found at `STATE->argv +
    STATE->next'.  If success is returned for this key, and
    `STATE->next' is unchanged, all remaining arguments are considered
    to have been consumed.  Otherwise, the amount by which
    `STATE->next' has been adjusted indicates how many were used.
    Here's an example that uses both, for different args:

If I do not understand wrong, the document implies that if some parser
changes the value of `STATE->next', then not all of the remaining
arguments will be marked as being consumed.  But the function
parser_parse_arg seems not to handle ARGP_KEY_ARGS this way:

     if (key == ARGP_KEY_ARGS)
       /* The default for ARGP_KEY_ARGS is to assume that if NEXT isn't
          changed by the user, *all* arguments should be considered
          consumed.  */
       parser->state.next = parser->state.argc;

This implementation will mark all of the remaining arguments as
already consumed, no matter whether the called parser changes

The attached argp-test1.c verifies this conclusion:

address@hidden tmp]$ gcc -o argp-test argp-test1.c
address@hidden tmp]$ ./argp-test a b c
Parsing a
address@hidden tmp]$

Do I understand wrong, or is there something wrong in

2. On the input passed in by the user

The following code in the function parser_init shows that only the
first child in a group will get the input in certain conditions:

     if (!group->parser
         && group->argp->children && group->argp->children->argp)
       /* For the special case where no parsing function is supplied for an
          argp, propagate its input to its first child, if any (this just
          makes very simple wrapper argps more convenient).  */
       group->child_inputs[0] = group->input;

And the attached "argp-test2.c" verifies this behavior:

address@hidden tmp]$ gcc -o argp-test argp-test2.c
address@hidden tmp]$ ./argp-test a
key = 0x1000003 In child1_parser: input-data
key = 0x1000003 In child2_parser: (null)
key = 0x0       In child1_parser: input-data
key = 0x1000006 In child1_parser: input-data
key = 0x0       In child2_parser: (null)
key = 0x1000002 In child1_parser: input-data
key = 0x1000001 In child2_parser: (null)
key = 0x1000001 In child1_parser: input-data
key = 0x1000004 In child2_parser: (null)
key = 0x1000004 In child1_parser: input-data
key = 0x1000007 In child2_parser: (null)
key = 0x1000007 In child1_parser: input-data
address@hidden tmp]$

If other children in the group need the input, we have to propagate it
to them.  Why not make it avaliable to all of the children by default?
What do I miss here?

3. On the key of long alias options

The VALs of long alias options are set in convert_options:

                   /* we add a disambiguating code to all the user's
                      values (which is removed before we actually call
                      the function to parse the value); this means that
                      the user loses use of the high 8 bits in all his
                      values (the sign of the lower bits is preserved
                      however)...  */
                   cvt->long_end->val =
                     ((opt->key | real->key) & USER_MASK)
                     + (((group - cvt->parser->groups) + 1) << USER_BITS);

(opt->key | real->key) here makes KEYs in the original alias argps
meaningless.  For example, in the attached argp-test3.c, we have:

static const struct argp_option my_argp_options[] =
   { "real",  'r', NULL, 0,            "a real option",   0, },
   { "alias", 'a', NULL, OPTION_ALIAS, "an alias option", 0, },
   { 0, 0, 0, 0, 0, 0, },

But in the parser, the KEY argument is not set to 'a' when the user
provides the option "--alias", it is set to 's' (= ('r' | 'a')):

address@hidden tmp]$ gcc -o argp-test argp-test3.c
address@hidden tmp]$ ./argp-test --alias
key = 
key = s
argp-test: --alias: (PROGRAM ERROR) Option should have been recognized!?
Try `argp-test --help' or `argp-test --usage' for more information.
address@hidden tmp]$

Perhaps I should define a constant for the options "real" and "alias",
as follows:

enum { REAL_OPTION = 'r', };
static const struct argp_option my_argp_options[] =
   { "real",  REAL_OPTION, NULL, 0,            "a real option",   0, },
   { "alias", REAL_OPTION, NULL, OPTION_ALIAS, "an alias option", 0, },
   { 0, 0, 0, 0, 0, 0, },

But why do we bitwise-or the keys?  I don't see any benefits in it,
what do I miss?

4. On `STATE->arg_num'

This member seems to be group-specific, i.e. it is the number of
arguments processed by the current group.  Its document says:

   `unsigned arg_num'
         While calling a parsing function with the KEY argument
         `ARGP_KEY_ARG', this represents the number of the current arg,
         starting at 0.  It is incremented after each `ARGP_KEY_ARG'
         call returns.  At all other times, this is the number of
         `ARGP_KEY_ARG' arguments that have been processed.

I'm a bit confused about the term "the number of the current arg".
What does this term mean?  Yes, this member is very rarely used.
Perhaps this is not a question.  ;-)

Guanpeng Xu

Express yourself instantly with MSN Messenger! Download today it's FREE! http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/

Attachment: argp-test1.c
Description: Binary data

Attachment: argp-test2.c
Description: Binary data

Attachment: argp-test3.c
Description: Binary data

reply via email to

[Prev in Thread] Current Thread [Next in Thread]