НАЗВАНИЕ
regexp - функции для компиляции и сопоставления регу лярных выражений
СИНТАКСИС
#define INIT описания #define GETC( ) реализация_GETC #define PEEKC( ) реализация_PEEKC #define UNGETC(c) реализация_UNGETC #define RETURN(p) реализация_RETURN #define ERROR(v) реализация_ERROR #include <regexp.h> char *compile (instring, expbuf, endbuf, eof) char *instring, *expbuf, *endbuf; int eof; int step (string, expbuf) char *string, *expbuf; extern char *loc1, *loc2, *locs; extern int circf, sed, nbra;
ОПИСАНИЕ
В данной статье описываются универсальные функции сопоставления регулярных выражений в форме ed(1), определенные во включаемом файле <regexp.h>. Этот исходный
файл используется такими программами, как ed(1),
sed(1), grep(1), bs(1) и expr(1), которые выполняют сопоставление регулярных выражений. Тем самым обеспечивается согласованная трактовка регулярных выражений.
У этого файла неприятный интерфейс. Программы, которые включают данный файл, перед оператором #include <regexp.h> должны содержать определение пяти макросов, перечисленных ниже. Макросы используются функцией compile.
Код | Толкование |
---|---|
11 | Верхняя граница диапазона слишком велика. |
16 | Некорректное число. |
25 | "\цифра" вне диапазона. |
36 | Некорректный или отсутствующий разделитель. |
41 | Нет запомненной цепочки символов для поиска. |
42 | Не сбалансированы скобки \( и \). |
43 | Слишком много открывающих скобок \(. |
44 | В скобках \{ \} указано больше двух чисел. |
45 | Фигурная скобка } ожидалась после \. |
46 | В скобках \{ \} первое число больше второго. |
49 | Не сбалансированы скобки [ и ]. |
50 | Переполнение регулярного выражения. |
compile (instring, expbuf, endbuf, eof)
Первый аргумент instring никогда не используется функцией compile явно, но бывает удобен для программ, которые передают различные указатели на входные символы. Иногда он используется в описаниях INIT (см. ниже). Программы, которые получают символы посредством вызовов функций или хранят их во внешнем массиве, могут передавать в качестве этого аргумента значение ((char *) 0).
Аргумент expbuf - указатель на символ. Он определяет позицию, начиная с которой должно быть размещено скомпилированное регулярное выражение.
Аргумент endbuf на единицу превосходит максимальную позицию, в которой может быть размещено регулярное выражение. Если скомпилированное выражение не умещается в (endbuf-expbuf) байт, выполняется вызов ERROR (50).
Аргумент eof - это символ, который отмечает конец регулярного выражения. Например, в ed(1) этим символом обычно является /.
В каждой программе, которая включает файл <regexp.h>, должен быть оператор #define для имени INIT. Заданные в нем описания будут размещены в самом начале функции compile. Чаще всего макрос INIT служит для того, чтобы установить регистровую переменную на начало регулярного выражения с целью последующего использования в GETC, PEEKC и UNGETC. Кроме того, в INIT можно описать внешние переменные, используемые макросами GETC, PEEKC и UNGETC. См. ниже пример описаний, взятый из grep(1).
В файле <regexp.h> есть и другие функции, которые фактически выполняют сопоставление регулярных выражений; одна из них - функция step. Обращение к ней выглядит так:
step (string, expbuf)
Первый аргумент функции step - указатель на цепочку символов, для которой надо проверить возможность сопоставления. Эта цепочка должна быть ограничена нулевым байтом.
Второй аргумент, expbuf, - скомпилированное регулярное выражение, полученное при помощи функции compile.
Функция step возвращает ненулевое значение, если данная цепочка сопоставляется с регулярным выражением, и 0 в противном случае. Если сопоставление имеет место, побочный эффект функции step заключается в установке двух внешних указателей. Переменная loc1, устанавливаемая функцией step, является указателем на первый сопоставленный символ. Переменная loc2, которая устанавливается функцией advance, указывает на символ, следующий за последним сопоставленным символом. Таким образом, если с регулярным выражением сопоставилась вся цепочка, то loc1 будет указывать на первый символ string, а loc2 - на нулевой байт в конце string.
Функция step использует внешнюю переменную circf. Compile присваивает этой переменной ненулевое значение, если регулярное выражение начинается с ^; в таком случае step будет пытаться выполнять сопоставление только с начала цепочки символов. Если до первой попытки сопоставления откомпилировано более одного регулярного выражения, следует сохранить для каждого скомпилированного выражения значение circf и восстанавливать значение этой переменной перед каждым вызовом step.
Функция advance вызывается из step с теми же аргументами, что и step. Задача функции step - передвигать указатель string на символ вперед и вызывать advance; step выполняется до тех пор, пока либо advance не возвратит ненулевое значение, что обозначает сопоставление, либо не будет достигнут конец string. Если хотят в любом случае ограничиться сопоставлением с начала цепочки string, step не вызывают, а просто используют advance.
Если функция advance встречает в регулярном выражении * или последовательность \{ \}, она, выполняя сопоставление, продвигает указатель на цепочку символов, насколько это возможно, и рекурсивно вызывает сама себя, пытаясь сопоставить остаток цепочки с остатком регулярного выражения. Если при этом сопоставление не выполнится, advance будет возвращаться вдоль цепочки, пока не обнаружит сопоставления либо не вернется к позиции в цепочке символов, с которой первоначально было сопоставлено * или \{ \}. Иногда желательно остановить этот возврат назад до того, как будет достигнуто начало цепочки. Если locs - внешний указатель на символ - в некоторый момент процесса возврата станет равен позиции в цепочке символов, advance прервет цикл возврата и завершится с результатом 0. Эта возможность используется программами ed(1) и sed(1) при выполнении глобальной подстановки (то есть не для первого вхождения, а для всей цепочки); например, при обработке выражений типа /y*//g не возникнет бесконечного цикла.
ПРИМЕР
Следующий пример показывает, как выглядят предназначенные для работы с регулярными выражениями макросы и
функции, которые используются в grep(1):
#define INIT register char *sp = instring; #define GETC() (*sp++) #define PEEKC() (*sp) #define UNGETC(c) (--sp) #define RETURN(c) return; #define ERROR(c) regerr() #include <regexp.h> ... (void) compile (*argv, expbuf, &expbuf[ESIZE], '\0'); ... if (step(linebuf, expbuf)) succeed();
СМ. ТАКЖЕ
ed(1), expr(1), grep(1), sed(1) в Справочнике пользователя.
Существуют другие типы ссылок для иных процессоров. Одинаковые типы ссылок на разных процессорах имеют одинаковые номера и смысл. Если возникнет необходимость в новых типах ссылок, то можно будет их добавить с новыми номерами.
Элементы, содержащие информацию о настройке, создаются ассемблером и используются редактором связей автоматически. Опции редактора связей позволяют как сохранять, так и удалять эту информацию из выходных файлов.
СМ. ТАКЖЕ
a.out(4), syms(4).
as(1), ld(1) в Справочнике пользователя.