bug-gnulib
[Top][All Lists]
Advanced

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

argp: output formatting, and argp_child interface.


From: Paul Knowles
Subject: argp: output formatting, and argp_child interface.
Date: Thu, 15 Dec 2005 15:04:44 +0100

Hello,

 I recently started on a project where, eventually, users need a
transparent way to add parameters to the command line for routines
they will be linking to the application.  argp looks like the right
tool for that, however, the interface, especially for multiple child
parsers, leaves a lot to be desired.  I've written up what I find as
frustrations and/or bugs, and would like to know your reactions on
fixing them (either by changing argp, or by changing my knowlege of
how argp is supposed to work).

******* Problem #1
struct argp{
  ...
  /* A vector of argp_children structures, terminated by a member with a 0
     argp field, pointing to child argps should be parsed with this one.  Any
     conflicts are resolved in favor of this argp, or early argps in the
     CHILDREN list.  This field is useful if you use libraries that supply
     their own argp structure, which you want to use in conjunction with your
     own.  */
  __const struct argp_child *children;
  ...
}

In my opinion, much better would be 
    struct argp_child **children;
for the reason that multiparser structures can then have an easy to
use, scalable, interface.  By adding a function to add children, much
of the complexity of the multiparser setup will go away.

void
argp_add_child(struct *argp, struct *argp_child, void *input)
{
        /* TOTALLY untested code! */
        int i=0;
        struct argp_child **cadd;
        void **iadd;
        assert(argp);
        assert(argp_child);
        
        cadd = argp->children;  
        
        /* works for adding the first child, and all subsequent */ 
        if(cadd){
           /* walk the list and count the children */
           while(*cadd){
               i++;
               cadd++;
        }

        /* keep space for all i existing children, 
           add space for the new child, and the NULL terminator
         */
        cadd = realloc(argp->children, (i+2)*sizeof(struct argp_child *));
        if(!cadd){
            /* no error recovery is really possible. */
            abort();
        }
        argp->children = cadd;
        *(argp->children+i) = argp_child;
        *(argp->children+i+1) = NULL;
        
//      + whatever is needed to crawl argp_state->child_inputs,
//      enlarge it, and add input to the right place: 
//      in all honesty, the documentation is incomprehensible on how
//      to do this correctly.
//      like this maybe? 

        /* keep space for all i existing children inputs, 
           add space for a new child, and the NULL terminator
           Note that this array _can_ have null's scattered throughout
           we must rely on i to see if the input pointer exists.

   How do we get argp_state given only argp?, and each argp
 can have its own child list, is state different for each?
 What keeps them from stepping on each other? (or are there
 internals here I don't yet know about?)

         */
        iadd = realloc(argp_state->child_inputs, (i+2)*sizeof(void *));
        assert(iadd);
        argp_state->child_inputs = iadd;
        *(argp_state->child_inputs+i) = input;
        *(argp_state->child_inputs+i+1) = NULL;

        return;
}

The idea of this is that it can easily enlarge the child pointer
array, add the child, and crawl in the argp_state **child_inputs list
and add the input address in the right place. (why is **child_inputs
already the ``right'' kind of variable, while argp_child *children is
busted? is it historic?)

That adding children is not encapsulated from the argp user by one
function call is a bug in the interface.

I realize that there are many projects already using the argp
interface as it presently stands.  From what I have seen, several have
solved the add_child problem in interesting and inventive ways, mostly
involving static arrays, memmove() or memcpy(), and a prayer that
users never add more parsers than the static array can hold.  This
means basically that they have ``solved'' the interface problem by
going around it, instead of fixing the lack of dedicated functions for
doing so.  As developers with longer usage exposure to argp than I,
what are your thoughts on the change proposed above?  How intrusive is
it for the rest of the internals? and how much pain will it cause as a
change in glibc?


******* Problem #2

Word wrapping should look at the COLUMNS environment variable to
determine word wrap unless rmargin=N was explicitly set by the user in 
ARGP_HELP_FMT.  It is silly that help text gets garbled and squashed
up into 79 columns on my 110 column xterms and that the resizing is
not automagic.  If I expressly drag my xterm corner to resize the
screen, I shouldn't also be required to accord it with yet another
environment variable: COLUMNS is already set, use it, or something
like min(150, COLUMNS-1) if 1000 character wide terminals cause problems.

If this is not acceptable, then somehow make the wrap
parameters available as customization parameters from within
the program, via, eg, a `struct argp_format', structure and
functions like argp_get_format() and argp_set_format() for
the things that are, for the moment, only accessible via
ARGP_HELP_FMT environment variables.


*******  Problem 3;
 I believe I have also stumbled on an output formatting problem, but
the code to duplicate a test case of this is not yet ready.  If time
permits I will make a test case.  The problem centered on the
difference between argp_option:

     {0, 0, 0, 0,   "Estimator and Window selection options", 2},
     {"algorithm", 'a', "NAME", 0, "Specify the estimator algorithm.", 0},

producing:
*********
 Estimator and Window selection options
  -a, --algorithm=NAME       Specify the estimator algorithm.
*********
with nicely aligned output, and 
     {0, 0, 0, 0,   "Estimator and Window selection options", 2},
     {"algorithm", 'a', "NAME", 0, 
                   "Specify the estimator algorithm used for frequency 
determination.", 0},
producing:
*********
 Estimator and Window selection options
  -a,                      --algorithm=NAME       Specify the 
                           estimator algorithm for frequency determination.
*********
where the option is misaligned in the output.  It specifically
happened only for the first option following the {0,0,0,0...} tag
line, and only when the option string got too long, for a presently
unknown value of `too long'.

glibc version 2.3.6 

with thanks for your attention and time
.paul.

Dr. Paul Knowles.               phone: 41 26 300 90 64
email: address@hidden      Fax: 41 26 300 97 47
finger me at pexppc33.unifr.ch for more contact information




reply via email to

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