GNU Gengetopt 2.10 Usage

文章出处:http://hi.baidu.com/uframer/blog/item/e7dcc9ef0efb6536adafd500.html

    需要由gengetopt生成的函数处理的命令行选项在一个文件中指定(该文件的扩展名通常为.ggo)。文件组织为文本行,格式为:

    package  <packname>

    version   <version>

    option  <long>  <short>  <desc>

    option  <long>  <short>  <desc>  <argtype>  {default="<default value>"}  <required>  {mutiple}

    option  <long>  <short>  <desc>  flag             <onoff>

    option  <long>  <short>  <desc>  no

 

    其中:

    package

        双引号字符串。优先于autoconf生成的PACKAGE。

    version

        双引号字符串。优先于autoconf生成的VERSION。

    purpose

        双引号字符串。程序的功能(可多行),将会出现在输出的帮助中。

    long

        长选项,双引号字符串。可由大小写字母、数字、'-' 和 '.' 组成,中间不能有空格。依据选项名生成的变量名保存该选项的参数。名字生成规则为:'.' 和 '-' 被替换为 '_',并在最后附加 '_arg' 或 ' _flag'。

    short

        短选项,一个字符,可以为大小写字母或数字。如果该字符为 '-',就表示没有同此行定义的长选项对应的短选项。(也就是说长选项可以没有对应的短选项。

    desc

        双引号字符串。可由大小写字母、数字、'-' 和 '.' 组成,第一个字符不能是空格。

    argtype

        string、int、short、long、float、double、longdouble、或longlong。

    default

        该选项可选的默认值。该值必须用双引号括起来。

    required

        yes或no。

    multiple

        如果标记为multiple,就表示此选项可以出现多次,所有的值被组织在一个数组中。参见“高级特征”一节。

    onoff

        on或off。为程序启动时该flag的状态。如果用户的命令行上给出此选项,则对应的flag反转。

    选项的第三种类型用于不需要任何参数的选项。它绝不能是required。

    文件中可以使用注释,注释的范围从 '#'开始直到行尾。

    下面是ggo文件的一个例子(该文件叫做sample1.ggo)

# file sample1.ggo
option  "str-opt"     s "A string option"      string     no
option  "my-opt"      m "Another integer option"      int     no
option  "int-opt"     i "A int option"         int        yes
option  "flag-opt"    - "A flag option"        flag       off
option  "funct-opt"   F "A function option"    no 
option  "long-opt"    - "A long option"        long       no
option  "def-opt"     - "A string option with default" string default="Hello" no

gengetopt最简单的用法是将输入文件作为标准输入:

    gengetopt < sample1.ggo

在默认情况下gengetopt生成cmdline.hcmdline.c。如果你不喜欢,也可以通过命令行选项指定输出的文件名:

    gengetopt < sample.ggo --file-name=cmdline1 --unamed-opts

选项--unamed-opts使生成的命令行选项解析器接收非选项的名字(例如,你可以直接传递一个文件名而无需将其作为一个选项的参数,还可以使用通配符,如*.c、foo*.? 等等)。

在cmdline1.h中你可以发现一个自动生成的C结构gengetopt_args_info:

/* cmdline1.h */

/* File autogenerated by gengetopt version 2.9.1  */


#ifndef CMDLINE1_H
#define CMDLINE1_H

/* If we use autoconf.  */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#ifndef CMDLINE_PARSER_PACKAGE
#define CMDLINE_PARSER_PACKAGE "sample1"
#endif

#ifndef CMDLINE_PARSER_VERSION
#define CMDLINE_PARSER_VERSION "2.0"
#endif

struct gengetopt_args_info
{
  char * str_opt_arg; /* A string option.  */
  int my_opt_arg; /* Another integer option.  */
  int int_opt_arg; /* A int option.  */
  int flag_opt_flag; /* A flag option (default=off).  */
  long long_opt_arg; /* A long option.  */
  char * def_opt_arg; /* A string option with default (default='Hello').  */

  int help_given ; /* Whether help was given.  */
  int version_given ; /* Whether version was given.  */
  int str_opt_given ; /* Whether str-opt was given.  */
  int my_opt_given ; /* Whether my-opt was given.  */
  int int_opt_given ; /* Whether int-opt was given.  */
  int flag_opt_given ; /* Whether flag-opt was given.  */
  int funct_opt_given ; /* Whether funct-opt was given.  */
  int long_opt_given ; /* Whether long-opt was given.  */
  int def_opt_given ; /* Whether def-opt was given.  */

  char **inputs ; /* unamed options */
  unsigned inputs_num ; /* unamed options number */
} ;

int cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info);

void cmdline_parser_print_help(void);
void cmdline_parser_print_version(void);

#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CMDLINE1_H */

注意,默认情况下生成的函数叫做cmdline_parser(下面给出的命令行选项可以将其命名为其他的名字),参数为main接收的参数和一个指向一个结构体的指针,运行的结果会保存在该结构体中。

在主程序中就可以使用该函数了:

/* main1.cc */
/* we try to use gengetopt generated file in a C++ program */
/* we don't use autoconf and automake vars */

#include <iostream.h>
#include "stdlib.h"

#include "cmdline1.h"

int
main (int argc, char **argv)
{
  gengetopt_args_info args_info;

  cout << "This one is from a C++ program" << endl ;
  cout << "Try to launch me with some options" << endl ;
  cout << "(type sample1 --help for the complete list)" << endl ;
  cout << "For example: ./sample1 *.* --funct-opt" << endl ;

  /* let's call our cmdline parser */
  if (cmdline_parser (argc, argv, &args_info) != 0)
    exit(1) ;

  cout << "Here are the options you passed..." << endl;

  for ( unsigned i = 0 ; i < args_info.inputs_num ; ++i )
    cout << "file: " << args_info.inputs[i] << endl ;

  if ( args_info.funct_opt_given )
    cout << "You chose --funct-opt or -F." << endl ;

  if ( args_info.str_opt_given )
    cout << "You inserted " << args_info.str_opt_arg << " for " <<
      "--str-opt option." << endl ;

  if ( args_info.int_opt_given )
    cout << "This is the integer you input: " << 
      args_info.int_opt_arg << "." << endl;

  if (args_info.flag_opt_given)
    cout << "The flag option was given!" << endl;

  cout << "The flag is " << ( args_info.flag_opt_flag ? "on" : "off" ) <<
    "." << endl ;

  cout << args_info.def_opt_arg << "! ";

  cout << "Have a nice day! :-)" << endl ;

  return 0;
}

 

现在你可以编译main.cc和由gengetopt生成的cmdline1.c,然后将它们连接成sample1可执行程序:

gcc  -c  cmdline1.c

g++  -c   main1.cc

g++  -o  sample1.o  main1.o

(这里我们假设getopt_long被包含在标准C库中)。

 

现在我们来测试生成的程序:

 

$ ./sample1 -s "hello" --int-opt 1234
This one is from a C++ program
Try to launch me with some options
(type sample1 --help for the complete list)
For example: ./sample1 *.* --funct-opt
Here are the options you passed...
You inserted hello for --str-opt option.
This is the integer you input: 1234.
The flag is off.
Have a nice day! :-)

 

你也可以在命令行中指定很多文件名(也演示了flag的用法):

$ ./sample1 *.h -i -100 -x
This one is from a C++ program
Try to launch me with some options
(type sample1 --help for the complete list)
For example: ./sample1 *.* --funct-opt
Here are the options you passed...
file: cmdline1.h
file: cmdline2.h
file: cmdline.h
file: getopt.h
This is the integer you input: -100.
The flag is on.
Have a nice day! :-)

 

如果我们试图省略--in-opt(或-i)这个标记为required的选项,我们就会得到一个错误:

$ ./sample1
This one is from a C++ program
Try to launch me with some options
(type sample1 --help for the complete list)
For example: ./sample1 *.* --funct-opt
sample1: `--int-opt' (`-i') option required!

 

如果你很好奇,可以看看生成的C文件。

 

高级特征

选项分组

可以给选项分组;属于同一组的选项是互斥的。如果要使用这个特征,首先需要定义组,然后使用groupoption定义组选项。组选项同标准选项的语法基本相同,区别是不能使用required标志(因为同一组内的选项是互斥的,所以使用这个标志就不合道理了),另外需要指定该选项所属的group。

defgroup  "<group name>"  {yes}

groupoption <long> <short> <desc> <argtype> group="<group name>"

如果组被定义为required(其实使用yes标志标识的),则必须在命令行上出现一个(且只有一个)属于该组的选项。

这儿有一个例子(取自于test_group_cmd.ggo):

defgroup "my grp2"
defgroup "grp1" yes
groupoption "opta" a "string a" group="grp1"
groupoption "optb" b "string b" group="grp1"
groupoption "optc" - "string c" group="my grp2"
groupoption "optd" d "string d" group="my grp2"

组grp1被标记为required,所以必须指定opta、optb二者之一(且不能全选)。输出为:

$ ./test_groups
gengetopt: 0 options of group grp1 were given. One is required
$ ./test_groups -a          OK
$ ./test_groups -a -b
gengetopt: 2 options of group grp1 were given. One is required
$ ./test_groups -a -c       OK
$ ./test_groups -a --optc -d
gengetopt: 2 options of group my grp2 were given. At most one is required

 

配置文件

    通常,将命令行选项放到配置文件里是一个很有用的特性这样,如果某些选项没有在命令行上出现,就可以从文件中获得它们的值。如果调用gengetopt时指定了--conf-parser选项,那么除了标准的命令行解析器之外,还会生成另一个解析器(名为<commandline_parser>_configfile):

int
<cmd_parser_name>_configfile (char * const filename,
                              struct gengetopt_args_info *args_info,
                              int override);

配置文件中以#开始的行是注释,此外的语法如下:

  • <option_name> {<option_val>} 意思是如果给出option_name,并且该选项接受参数,那么其值为option_val
  • 下面给出了一个使用此特征的例子(test_conf_parser):

    /* test_conf_parser.c test */

    /* test all kinds of options and the conf file parser */


    #include <stdlib.h>
    #include <stdio.h>

    #include "test_conf_parser_cmd.h"

    static struct gengetopt_args_info args_info;

    int
    main (int argc, char **argv)
    { 
      if (test_conf_parser_cmd_parser (argc, argv, &args_info) != 0)
        exit(1) ;

      if (test_conf_parser_cmd_parser_configfile
          (args_info.conf_file_arg, &args_info, 1) != 0) // override cmd options
        exit(1);

      printf ("value of required: %s/n", args_info.required_arg);
      printf ("value of string: %s/n", args_info.string_arg);
      printf ("value of no-short: %d/n", args_info.no_short_given);
      printf ("value of int: %d/n", args_info.int_arg);
      printf ("value of float: %f/n", args_info.float_arg);

      return 0;
    }

    如果我们使用配置文件(test_conf.conf)

    # required option
    required "this is a test"
    float 3.14
    no-short
    string another

     

    并这样运行test_conf_parser,结果为:

    ./test_conf_parser -r bar -i 100 --conf-file test_conf.conf
    value of required: this is a test
    value of string: another
    value of no-short: 1
    value of int: 100
    value of float: 3.140000

     

    mutiple选项

        如果一个选项被标记为multiple,则可以在命令行上多次指定此选项。在这种情况下,假定该选项叫做foo,生成foo_given字段就保存该选项出现的次数,而相应的foo_arg字段包含该选项值的数组。

        例如,如果gengetopt文件如下:

    # test options that can be given more than once

    option "string"      s "string option" string no multiple
    option "int"         i "int option" int no multiple

    就会采用如下方式接收命令行选项:

    /* test_multiple.c test */

    /* test options that can be given more than once */


    #include <stdlib.h>
    #include <stdio.h>

    #include "test_multiple_cmd.h"

    static struct gengetopt_args_info args_info;

    int
    main (int argc, char **argv)
    {
      int i = 0;

      if (test_multiple_cmd_parser (argc, argv, &args_info) != 0)
        exit(1) ;

      for (i = 0; i < args_info.string_given; ++i)
        printf ("passed string: %s/n", args_info.string_arg[i]);

      for (i = 0; i < args_info.int_given; ++i)
        printf ("passed int: %d/n", args_info.int_arg[i]);

      return 0;
    }

    如果采用如下方式调用程序:

    ./test_multiple -s "foo" -s "bar" -s "hello" -i 100 -i 200 -s "world"

    输出为:

    passed string: world
    passed string: hello
    passed string: bar
    passed string: foo
    passed int: 200
    passed int: 100

     

    给Windows用户的提醒

        如果你运行Windows,请记住DOS shell不会翻译通配符,因此前面使用'*.h'的例子无法正常运行。

     

    选项

    下面是gengetopt --help的输出:

    $ gengetopt --help
    gengetopt 2.10

    Purpose:
      This program generates a C function that uses getopt_long function
      to parse the command line options, validate them and fill a struct.

    Usage: gengetopt [OPTIONS]...
       -h         --help              Print help and exit
       -V         --version           Print version and exit
       -iSTRING   --input=STRING      input file (default std input)
       -fSTRING   --func-name=STRING  name of generated function (default='cmdline_parser')
       -FSTRING   --file-name=STRING  name of generated file (default='cmdline')
       -l         --long-help         long usage line in help
       -u         --unamed-opts       accept filenames
                  --no-handle-help    do not handle --help|-h automatically
                  --no-handle-version do not handle --version|-V automatically
                  --no-handle-error   do not exit on errors
                  --conf-parser         generate a config file parser

    Maintained by Lorenzo Bettini <[email protected]>
    Report bugs to [email protected]

     

    选项的含义应该说的很清楚了,详细解释一下:

        如果不指定--func-name,则使用cmdline_parser作为默认值。

        如果指定--long-help选项,"Usage"之后会显示所有的选项;如果有很多选项就会比较烦人。

        如果指定--unamed-opts选项,我们就能接收不属于option的参数,在大多数情况下,这意味这我们可以将文件名传递给程序(参见前面sample1 *.h这个例子)。

        如果指定--no-handle-help(--no-handle-version),就不会自动处理命令行选项--help|-h(--version|-V),这样程序员就可以输出其它的信息,而且还可以在随后调用标准的帮助(版本)输出函数,该函数名为<parser-name>_print_help(<parser-name>_print_version),其中<parser-name>是通过--func-name指定的名字或默认的cmdline_parser。

        如果指定--no-handle-error,解析过程中的错误并不会造成程序退出;由于发生错误时解析器函数会返回非0值,程序可以自己打印帮助信息,就想gengetopt的行为那样(试一下!)。

        也许你已经猜到了:gengetopt就是自己用自己生成的函数解析命令行选项的,下面是gengetopt使用的ggo文件:

    purpose "This program generates a C function that uses getopt_long function
    to parse the command line options, validate them and fill a struct."
    option  "input"         i "input file. default std input"  string     no
    option  "func-name"     f "name of generated function"  string default="cmdline_parser" no
    option  "file-name"     F "name of generated file"  string default="cmdline" no
    option  "long-help"     l "long usage line in help" no
    option  "unamed-opts"   u "accept filenames" no
    option  "no-handle-help"   - "do not handle --help|-h automatically" no 
    option  "no-handle-version"   - "do not handle --version|-V automatically" no
    option  "no-handle-error" - "do not exit on errors" no

    gengetopt自己使用的生成命令如下:

    gengetopt --input=cmdline.ggo --no-handle-version --no-handle-help --no-handle-error

    当指定--help|h选线时,gengetopt会调用cmdline_parser_print_help()然后输出报告bug的请求。当指定--version|-V时,gengetopt会调用cmdline_parser_print_version()并输出版权信息。

    如果发生错误,会输出错误消息到屏幕上:

    $ ./gengetopt --zzzz
    ./gengetopt: unrecognized option `--zzzz'
    Run gengetopt --help to see the list of options.

     

     

     

     

     

     

     

     

     

     

     

    你可能感兴趣的:(function,String,File,Integer,input,filenames)