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: [EMAIL PROTECTED] Fax: 41 26 300 97 47 finger me at pexppc33.unifr.ch for more contact information _______________________________________________ bug-gnulib mailing list bug-gnulib@gnu.org http://lists.gnu.org/mailman/listinfo/bug-gnulib