Section 26.2. Using the Option Table

   


26.2. Using the Option Table

26.2.1. Creating a Context

popt can interleave the parsing of multiple command-line sets. It does this by keeping all the state information for a particular set of command-line arguments in a poptContext data structure, an opaque type that should not be modified outside the popt library.

New popt contexts are created by poptGetContext().

 #include <popt.h> poptContext poptGetContext(char * name, int argc, const char ** argv,                            struct poptOption * options, int flags); 


The first parameter, name, is used for alias handling and in help messages, and should be the name of the application whose options are being parsed. The next two arguments specify the command-line arguments to parse. These are generally passed to poptGetContext() exactly as they were passed to the program's main() function.[5] The options parameter points to the table of command-line options, which was described in the previous section. The final parameter, flags, modifies how options are parsed, and consists of the following flags (which may be logically OR'ed together):

[5] A common mistake is to define argv as char ** rather than const char **, which is more correct. The prototype for poptGetContext() causes a compiler warning if argv is not defined in the correct manner.

 POPT_CONTEXT_KEEP_FIRST 


Normally, popt ignores the value in argv[0] as it is typically the name of the program being run rather than a command-line argument. Specifying this flag causes popt to treat argv[0] as an option.

 POPT_CONTEXT_POSIXMEHARDER 


Strict POSIX compliance requires that all options occur before extra command-line parameters. For example, according to POSIX, rm -f file1 file2 would force the files file1 and file2 to be removed, while rm file1 file -f would cause normal removal of the three files file1, file2, and -f. Most Linux programs ignore this particular convention, so popt does not use this rule by default. This flag tells popt to parse options according to this convention.[6]

[6] The "posix me harder" terminology is popular among Linux applications when some (often unpleasant) strict POSIX compatibility mode is provided.

A poptContext keeps track of which options have already been parsed and which remain, among other things. If a program wishes to restart option processing of a set of arguments, it can reset the poptContext by passing the context as the sole argument to poptResetContext().

When argument processing is complete, the process should free the popt-Context as it contains dynamically allocated components. The poptFreeContext() function takes a poptContext as its sole argument and frees the resources the context is using.

Here are the prototypes of both poptResetContext() and poptFreeContext():

 #include <popt.h> void poptFreeContext(poptContext con); void poptResetContext(poptContext con); 


26.2.2. Parsing the Command Line

After an application has created a poptContext, it may begin parsing arguments. The poptGetNextOpt() performs the actual argument parsing.

 #include <popt.h> int poptGetNextOpt(poptContext con); 


Taking the context as its sole argument, this function parses the next command-line argument found. After finding the next argument in the option table, the function fills in the object pointed to by the option table entry's arg pointer if it is not NULL. If the val enTRy for the option is nonzero, the function then returns that value. Otherwise, poptGetNextOpt() continues on to the next argument.

poptGetNextOpt() returns -1 when the final argument has been parsed, and other negative values when errors occur. This makes it a good idea to keep the val elements in the option table greater than zero.

If all of the command-line options are handled through arg pointers, command-line parsing is reduced to the following line of code:

 rc = poptGetNextOpt(poptcon); 


Many applications require more complex command-line parsing than this, however, and use the following structure:

 while ((rc = poptGetNextOpt(poptcon)) > 0) {     switch (rc) {         /* specific arguments are handled here */     } } 


When returned options are handled, the application needs to know the value of any arguments that were specified after the option. There are two ways to discover them. One is to ask popt to fill in a variable with the value of the option through the option table's arg elements. The other is to use poptGetOptArg().

 #include <popt.h> char * poptGetOptArg(poptContext con); 


This function returns the argument given for the final option returned by poptGetNextOpt(), or it returns NULL if no argument was specified.

26.2.3. Leftover Arguments

Many applications take an arbitrary number of command-line arguments, such as a list of file names. When popt encounters an argument that does not begin with a -, it assumes it is such an argument and adds it to a list of leftover arguments. Three functions allow applications to access such arguments:

 char * poptGetArg(poptContext con); 


This function returns the next leftover argument and marks it as processed.

 char * poptPeekArg(poptContext con); 


The next leftover argument is returned but not marked as processed. This allows an application to look ahead into the argument list, without modifying the list.

 char ** poptGetArgs(poptContext con); 


All the leftover arguments are returned in a manner identical to argv. The final element in the returned array points to NULL, indicating the end of the arguments.

26.2.4. Automatic Help Messages

One of the benefits of using popt is its ability to generate help and usage messages automatically. Help messages list each command-line option along with a reasonably detailed description of that option, while usage messages provide a concise list of the available options without any descriptive text. popt provides a function to create each type of message.

 #include <popt.h> void poptPrintHelp(poptContext con, FILE * f, int flags); void poptPrintUsage(poptContext con, FILE * f, int flags); 


These two functions behave almost identically, writing the appropriate type of message to the file f. The flags argument is not currently used by either function, and should be set to zero for compatibility with future versions of popt.

Since the help message is normally provided by the --help option, and the usage message by the --usage option, popt provides an easy way of adding those two options to your program. The POPT_AUTOHELP macro can be used in the option table to add these options,[7] which displays the appropriate messages on STDOUT and exit with a return code of 0.[8] This example shows the option table in grep.c with the single line we need to add to the option table for grep to enable automatic help text:

[7] It also adds a -? option that is the same as --help.

[8] The POPT_AUTOHELP macro expands to add a nested option table that defines the new options and a callback that implements the options.

  95:     struct poptOption optionsTable[] = {  96:             { "extended-regexp", 'E', POPT_ARG_VAL,  97:               &mode, MODE_EXTENDED,  98:               "pattern for match is an extended regular "  99:               "expression" }, 100:             { "fixed-strings", 'F', POPT_ARG_VAL, 101:               &mode, MODE_FIXED, 102:               "pattern for match is a basic string (not a " 103:               "regular expression)", NULL }, 104:             { "basic-regexp", 'G', POPT_ARG_VAL, 105:               &mode, MODE_REGEXP, 106:               "pattern for match is a basic regular expression" }, 107:             { "ignore-case", 'i', POPT_ARG_NONE, &ignoreCase, 0, 108:               "perform case insensitive search", NULL }, 109:             { "max-count", 'm', POPT_ARG_INT, &maxCount, 0, 110:               "terminate after N matches", "N" }, 111:             { "regexp", 'e', POPT_ARG_STRING, &pattern, 0, 112:               "regular expression to search for", "pattern" }, 113:             POPT_AUTOHELP 114:             { NULL, '\0', POPT_ARG_NONE, NULL, 0, NULL, NULL } 115:     }; 


Here is what the help message generated by this table looks like:

 Usage: grep [OPTION...]   -E,  --extended-regexp      pattern for match is an extended regular expression   -F, --fixed-strings        pattern for match is a basic string (not a regular                             expression)   -G, --basic-regexp      pattern for match is a basic regular expression    -i, --ignore-case        perform case insensitive search    -m, --max-count=N        terminate after N matches    -e, --regexp=pattern     regular expression to search for Help options:   -?, --help               Show this help message   --usage                  Display brief usage message 


While this looks quite good, it is not quite right. The first line does not mention that the command expects file names on the command line. The [OPTION...] text that does appear there is popt's default, and this can be changed to be more descriptive through the poptSetOtherOptionHelp() function.

 #include <popt.h> poptSetOtherOptionHelp(poptContext con, const char * text); 


The context is the first parameter and the second specifies the text that should appear after the program's name. Adding this call

 poptSetOtherOptionHelp(optCon, "<pattern> <file list>"); 


changes the first line of our help message to

 Usage: grep <pattern> <file list> 


which is much nicer.

The final nicety of help message generation is how nested tables are handled. Look again at the help message for our grep program; the help options are in their own section of the help message. When a POPT_ARG_INCLUDE_TABLE option table entry provides a descrip member, that string is used as a description for all of the options in the nested table, and those options are displayed in their own section of the help message (like the help options for tail). If the descrip is NULL, the options for the nested table are displayed with the options from the main table rather than in their own section.

Occasionally, programs provide options that probably should not be used; they may be there for support with legacy applications or designed for testing only. Automatic help message generation for that option can be suppressed by logically OR'ing POPT_ARGFLAG_DOC_HIDDEN with the arg member of the the struct poptOption that defines that option.


       
    top
     


    Linux Application Development
    Linux Application Development (paperback) (2nd Edition)
    ISBN: 0321563220
    EAN: 2147483647
    Year: 2003
    Pages: 168

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net