GNU hello代码分析
2015-11-10 15:32
218 查看
GNU中的一个软件包,包名叫hello,呵呵,看来很简单啦。
今天就来分析一下,GNU的目的是通过这个说明一下,GNU标准软件包所应遵守的规则,以及一些必须的测试,编译脚本文件等。
俺就不分析其他的了,直接上最具价值的代码,其他忽略,这个程序实在是太小了,最重要的是一个getopt_long函数的应用,
用于解析命令行参数的。
#include <config.h>
#include "system.h"
#include "errno.h"
#include "error.h"
#include "progname.h"
#include "xalloc.h"
static const struct option longopts[] = {
{"greeting", required_argument, NULL, 'g'}, 需要参数
{"help", no_argument, NULL, 'h'}, 不需要参数
{"traditional", no_argument, NULL, 't'},
{"version", no_argument, NULL, 'v'},
{NULL, 0, NULL, 0} 通过man getopt_long发现,这个结构体需要以NULL结束。
};
/* Forward declarations. */ 前向声明,估计调用在实现之前。
static void print_help (void);
static void print_version (void);
int
main (int argc, char *argv[]) 关键的入口函数在这里啦。
{
int optc;
int lose = 0;
const char *greeting_msg;
wchar_t *mb_greeting;
size_t len;
set_program_name (argv[0]);
/* Set locale via LC_ALL. */
setlocale (LC_ALL, "");
#if ENABLE_NLS
/* Set the text message domain. */
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
#endif
/* Having initialized gettext, get the default message. */
greeting_msg = _("Hello, world!"); 常指针指向一个字符串常量,C语言中有_()这个用法吗?难道是GNU的扩展???
/* Even exiting has subtleties. On exit, if any writes failed, change
the exit status. The /dev/full device on GNU/Linux can be used for
testing; for instance, hello >/dev/full should exit unsuccessfully.
This is implemented in the Gnulib module "closeout". */
atexit (close_stdout);
这个函数用于处理命令行参数,字符后面跟一个冒号表示需要一个参数。
该函数返回短命令符,下面的程序通过case判断。
while ((optc = getopt_long (argc, argv, "g:htv", longopts, NULL)) != -1)
switch (optc)
{
/* --help and --version exit immediately, per GNU coding standards. */
case 'v':
print_version ();
exit (EXIT_SUCCESS);
break;
case 'g':
greeting_msg = optarg; // extern char *optarg;一个全局变量,getopt用它来保存参数
break;
case 'h':
print_help ();
exit (EXIT_SUCCESS);
break;
case 't':
greeting_msg = _("hello, world");
break;
default:
lose = 1;
break;
}
if (lose || optind < argc)
{
/* Print error message and exit. */
error (0, 0, "%s: %s", _("extra operand"), argv[optind]);
print_help ();
}
len = mbsrtowcs(NULL, &greeting_msg, 0, NULL);
if (len == (size_t)-1)
error (EXIT_FAILURE, errno, _("conversion to a multibyte string failed"));
mb_greeting = xmalloc((len + 1) * sizeof(wchar_t));
mbsrtowcs(mb_greeting, &greeting_msg, len + 1, NULL);
/* Print greeting message and exit. */
wprintf (L"%ls\n", mb_greeting);
free(mb_greeting);
exit (EXIT_SUCCESS);
}
/* Print help info. This long message is split into
several pieces to help translators be able to align different
blocks and identify the various pieces. */
static void
print_help (void)
{
/* TRANSLATORS: --help output 1 (synopsis)
no-wrap */
printf (_("\
Usage: %s [OPTION]...\n"), program_name);
/* TRANSLATORS: --help output 2 (brief description)
no-wrap */
fputs (_("\
Print a friendly, customizable greeting.\n"), stdout);
puts ("");
/* TRANSLATORS: --help output 3: options 1/2
no-wrap */
fputs (_("\
-h, --help display this help and exit\n\
-v, --version display version information and exit\n"), stdout);
puts ("");
/* TRANSLATORS: --help output 4: options 2/2
no-wrap */
fputs (_("\
-t, --traditional use traditional greeting\n\
-g, --greeting=TEXT use TEXT as the greeting message\n"), stdout);
printf ("\n");
/* TRANSLATORS: --help output 5+ (reports)
TRANSLATORS: the placeholder indicates the bug-reporting address
for this application. Please add _another line_ with the
address for translation bugs.
no-wrap */
printf (_("\
Report bugs to: %s\n"), PACKAGE_BUGREPORT);
#ifdef PACKAGE_PACKAGER_BUG_REPORTS
printf (_("Report %s bugs to: %s\n"), PACKAGE_PACKAGER,
PACKAGE_PACKAGER_BUG_REPORTS);
#endif
#ifdef PACKAGE_URL
printf (_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
#else
printf (_("%s home page: <http://www.gnu.org/software/%s/>\n"),
PACKAGE_NAME, PACKAGE);
#endif
fputs (_("General help using GNU software: <http://www.gnu.org/gethelp/>\n"),
stdout);
}
/* Print version and copyright information. */
static void
print_version (void)
{
printf ("%s (%s) %s\n", PACKAGE, PACKAGE_NAME, VERSION);
/* xgettext: no-wrap */
puts ("");
/* It is important to separate the year from the rest of the message,
as done here, to avoid having to retranslate the message when a new
year comes around. */
printf (_("\
Copyright (C) %d Free Software Foundation, Inc.\n\
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
This is free software: you are free to change and redistribute it.\n\
There is NO WARRANTY, to the extent permitted by law.\n"), COPYRIGHT_YEAR);
}
今天就来分析一下,GNU的目的是通过这个说明一下,GNU标准软件包所应遵守的规则,以及一些必须的测试,编译脚本文件等。
俺就不分析其他的了,直接上最具价值的代码,其他忽略,这个程序实在是太小了,最重要的是一个getopt_long函数的应用,
用于解析命令行参数的。
#include <config.h>
#include "system.h"
#include "errno.h"
#include "error.h"
#include "progname.h"
#include "xalloc.h"
static const struct option longopts[] = {
{"greeting", required_argument, NULL, 'g'}, 需要参数
{"help", no_argument, NULL, 'h'}, 不需要参数
{"traditional", no_argument, NULL, 't'},
{"version", no_argument, NULL, 'v'},
{NULL, 0, NULL, 0} 通过man getopt_long发现,这个结构体需要以NULL结束。
};
/* Forward declarations. */ 前向声明,估计调用在实现之前。
static void print_help (void);
static void print_version (void);
int
main (int argc, char *argv[]) 关键的入口函数在这里啦。
{
int optc;
int lose = 0;
const char *greeting_msg;
wchar_t *mb_greeting;
size_t len;
set_program_name (argv[0]);
/* Set locale via LC_ALL. */
setlocale (LC_ALL, "");
#if ENABLE_NLS
/* Set the text message domain. */
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
#endif
/* Having initialized gettext, get the default message. */
greeting_msg = _("Hello, world!"); 常指针指向一个字符串常量,C语言中有_()这个用法吗?难道是GNU的扩展???
/* Even exiting has subtleties. On exit, if any writes failed, change
the exit status. The /dev/full device on GNU/Linux can be used for
testing; for instance, hello >/dev/full should exit unsuccessfully.
This is implemented in the Gnulib module "closeout". */
atexit (close_stdout);
这个函数用于处理命令行参数,字符后面跟一个冒号表示需要一个参数。
该函数返回短命令符,下面的程序通过case判断。
while ((optc = getopt_long (argc, argv, "g:htv", longopts, NULL)) != -1)
switch (optc)
{
/* --help and --version exit immediately, per GNU coding standards. */
case 'v':
print_version ();
exit (EXIT_SUCCESS);
break;
case 'g':
greeting_msg = optarg; // extern char *optarg;一个全局变量,getopt用它来保存参数
break;
case 'h':
print_help ();
exit (EXIT_SUCCESS);
break;
case 't':
greeting_msg = _("hello, world");
break;
default:
lose = 1;
break;
}
if (lose || optind < argc)
{
/* Print error message and exit. */
error (0, 0, "%s: %s", _("extra operand"), argv[optind]);
print_help ();
}
len = mbsrtowcs(NULL, &greeting_msg, 0, NULL);
if (len == (size_t)-1)
error (EXIT_FAILURE, errno, _("conversion to a multibyte string failed"));
mb_greeting = xmalloc((len + 1) * sizeof(wchar_t));
mbsrtowcs(mb_greeting, &greeting_msg, len + 1, NULL);
/* Print greeting message and exit. */
wprintf (L"%ls\n", mb_greeting);
free(mb_greeting);
exit (EXIT_SUCCESS);
}
/* Print help info. This long message is split into
several pieces to help translators be able to align different
blocks and identify the various pieces. */
static void
print_help (void)
{
/* TRANSLATORS: --help output 1 (synopsis)
no-wrap */
printf (_("\
Usage: %s [OPTION]...\n"), program_name);
/* TRANSLATORS: --help output 2 (brief description)
no-wrap */
fputs (_("\
Print a friendly, customizable greeting.\n"), stdout);
puts ("");
/* TRANSLATORS: --help output 3: options 1/2
no-wrap */
fputs (_("\
-h, --help display this help and exit\n\
-v, --version display version information and exit\n"), stdout);
puts ("");
/* TRANSLATORS: --help output 4: options 2/2
no-wrap */
fputs (_("\
-t, --traditional use traditional greeting\n\
-g, --greeting=TEXT use TEXT as the greeting message\n"), stdout);
printf ("\n");
/* TRANSLATORS: --help output 5+ (reports)
TRANSLATORS: the placeholder indicates the bug-reporting address
for this application. Please add _another line_ with the
address for translation bugs.
no-wrap */
printf (_("\
Report bugs to: %s\n"), PACKAGE_BUGREPORT);
#ifdef PACKAGE_PACKAGER_BUG_REPORTS
printf (_("Report %s bugs to: %s\n"), PACKAGE_PACKAGER,
PACKAGE_PACKAGER_BUG_REPORTS);
#endif
#ifdef PACKAGE_URL
printf (_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
#else
printf (_("%s home page: <http://www.gnu.org/software/%s/>\n"),
PACKAGE_NAME, PACKAGE);
#endif
fputs (_("General help using GNU software: <http://www.gnu.org/gethelp/>\n"),
stdout);
}
/* Print version and copyright information. */
static void
print_version (void)
{
printf ("%s (%s) %s\n", PACKAGE, PACKAGE_NAME, VERSION);
/* xgettext: no-wrap */
puts ("");
/* It is important to separate the year from the rest of the message,
as done here, to avoid having to retranslate the message when a new
year comes around. */
printf (_("\
Copyright (C) %d Free Software Foundation, Inc.\n\
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
This is free software: you are free to change and redistribute it.\n\
There is NO WARRANTY, to the extent permitted by law.\n"), COPYRIGHT_YEAR);
}
相关文章推荐
- c++(快速排序)
- C#调用非托管DLL时遇到“找不到指定的模块”问题解决方法
- c++(非递归排序)
- java 入门 第二季4
- c++(查找)
- VS2013+qt-vs-addin-1.2.4安装配置
- 主activity报空指针异常java.lang.RuntimeException: Unable to resume activity
- c++(递归和堆栈)
- 二分查找(两行代码)
- Spring3中的@value注解
- laravel 获得url 参数
- Openstack python api 学习文档 api创建虚拟机
- spring <context:component-scan>使用说明
- c#调用dll获取dll物理路径的方法
- c++2(循环和递归)
- C++primer第五版第六章学习笔记
- java项目jsp中如何引用本地路径图片
- C# Windows Media Player操作
- spring mvc控制器问题
- c++1