Вы совершенно правы, что справочная страница скрывает эти подробности, но из исходного кода можно почерпнуть достаточно подсказок, например, реализацию glibc в glibc-xyz / posix / getopt.c _getopt_internal_r
.(Возможно, это единственная интересная реализация этой функции расширения GNU?)
Этот код устанавливает optopt
в 0, когда встречается с ошибочной длинной опцией, которая, я думаю, полезна, чтобы отличать этот случай от ошибочной короткой опции, когда optopt
, безусловно, будет не NUL.
Сообщения об ошибках, генерируемые, когда opterr != 0
в основном выводят ошибочную длинную опцию как argv[optind]
, и более поздний код (всегда или - консервативно - впо меньшей мере, в основном) позже optind
перед возвратом.
Поэтому рассмотрим эту программу:
#include <getopt.h>
#include <stdio.h>
int main(int argc, char **argv) {
struct option longopts[] = {
{ "foo", no_argument, NULL, 'F' },
{ NULL, 0, NULL, 0 }
};
int c;
do {
int curind = optind;
c = getopt_long(argc, argv, "f", longopts, NULL);
switch (c) {
case 'f': printf("-f\n"); break;
case 'F': printf("--foo\n"); break;
case '?':
if (optopt) printf("bad short opt '%c'\n", optopt);
else printf("bad long opt \"%s\"\n", argv[curind]);
break;
case -1:
break;
default:
printf("returned %d\n", c);
break;
}
} while (c != -1);
return 0;
}
$ ./longopt -f -x --bar --foo
-f
./longopt: недопустимый параметр - 'x'
плохая короткая опция 'x'
./longopt: нераспознанная опция '--bar'
плохая длинная опция "--bar"
--foo
Таким образом, в этих случаях, кэшируя значение до getopt_long
optind
, мы легко можем распечатать те же плохие опции, что и opterr
messages.
Это может быть не совсем правильно во всех случаях, так как реализация glibc используетего собственная __nextchar
, а не argv[optind]
(в случае «нераспознанного варианта») заслуживает изучения, но этого должно быть достаточно, чтобы начать работу.
Если вы тщательно обдумаете связь между optind
иповторные вызовы getopt_long
, я думаю, распечатка argv[cached_optind]
будет довольно безопасной.optopt
существует, потому что для коротких опций вам нужно знать, какой именно символ в слове является проблемой, но для длинных опций проблема заключается в целом текущем слове (по модулю отбрасывая аргументы опций вида =param
).И текущее слово - это то, на которое getopt_long
смотрит с (входящим) значением optind
.
В отсутствие гарантии, написанной в документации, я был бы несколько менее оптимистичен в отношении использования преимуществаoptopt = 0
поведения, хотя.