http://blog.csdn.net/uframer/article/details/1297550
GNU Gengetopt 2.10 Usage
需要由gengetopt生成的函数处理的命令行选项在一个文件中指定(该文件的扩展名通常为 .ggo )。文件组织为文本行,格式为:package <packname> version <version> option <long> <short> <desc> <argtype> {default="<default value>"} <required> {multiple} 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.h和 cmdline.c。如果你不喜欢,也可以通过命令行选项指定输出的文件名:
gengetopt < sample1.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; } |
现在你可以编译main1.cc和由gengetopt生成的cmdline1.c,然后将它们连接成sample1可执行程序:
gcc -c cmdline1.c g++ -c main1.cc g++ -o sample1 cmdline1.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! :-)如果我们试图省略 --int-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.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
multiple选项
如果一个选项被标记为 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 <bettini@gnu.org> Report bugs to <bug-gengetopt@gnu.org>选项的含义应该说的很清楚了,详细解释一下:
- 如果不指定--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的行为那样(试一下!)。
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.