Re: Options handler for userspace programs

From: Andrea Di Pasquale <spikey.it_at_gmail.com>
Date: Tue, 23 Dec 2008 16:35:49 +0100
Hi! I written new options parser for argv, string and
environment variable.

optsscan_argv()		/* handle argv */
optsscan_strenv()	/* handle string or env var */

They include getopt(), getopt_long() and
getopt_long_only() functionalities in two types of functions.
So, you can handle only short options, short and long
options and only long options, all in two types of functions.
Obviously, you can to handle an argument, with this syntax:

Short options:

	-o
	-o arg
	-o= arg
	-o=arg

Long options:

	--option
	--option argument
	--option= argument
	--option=argument

Link to tarball:

	http://jo666.altervista.org/optsscan.tar.gz

Here, you can find optsscan code and a main example.

Thank you,
regards,

Andrea

> You clearly need two different functions:
> * One that accepts an array of options (such as "argv")
> * One that accepts a string
>
> The latter can then be used for handling environment
> variables or files.
>
> Tim
>
>
> Andrea Di Pasquale wrote:
>> Hi Tim,
>> If you want, i can to build:
>> optsscan_argv()
>> optsscan_env()
>> optsscan_string()
>> Else, i can to build optsscan() that read from *envstr:
>> *envstr can to be environment variable or static string.
>> Example:
>> optsscan(etc, getenv($ENV));
>> or
>> optsscan(etc, "--option arg -o arg");
>> I think that support parsing arguments from file is bad idea.
>> Regards,
>> Andrea
>>> If you're going to only support environment
>>> variables (and not support parsing arguments read
>>> from files or coded into static strings), then
>>> it makes sense to bundle it.
>>>
>>> Tim
>>>
>>> Andrea Di Pasquale wrote:
>>>
>>>> Hi Tim, how are you?
>>>> I'm writing optsscan() at the moment, it supports short,
>>>> short & long, long option style, all in a function.
>>>> Instead, getopt uses:
>>>> getopt()                /* short */
>>>> getopt_long()         /* short & long */
>>>> getopt_long_only()    /* long */
>>>> Here, all there functions are in:
>>>> optsscan()
>>>> Obviously, the coder can choose one style or two style or all  
>>>> styles.
>>>> Ma question is: can i include environment variable parser for  
>>>> options
>>>> in optsscan() or i must to divide it in optsscan_argv() and
>>>> optsscan_envp() ?
>>>> Best regards,
>>>> Andrea
>>>>
>>>>> Andrea Di Pasquale wrote:
>>>>>
>>>>>> Hi Tim! Thanks for your response.
>>>>>> What do you mean with:
>>>>>>
>>>>>>> * gzip supports command-line options in environment variables;
>>>>>>> neither getopt() nor getopt_long() can be used to parse
>>>>>>> a string containing command-line options
>>>>>
>>>>>
>>>>>
>>>>> GZip allows you to add additional command-line arguments
>>>>> through an environment variable:
>>>>> GZIP="-8v --name"
>>>>>
>>>>> It is not easy to use getopt() or getopt_long() with this
>>>>> because it's not already split into words.  (The argv array
>>>>> has already been split into words by the shell.)
>>>>>
>>>>> To support this, the option parser should have a way to
>>>>> give it a string that's not already split and parse that.
>>>>> Programs that wanted to work like gzip could then just
>>>>> parse the environment variable, then the argv list,
>>>>> as suggested below.
>>>>>
>>>>> I've seen other cases where programs want to parse
>>>>> options that are read from a file or from stdin.
>>>>> GNU tar, for instance, supports command-line options
>>>>> when reading input for the -T option.  Having an easy
>>>>> way to parse a string before or after the normal argv
>>>>> array would make this much easier to implement.
>>>>>
>>>>> To handle all of the different modes that you'll
>>>>> want to support (read lib/libc/stdlib/getopt_long.c
>>>>> source to see some of the modes people have found
>>>>> useful), I suggest using an object-style interface.
>>>>> Here is one idea for how your parser might be used:
>>>>>
>>>>>
>>>>> #include <option_parser.h>
>>>>>
>>>>> struct parser *parser;  /* The parser object managed by your    
>>>>> library. */
>>>>>
>>>>> struct parser_option my_options[] = {
>>>>> /* ... list of options for this program ... */
>>>>> /* Note: one way to handle 'allargs' might be with a special
>>>>>    entry here.  Then you wouldn't need an explicit 'allarg'
>>>>>    mode setter. */
>>>>> /* A special entry for "--" could also be helpful here;
>>>>>    such an entry would be returned just before the first
>>>>>    non-option (for use with 'allargs').  This should be returned
>>>>>    even if there is not an explicit "--" end-of-option marker.
>>>>>    That would make it easy for programs to use your option
>>>>>    parser for parsing regular options, then stop and later
>>>>>    continue using your option parser to retrieve file options. */
>>>>> };
>>>>> struct parser_option *opt;
>>>>> const char *envopts = getenv("GZIP");
>>>>>
>>>>> parser = parser_new(&my_options);  /* Create a parser object. */
>>>>> parser_disable_permute(&parser); /* Set modes. */
>>>>> parser_enable_longonly(&parser);
>>>>> parser_enable_allargs(&parser);
>>>>> parser_enable_dashW(&parser);
>>>>>
>>>>> while ((opt = parse_option_from_string(&parser, envopts)) !=  
>>>>> NULL) {
>>>>>  /* process option from environment var */
>>>>>
>>>>>  /* Since 'opt' is a pointer to the option description, the
>>>>>     client program can easily use the data from there. */
>>>>>
>>>>>  /* Some information about the option is stored in
>>>>>     the 'parser' object. */
>>>>>  argument = parse_argument(&parser);
>>>>> }
>>>>>
>>>>> /* You could also just have a way to "prepend" a string to the    
>>>>> options,
>>>>> and then return those options with the next loop.  That avoids the
>>>>> need to duplicate the option-parsing loop. */
>>>>>
>>>>> while ((opt = parse_option_from_argv(&parser, &argv, &argc)) ! 
>>>>> =   NULL) {
>>>>>  /* process option from argument list */
>>>>> }
>>>>>
>>>>> /* After this, argv and argc should make sense. */
>>>>>
>>>>> /*
>>>>> Some programs want to use a loop like the above to handle
>>>>> initial options, then want to use parse_option_from_argv()
>>>>> later in a separate loop to read out filenames (and possibly
>>>>> other options).
>>>>> */
>>>>>
Received on Tue Dec 23 2008 - 15:03:43 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:39 UTC