104 {"ignore-environment", no_argument, NULL, 'i'},
105 {"unset", required_argument, NULL, 'u'},
106 {GETOPT_HELP_OPTION_DECL},
107 {GETOPT_VERSION_OPTION_DECL},
108 {NULL, 0, NULL, 0}
109 };
GNU Coreutils содержит большое число программ, многие из которых выполняют одни и те же общие задачи (например, анализ аргументов). Для облегчения сопровождения многие типичные идиомы были определены в виде макросов. Двумя таким макросами являются
GETOPT_HELP_OPTION_DECL
и
GETOPT_VERSION_OPTION
(строки 106 и 107). Вскоре мы рассмотрим их определения. Первая функция,
usage()
, выводит информацию об использовании и завершает программу. Макрос
_("string")
(строка 115, используется также по всей программе) также предназначен для локализации, пока также считайте его содержащим строковую константу.
111 void
112 usage(int status)
113 {
114 if (status '= 0)
115 fprintf(stderr, _("Try '%s --help' for more information.n"),
116 program_name);
117 else
118 {
119 printf (_("
120 Usage: %s [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]n"),
121 program_name);
122 fputs (_("
123 Set each NAME to VALUE in the environment and run COMMAND. n
124 n
125 -i, --ignore-environment start with an empty environmentn
126 -u, --unset=NAME remove variable from the environmentn
127 "), stdout);
128 fputs(HELP_OPTION_DESCRIPTION, stdout);
129 fputs(VERSION_OPTION_DESCRIPTION, stdout);
130 fputs(_("
131 n
132 A mere - implies -i. If no COMMAND, print the resulting
133 environment.n"), stdout);
134 printf(_("nReport bugs to <%s>.n"), PACKAGE_BUGREPORT);
135 }
136 exit(status);
137 }
Первая часть
main()
объявляет переменные и настраивает локализацию. Функции
setlocale()
,
bindtextdomain()
и
textdomain()
(строки 147–149) обсуждаются в главе 13 «Интернационализация и локализация». Отметим, что эта программа использует аргумент
main() envp
(строка 140). Это единственная программа Coreutils, которая так делает. Наконец, вызов
atexit()
в строке 151 (см. раздел 9.1.5.3. «Функции завершения») регистрирует библиотечную функцию Coreutils, которая очищает все выходные буферы и закрывает
stdout
, выдавая сообщение при ошибке. Следующая часть программы обрабатывает аргументы командной строки, используя
getopt_long()
.
139 int
140 main(register int argc, register char **argv, char **envp)
141 {
142 char *dummy_environ[1];
143 int optc;
144 int ignore_environment = 0;
145
146 program_name = argv[0];
147 setlocale(LC_ALL, "");
148 bindtextdomain(PACKAGE, LOCALEDIR);
149 textdomain(PACKAGE);
150
151 atexit(close_stdout);
152
153 while ((optc = getopt_long(argc, argv, "+iu:", longopts, NULL)) != -1)
154 {
155 switch (optc)
156 {
157 case 0:
158 break;
159 case 'i':
160 ignore_environment = 1;
161 break;
162 case 'u':
163 break;
164 case_GETOPT_HELP_CHAR;
165 case_GETOPT_VERSION_CHAR(PROGRAM_NAME, AUTHORS);
166 default:
167 usage(2);
168 }
169 }
170
171 if (optind != argc && !strcmp(argv[optind], "-"))
172 ignore_environment = 1;
Вот отрывок из файла
src/sys2.h
в дистрибутиве Coreutils с упомянутыми ранее определениями и макросом '
case_GETOPT_xxx
', использованным выше (строки 164–165):
/* Вынесение за скобки общей части кода, обрабатывающего --help и
--version. */
/* Эти значения перечисления никак не могут конфликтовать со значениями опций,
обычно используемыми командами, включая CHAR_MAX + 1 и т.д. Избегайте
CHAR_MIN - 1, т.к. оно может равняться -1, значение завершения опций getopt.
*/
enum {
GETOPT_HELP_CHAR = (CHAR_MIN — 2),
GETOPT_VERSION_CHAR = (CHAR_MIN - 3)
};