15.2.2. Программирование с popt

Для использования popt в программе, мы должны заполнить таблицу опций и вызвать poptGetContext. Функция poptGetContext разбирает опции командной строки и возвращает poptContext, неопределенный тип данных, которые нужно передавать в качестве параметров в разные функции popt. poptContext хранит состояние процедуры разбора. Это позволяет вызывать библиотеку, передавая ее функциям различные и многочисленные наборы аргументов. Каждый набор имеет собственный контекст, благодаря чему все данные можно держать отдельно во избежании смешивания с другими.

Базовый синтаксис poptGetContext:

poptContext poptGetContext (const char * name,

int argc,

const char ** argv,

const struct poptOption * options,

int flags );

Использование функций popt требует включения хэдера popt.h:

#include <popt.h>

Flags должен быть битовой маской, возможные значения перечислены ниже.

Флаг

Значение

POPT_CONTEXT_NO_EXEC

Игнорировать исполняемые расширения

POPT_CONTEXT_KEEP_FIRST

Обрабатывать argv[0] (имя самой команды) как опцию

POPT_CONTEXT_POSIXMEHARDER

Не позволять опциям следовать за аргументами

Когда использование poptContext завершилось, необходимо освободить память вызовом poptFreeContext:

poptContext poptFreeContext(poptContext context);

Также возможно заполнить контекст из установок, записанных в файле, с помощью poptReadConfigFile:

int poptReadConfigFile(poptContext context,

const char * file_name);

15.2.2.1. Заполнение таблицы опций
Программа нуждается в доступе к таблице, которая определяет все возможные опции. Эта "таблица" - массив структур, где каждая структура задает одну опцию. Формат структуры для отдельной опции такой:

struct poptOption {

const char * longName;

char shortName;

int argInfo;

void * arg;

int val;

const char * descrip;

const char * argDescrip;

};

Соответственно, longName определяет длинную форму опции, shortName - короткую, однобуквенную форму. Для того, чтобы задать отсутствие короткой опции, надо поместить в это поле нулевой символ, '\0'. Например, опция --rebuilddb не имеет короткого варианта.

Поле descrip содержит короткое описание опции, argDescrip - типы значений, или NULL, если опция не имеет передаваемых значений.

Поле argInfo содержит флаг, указывающий библиотеке, как обрабатывать данную опцию. По крайней мере, необходимо определить тип опции. Также можно задать специальные флаги обработки. Ниже описываются типы опций.

Тип

Значение

Определяет

POPT_ARG_NONE

0

Данные не передаются в аргументе, это отдельная опция, как -v

POPT_ARG_STRING

1

Аргумент обрабатывается как строка

POPT_ARG_INT

2

Аргумент обрабатывается как целое

POPT_ARG_LONG

3

Аргумент обрабатывается как длинное целое

POPT_ARG_INCLUDE_TABLE

4

Аргумент помещается в таблицу

POPT_ARG_CALLBACK

5

Аргумент помещается в вызывающую функцию

POPT_ARG_INTL_DOMAIN

6

Устанавливает домен перевода

POPT_ARG_VAL

7

Использовать значение из поля val для аргумента

POPT_ARG_FLOAT

8

Аргумент обрабатывается как число с плавающей точкой

POPT_ARG_DOUBLE

9

Аргумент обрабатывается как число с плавающей точкой двойной точности

Используйте эти константы, определенные в popt.h, вместо указывания реальных чисел.

В зависимости от типа определенного в поле argInfo, popt будет интерпретировать неспецифицированное поле указателя arg различными путями. Использование указателя позволяет библиотеке автоматически обновлять переменные программы, базируясь на установках опций командной строки.

Вы можете задать в поле arg значение NULL. В этом случае popt не будет задавать никаких значений.

Тип POPT_ARG_NONE указывает, что опция не имеет значений, как, например, -v.

Если тип аргумента POPT_ARG_NONE, popt установит arg в значение 1, если опция присутствует в командной строке.

15.2.2.2. Обработчики обратного вызова (callback-функции) popt
Тип POPT_ARG_CALLBACK указывает, что в поле arg хранится указатель на callback-функцию, определенную следующим образом:

typedef void (*poptCallbackType) (poptContext con,

enum poptCallbackReason reason,

const struct poptOption * opt,

const char * arg,

const void * data);

Reason будет одним из следующих значений:

enum poptCallbackReason {

POPT_CALLBACK_REASON_PRE = 0,

POPT_CALLBACK_REASON_POST = 1,

POPT_CALLBACK_REASON_OPTION = 2

};

Поле data содержит значение поля descrip из структуры poptOption. В этом поле вы можете установить указатель на какие-то произвольные данные.

Callback-функции удобны, если вы используете вложенные таблицы опций. В этом случае вы можете поместить код обработки для вложенных опций в callback.

15.2.2.3. Специальные флаги таблицы опций
В дополнение ко всему вышеперечисленному, вы можете определить специальные битовые флаги, определяющие расширенную информацию для обработки каждой опции. Сочетание этих флагов с типом значения происходит с использованием логического оператора OR:

* POPT_ARGFLAG_ONEDASH позволяет использовать longName с одним или двумя дефисами, например, -upgrade или --upgrade.

* Для опций типа битовых масок флаги POPT_ARGFLAG_OR, POPT_ARGFLAG_NOR, POPT_ARGFLAG_AND, POPT_ARGFLAG_NAND, и POPT_ARGFLAG_XOR говорят popt применять заданную операцию, то есть соответственно OR, NOR, AND, NAND, или XOR, к значению, если оно установлено. Флаг POPT_ARGFLAG_NOT вначале инвертирует значение.

* Также можно использовать макрос POPT_BIT_SET для установки бита, а POPT_BIT_CLR - для очистки бита.

* Флаг POPT_ARGFLAG_OPTIONAL указывает на то, что значение аргумента опционально.

* Флаг POPT_ARGFLAG_DOC_HIDDEN говорит popt скрыть эту опцию при отображении справочной информации. Другими словами, это опция для внутреннего использования.

* Редко используемый флаг POPT_ARGFLAG_STRIP заставляет popt игнорировать опцию.

* Флаг POPT_ARGFLAG_SHOW_DEFAULT говорит popt показать значение опции, которым она инициализирована по умолчанию, при выводе справочной информации.

15.2.2.4. Магические опции
В программировании RPM разработчики обычно завершают таблицу опций тремя специальными опциями: POPT_AUTOALIAS, POPT_AUTOHELP, и POPT_TABLEEND. Опция POPT_AUTOALIAS определяет таблицу псевдонимов:

#define POPT_AUTOALIAS { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptAliasOptions, \

0, "Options implemented via popt alias/exec:", NULL },

Эта опция ссылается на таблицу poptAliasOptions. Вы можете использовать тип argInfo POPT_ARG_INCLUDE_TABLE для включения другой таблицы опций. Эти опции будут заполнены псевдонимами popt. Кроме того, внутри RPM программ еще одна таблица, rpmcliAllPoptTable, хранит группы опций, общие для всех RPM программ и всех режимов работы rpm.

Опция POPT_AUTOHELP поддерживает стандартную опцию help. Макрос POPT_AUTOHELP автоматически поддерживает использование опций -?, --help, и --usage:

#define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptHelpOptions, \

0, "Help options:", NULL },

Опция POPT_TABLEEND определяет пустую опцию для обозначения конца таблицы. Включение пустой опции в конце - обязательное требование:

#define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL }

15.2.2.5. Разбор опций командной строки
Когда контекст определен, далее нужно обойти параметры командной строки. Для обхода используется poptGetNextOpt:

int poptGetNextOpt(poptContext context);

Если встречаются ошибки, poptGetNextOpt в качестве кода возврата возвращает отрицательный код ошибки. Если при обходе появилась пустая опция (признак конца таблицы опций), возвращается -1. Коды ошибок:

Код

Означает

POPT_ERROR_NOARG

Опция требует аргумента, но он отсутствует

POPT_ERROR_BADOPT

Аргумент не может быть разобран

POPT_ERROR_OPTSTOODEEP

Псевдонимы имеют слишком большой уровень вложенности

POPT_ERROR_BADQUOTE

Начальные и конечные кавычки не заданы

POPT_ERROR_BADNUMBER

Аргумент не может быть приведен к номеру

POPT_ERROR_OVERFLOW

Номер агрумента выходит из диапазона возможных значений

POPT_ERROR_ERRNO

Системный вызов вернул ошибку в errno

15.2.2.6. Обзор опций командной строки
В нормальных обстоятельствах poptGetNextOpt разбирает все опции командной строки и возвращает -1. Если вы нуждаетесь в упрощении, можно задать указатели на переменные, переданные в таблицу опций. Если необходимы некоторые специальные действия при обработке опций, которые не выполняет popt, например, нужно обработать опции с типом POPT_ARG_NONE, тогда poptGetNextOpt возращает однобуквенную опцию.

В этом случае можно вызвать poptGetNextOpt в цикле:

while ((option = poptGetNextOpt(context) ) {

/* Do something... */

}

Внутри цикла мы можем вызвать poptGetOptArg для получения значения аргумента:

char * poptGetOptArg(poptContext context);

Для перезапуска обработки опций используется poptResetContext:

void poptResetContext(poptContext context);

В целом, popt просто ищет аргументы, начинающиеся с черточки -. В большинстве приложений командной строки имеется экстрааргумент в конце команды, например, список файлов. popt не обрабатывает их, но может предоставить возможности такой обработки. Для обхода экстрааргументов вызывается poptGetArg:

char * poptGetArg(poptContext context);

Чтобы получить все экстрааргументы, нужно вызывать функцию до тех пор, пока она не вернет NULL.

Чтобы перейти к следующему аргументу, используют poptPeekArg, при этом не отмечая аргумент, как прошедший обработку:

char * poptPeekArg(poptContext context);

Или же можно получить весь список экстрааргументов путем вызова poptGetArgs:

char ** poptGetArgs(poptContext context);

Далее - Обработка ошибок
Назад - Псевдонимы popt
Содержание