babolo-parser(3) FreeBSD Library Functions Manual babolo-parser(3) NAME babolo_getparm, babolo_freeparm -- Разбирает строку по словам; babolo_testchar, babolo_testword, babolo_goword, babolo_treedump -- Оценка слова по дереву поиска LIBRARY library ``libbabolo-parser'' SYNOPSIS #include #include #include babolo_parm * babolo_getparm(u_int32_t flag, u_char **instring, const u_char *strend, u_char absq); void babolo_freeparm(babolo_parm *parsed); int babolo_openopt(u_int32_t flags, babolo_opt **opt, int argc, char *const *argv, const char *ostr); int babolo_getopt(babolo_opt **opt); char * babolo_getoptarg(babolo_opt **opt, int argn); char * babolo_getarg(babolo_opt **opt); int babolo_closeopt(babolo_opt **opt); u_int32_t babolo_testchar(const babolo_lexor *lext, u_int32_t state, const u_char **next); u_int32_t babolo_weakchar(const babolo_lexor *lext, u_int32_t state); u_int32_t babolo_testword(const babolo_lexor *lext, const u_char *word); u_int32_t babolo_goword(const babolo_lexor *lext, const u_char **word); void babolo_treedump(const babolo_lexor *lext); DESCRIPTION Функция babolo_getparm() предназначена для обработки конфигурационных файлов. Она делит входную строку instring на слова, разделители - любые группы пробелов (в том числе табуляции, концы строк и т.п.) При разборе строки учитываются экранирование обратным слэшем (например, пробелов), одинарные и двойные кавычки, имена переменных окружения в фигурных скоб- ках и без них - как это делает sh(1) со своими параметрами, но в отличие от него, не обрабатываются специальным образом обратные кавычки или угло- вые скобки, не распознаются специальные переменные, а только переменные окружения, не вычисляются выражения. Параметр strend задает комбинацию символов, по которой заканчивается раз- бор строки (это может, например, быть стандартный возврат каретки или комментарий.) Если эта строка имеет нулевую длинну, то концом строки счи- тается нулевой символ. Параметр flag предназначен для изменения поведения парсера. Его биты опи- саны ниже. Параметр absq - символ, который работает в качестве "абсолютной кавычки", то есть кавычка, которая ничем не экранируется. Удобно в качестве такой использовать символ, который не используется в разбираемом тексте, напри- мер, из диапазона \001 .. \005. Используется только если не 0. babolo_freeparm() освобождает память, занятую структурой babolo_parm. babolo_openopt() готовит структуру opt к разбору опций, возможно с пара- метрами. В отличие от getopt(3) разбор параметров рекурсивный и реентера- бельный, отличается так же и стиль взаимодействия с опциями и аргумен- тами. При первом вызове babolo_openopt() opt обязательно должен быть NULL, если opt не NULL, тогда новые параметры встраиваются в предыдущую последовательность параметров в том месте, в котором случился вызов. argc, argv и ostr имеют примерно тот же смысл, что и параметры getopt(3) соответственно. В отличие от getopt(3) поведение управляется флагами flags, эти флаги: #define Bpars_NONU 0x00200000 #define Bpars_ESYM 0x00400000 #define Bpars_EPRM 0x00800000 #define BLIN_VER1 0x01000000 ... Bpars_NONU Если этот флаг установлен, то argv[0] не будет участвовать в разборе опций. Для совместимости с getopt(3) при первом вызове babolo_openopt() должен быть установлен. Bpars_ESYM Если этот флаг установлен, то неуказанные в ostr флаги будут обрабатываться как если бы они были заданы без аргумента. Bpars_EPRM Если этот флаг установлен и у флага, который в ostr отмечен имеющим аргумент аргумент не будет задан, то вместо ошибки при разборе будет выдано в качестве аргумента NULL. Если babolo_openopt() вызывается с уже существующей структурой opt, то параметр ostr может быть NULL, тогда вместо него будет использован ostr из предыдущего вызова babolo_openopt() с тем же opt. Если и там ostr не был задан, то используется ostr от еще более предыдущего вызова и т.д. babolo_getopt() возвращает следующий флаг из структуры opt, возможно, выстроенной не одним вызовом babolo_openopt(). После вызова babolo_getopt() можно вызвать babolo_getoptarg() для получения аргумента текущего флага. Сейчас параметр argn функции babolo_getoptarg() может быть только 0. Функцию babolo_getarg() можно вызывать после того, как babolo_getopt() вернула результат 0, последовательные вызовы babolo_getopt() возвращают последовательно все аргументы из структуры opt, возможно, выстроенной не одним вызовом babolo_openopt(). babolo_closeopt() вызывается только один раз для каждого opt, независимо от того, сколько раз для этого opt вызывалась babolo_openopt(). Появление функций для работы с опциями спровоцировано изменением при вызове скрипта у FreeBSD 6, когда все аргументы интерпретатора в скрипте выдаются одним первым параметром интерпретатора и нет способа определить, откуда этот параметр порожден. Но решение сделано более обшим. В процессе разбора опций можно в любой момент вызвать babolo_openopt(), которая добавит свои argv в месте вызова. Символ `:' в начале строки ostr не обладает специальным значением и обо- значает обычный флаг. Этот символ после символа флага обозначает наличие параметра у флага. Не следует употреблять несколько символов : подряд нигде, кроме как в самом начале этого параметра. Поведение последователь- ности из символов `:', кроме как `::' в начале параметра ostr, не опреде- лено. Символ `-' в строке ostr не имеет специального значения, может иметь или не иметь аргумент (символ `:' после `-'). Однако в строке аргументов опция `-' обрабатывается специальным образом. Аргумент `--' является признаком конца флагов, как отдельный флаг `-' может быть упо- треблен только если он единственный или не первый символ в слове. В пер- вом случае аргумент флага `-' может быть только в следующем слове. Функция babolo_testchar() реализует один переход автомата оценки слов. Параметр lext задает правила для автомата, state является состоянием перед переходом, next ссылается на указатель на символ, который управляет переходом. Состояние автомата - это смещение в массиве lexgraf структуры babolo_lexor в некоторых условных единицах, размер которых зависит от заданного lext. Не все состояния разрешены, список разрешенных состояний определяется lext. Всегда разрешено начальное состояние 0 и результат выполнения babolo_testchar() всегда является либо разрешенным состояни- епм, либо конечным результатом оценки слова. Автомат оценки слов построен на дереве, из каждой вершины которого, если она не терминальная (лист), ведут дуги, помеченные символами, и кроме того из каждой нетерминальной вершины есть непомеченная дуга. state однозначно определяет текущую вершину. В качестве следующей вершины и результата выполнения babolo_testchar() берется та вершина, к которой ведет дуга, помеченная символом next. Если дуга, помеченная таким симво- лом, отсутствует, то переход происходит по непомеченной дуге. При переходе по дуге по умолчанию next может не продвинуться при следую- щих обстоятельствах: · Переход произошел на лист, и Bpars_CEND сброшен. Смысл непродвижения next в этой ситуации состоит в том, что символ, определивший конец предыдущего слова, может быть рассмотрен в качестве первого символа следующего слова. · Переход произошел на нетерминальную вершину, и Bpars_CMID установлен. Смысл непродвижения next в этой ситуации состоит в том, что следующим шагом можно оценить эту же букву из другой вершины. Лист в этом дереве хранит значение (номер) слова, буквы которого направ- ляли проход по дереву до этого листа. Когда в результате примерения babolo_testchar() достигается лист, то зна- чение слова есть побитовая инверсия результата babolo_testchar(), и это значение не является допустимым указателем на вершину дерева разбора. Ес- ли вызвать babolo_testchar() с таким значением в качестве state, то будет возвращен результат ~0, соответствующий значению слова, равному 0. Если установлен Bpars_AABS, то можно построить не только дерево, но и направленный граф с циклами. Средств строить такие графы не вручную в lexor(1) сейчас нет. Подробнее о структуре описания автомата lext нужен текст, но нет его. Функция babolo_weakchar() возвращает вершину, на которую из заданной в state вершины ведет дуга по умолчанию. Функция babolo_testword() производит оценку слова, заданного word по пра- вилам, заданным lext. Для оценки используется babolo_testchar(), которая запускается для символов, заданных в word последовательно до тех пор, пока не будет достигнут лист в lext. Функция babolo_goword() аналогична babolo_testword(), но параметр word ссылается на слово и в процессе выполнения продвигается по нему. Флаг Bpars_CEND влияет на это продвижение. Процедура babolo_treedump() предназначена для распечатки в stderr струк- туры lext в читаемом виде. flag, используемый в качестве параметра или хранимый в соответствующих структурах, управляет поведением процедур. Его биты: #define Bpars_NPRM 0x000000FF #define Bpars_VTLN 0x00000100 #define Bpars_CRLN 0x00000200 #define Bpars_LFLN 0x00000400 #define Bpars_XXLN 0x00000700 #define Bpars_FAST 0x00010000 #define Bpars_FIXB 0x00020000 #define Bpars_NOEN 0x00040000 #define Bpars_NOAL 0x00080000 #define Bpars_FIRM 0x00100000 #define Bpars_NONU 0x00200000 #define Bpars_AABS 0x00200000 #define Bpars_CEND 0x00400000 #define Bpars_CMID 0x00800000 #define BLIN_VER1 0x01000000 #define BLIN_VER2 0x02000000 #define BLIN_VER3 0x04000000 #define BLIN_VER4 0x08000000 Bpars_NPRM если отличен от 0, задает максимальное количество параметров на выходе, при этом в последнем параметре может быть больше одного слова. Максимальное значение - 255. Bpars_VTLN считать символ VT (0x0b) концом строки. Если задан этот флаг, то strend задает слово, обозначающее начало комментария. Оно само и все содержимое строки до символа VT и сам символ VT игнорируется. Bpars_CRLN аналогично предыдущему флагу, но в качестве конца строки используется символ CR (0x0d). Можно употреблять одновре- менно с другими Bpars_XXLN флагами. Bpars_LFLN аналогично предыдущим двум, но для LF (0x0a). Можно употреб- лять одновременно с другими Bpars_XXLN флагами. Символы, помеченные флагами Bpars_XXLN, считаются в члене cntr струк- туры, возвращаемой babolo_getparm(). Bpars_FAST В норме babolo_getparm() сначала производит предварительный просмотр и считает количество и размер слов для выделения памяти ровно нужного размера. С этим флагом предварительного просмотра не производится, память выделяется на 256 слов с общей длиной ARG_MAX символов. Bpars_FIXB указывает, что первое слово должно начинаться с начала строки instring, и если в начале строки пробел или конец строки, то в качестве первого слова в результате разбора будет слово нулевой длинны. Если этот бит не указан, то первое слово может начинаться с любой позиции входной строки. Bpars_NOEN отменяет подстановку переменных окружения, при этом фигурные скобки и знак доллара теряют свой специальный смысл. Bpars_NOAL Не выделяется память для слов, в структуре ссылки даются на слова в исходном тексте, при необходимости слова переписыва- ются. Bpars_FIRM Разбор прекращается, как только найдено заданное количество слов. Bpars_NONU Не добавлять в массив ссылок нулевую ссылку в конец. Bpars_AABS Задает формат правил с абсолютной адресацией. В таком фор- мате возможны циклы и его удобнее программировать вручную, но он может привести к тому, что размер структуры babolo_lexor может оказаться больше, чем при относительной адресации. Bpars_CEND разрешает продвигаться по заданному слову, если не произошло успешного сопоставления символа. Bpars_CMID Не разрешает продвигаться по слову на шаге сравнения, если произошел переход на другую ветвь графа по несопоставлению символа. Опасно зацикливанием, пользоваться с осторожностью. BLIN_VER1 включает печать сообщений в stderr об ошибках. BLIN_VER2 и выше предназначены для отладки. Остальные поля должны быть установлены в 0. Определены так же макрокоманды: kukBpars_NPRM (x) изготавливает битовую маску Bpars_NPRM из количества парамет- ров getBpars_NPRM (a) извлечение значения поля Bpars_NPRM из флагов a setBpars_NPRM (a, x) установка значения x в поле Bpars_NPRM флагов a babolo_freeparm() освобождает память, занятую структурой babolo_parm. RETURN VALUES Результатом выполнения babolo_getparm() является следующая структура: struct babolo_parm { u_int32_t flag; /* Здесь хранятся как заданные при вызове, */ /* так и используемые библиотекой биты */ int argc; /* Количество найденных при разборе слов. */ size_t cntr; /* Количество строки в разобранном тексте */ u_char *(argv[0]); /* Массив разобранных слов */ }; Если при разборе произошла ошибка, в качестве результата возвращается NULL и устанавливается errno. Функция меняет параметр instring так, что бы он указывал на конец разо- бранной строки. babolo_openopt() при успехе возврашает 0 и заполняет или меняет opt. Ес- ли возникла ошибка, то возвращается ненулевое значение и устанавливается errno. babolo_getopt() при успехе возврашает флаг, если есть невыданные флаги в opt или 0, если все флаги кончились. При ошибке возврашает -1 и устанав- ливает errno. babolo_getoptarg() возврашает аргумент последнего выданного babolo_getopt() флага, если есть, или NULL, если аргумента у флага нет или возникла ошибка. При ошибке устанавливается errno. Если аргумент запрошен у флага, который не описан при вызове babolo_openopt() как имею- щий аргумент, то возвращается NULL и errno не выставляется. Аналогично не выставляется errno, если флаг описан как имеющий аргумент, но аргумент отсутствует и при вызове babolo_openopt() в flags выставлен бит Bpars_EPRM. babolo_getarg() после окончания флагов возвращает ссылку на очередной аргумент, если есть, или NULL. При возникновении ошибки возвращается NULL и устанавливается errno. babolo_closeopt() при успехе возвращает 0. Если возникла ошибка, то воз- вращается ненулевое значение и устанавливается errno. Функция babolo_testchar() возвращает значение, которое может быть следую- щим состоянием, если это значение от 0 до szt включительно, или инверсию от результата оценки слова, если результат не в допустимом для заданного lext диапазоне. Функция babolo_testword() возвращает результат оценки слова. Функция babolo_goword() в дополнение к возвращаемой оценке слова продви- гает указатель по входному слову. ERRORS babolo_getparm() устанавливает при ошибках errno: [EFAULT] Отсутствует указатель на строку в instring или strend. [ENOMEM] не выделено достаточно памяти. [E2BIG] выходной список аргументов не помещается в ARG_MAX памяти. [EINVAL] синтаксическая ошибка при разборе строки. babolo_openopt() устанавливает при ошибках errno: [EFAULT] Один из параметров NULL в контексте, где нужна дей- ствительная ссылка. [ENOMEM] не выделено достаточно памяти. [EINVAL] В первом для opt вызове не указана строка ostr. Кроме того, при достаточно высоком уровне отладочного вывода возможны ошибки от функций warnx(3) и fprintf(3) (если возможны). babolo_closeopt(), babolo_getoptarg() и babolo_getarg() устанавливают при ошибках errno: [EFAULT] Один из параметров NULL в контексте, где нужна дей- ствительная ссылка. babolo_getopt() устанавливает при ошибках errno: [EFAULT] Один из параметров NULL в контексте, где нужна дей- ствительная ссылка. [EINVAL] найденный флаг не указан в ostr и не установлен бит Bpars_ESYM. [ENOENT] для флага в ostr указано наличие аргумента, но аргу- мент не найден и бит Bpars_EPRM не установлен. Кроме того, при достаточно высоком уровне отладочного вывода у функций babolo_openopt(), babolo_closeopt(), babolo_getopt(), babolo_getoptarg() и babolo_getarg() возможны ошибки от функций warnx(3) и fprintf(3) (если возможны). Функции babolo_testchar(), babolo_testword(), babolo_goword() ошибок не возвращают. Надо заботиться о том, что бы lext обеспечивал правильный возврат на всем множестве возможных входных слов. Процедура babolo_treedump() сообщает об ошибках в stderr. SEE ALSO sh(1), lexor(1), getopt(3). AUTHOR Aleksandr A. Babaylov (aka @BABOLO) .@babolo.ru http://www.babolo.ru/ BUGS Не определена реакция babolo_getopt() на входные слова вида `--<чтонибудь еще>' (long options). Параметр lext по сути является программой, которую в общем случае надо писать в кодах. lexor предназначен для составления таких программ, но не все возможности автомата он может использовать. Так же надо обращать специальное внимание на остановку просмотра слова вовремя, например, по символу 0, если он используется для ограничения слова. Документация ни к черту. 25 January 2004