您的位置:首页 > 编程语言

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);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: