本文共 4515 字,大约阅读时间需要 15 分钟。
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); }转载地址:http://jczji.baihongyu.com/