C.1 Команды

Предыдущая  Содержание  Следующая V*D*V

munch — создание списка классов

 

nm -p объект... архив... | munch

 

munch читает листинг в стиле Berkeley nm (1) из потока стандартного ввода и создаёт исходный файл C в виде потока стандартный вывода, определяя завершённый нулём массив classes[] с указателями на функции классов, найденные в каждом объекте и архиве. Этот массив отсортирован по именам функций классов.

Функция класса — любое имя, которое появляется с типом T и предшествующим подчёркиванием, с типом b, d или s.

Это приём для упрощения программы извлечения данных. Совместимый эффект опции -p в Berkeley и System V nm является приятным сюрпризом.

Поскольку nm на HP/UX не выводит статические символы, munch не очень удобен на этой системе.

ooc — препроцессор для объекто-ориентированного кодирования на ANSI C

ooc [опция ...] [report ...] description target ...

 

ooc это программа awk, которая читает описания классов и выполняет задачи кодирования подпрограмм, необходимых для объектно-ориентированное кодирование на ANSI C. Кодом, генерируемым ooc, управляют отчёты, которые могут быть изменены. Эта страница руководства описывает результаты создания стандартных отчётов.

description представляет собой имя класса. ooc загружает файл описания класса с именем description.d и рекурсивно файлы описания класса для всех суперклассов вплоть до корневого класса. Если в качестве target указаны -h или -r, в поток стандартного вывода записывается заголовочный файл C для открытого интерфейса или закрытого представления описания. Если в качестве target определены source.dc или -,  в поток стандартного вывода записываются операторы #include для заголовочных файлов description и source.dc, или читается поток стандартного ввод, производится предварительная обработка и копирование в поток стандартного вывода. Если в качестве target указан -dc, в поток стандартного вывода записывается исходник скелета для description, который содержит все возможные методы.

Вывод создаётся генерацией отчёта из файлов стандартных отчётов. Если в качестве report определён file.rep, стандартные файлы не загружаются.

 

Здесь приведены некоторые глобальные опции для управления ooc:

 

-Dname[=value]
определяет value или пустую строку для замены `name. name должно быть в одно слово. ooc заранее определяет GNUC со значением 0.

 

-d
организует отладку после нормальной обработки. Команды отладки читаются из потока стандартного ввода: class.d загружает файл описания класса; report.rep загружает файл отчёта; описание, отчёт, класс или имя метода создают вывод с соответствующей информацией; а all, classes, descriptions или reports выводят всю информацию в соответствующей категории.

 

-l
создаёт штампы #line в соответствии с указаниями отчётов.

 

-M
создаёт строку зависимости для makefile для каждого описания description и его файлов описаний суперклассов.

 

-R
необходимо указывать при обработке корневого класса. В этом случае загружаются другие стандартные отчёты.

Лексические соглашения

Все входные строки обрабатываются следующим образом: сначала удаляется комментарий; затем склеиваются строки, заканчивающиеся обратной наклонной чертой; в конце удаляются завершающие пробелы.

Комментарий продолжается от // до конца строки. Он удаляется вместе с предыдущими пробелами до склейки.

При склеивании обратная наклонная черта отмечает точку контакта и удаляется. Все пробелы вокруг точки контакта заменяются одинарным пробелом.

Идентификаторы, значимые для ooc, следуют соглашениям C, за исключением того, что они не могут использовать символы подчёркивания. Подчеркивание используется, чтобы избежать конфликтов между кодом ooc и кодом пользователя.

Операторы деклараций, значимые для ooc, упрощены относительно C. Они могут начинаться с const и информация о типе должна предшествовать имени. Информация о типе может использовать *, но без круглых скобок. В целом, произвольный оператор объявления может быть адаптирован для ooc через применение для имени типа определения typedef.

Строка, начинающаяся с %%, действует как конец файла.

Файл описания класса

Файл описания класса имеет следующий формат:

 

заголовок

% meta class {

  компоненты

%

  методы со статической компоновкой

%-

  методы с динамической компоновкой

%+

  методы класса

%}

...

 

заголовок — произвольная информация, которая копируется в поток стандартного вывода, если создаётся файл интерфейса. Информация после %prot копируется в поток стандартного вывода, если создаётся файл представления.

компоненты — декларации компонентов структуры C с одним оператором объявления на строку. Они копируются в struct, сгенерированную в файле представления для класса. Они также определяют порядок параметров конструктора для корневого метакласса.

Первый набор методов использует статическую компоновку, то есть они представляют собой функции с по крайней мере одним объектом в качестве параметра; второй набор использует динамическую компоновку и в качестве параметра имеет объект, для которого выбран метод; третий набор — методы класса, то есть у них в качестве параметра есть класс, для которого выбран метод. Объект выбора всегда называется self. Декларации методов определяются заголовками функций C, селекторами и информацию для конструктора метакласса.

Строка заголовка класса % meta class { имеет одну из трёх форм. Первая форма используется, чтобы представить только корневой класс:

 

% meta class {
class — корневой класс, на что указывает тот факт, что у него нет суперкласса. Позже определённый суперкласс будет корневым классом самого себя. Представлен позже meta должен быть корневым метаклассом, на что указывает тот факт, что он имеет самого себя в качестве метакласса.

 

% meta class: super {
class — новый класс с meta в качестве его метакласса и super в качестве его суперкласса. Это также использовалось бы, чтобы представить корневой метакласс, который имеет себя самого как метакласс и корневой класс как суперкласс. Если super не определён, то ooc будет рекурсивно (но только один раз) загружать файл описания класса super.d, а затем должны быть определены super и meta, чтобы class мог быть определён. Если используется эта форма заголовка класса, могут быть представлены только методы со статической компоновкой.

 

% meta: supermeta class: super {
Это дополнительно определяет meta как новый метакласс с supermeta в качестве его суперкласса. Если super не определён, то ooc будет рекурсивно (но только один раз) загружать файл описания класса super.d, а затем должны быть определены super и supermeta, чтобы meta и class могли быть определены.

 

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

 

[ tag : ] declarator ( declarator { , declarator } [ , ... ] );
Необязательный тэг представляет собой идентификатор, участвующий в поиске метода с помощью respondsTo(). Первый declarator представляет имя метода и тип результата, остающиеся операторы declarator представляют имена параметров и их типы. Только один параметр должен иметь имя self, чтобы указать получателя вызова метода.

 

declarator, как описано выше, это упрощённый оператор объявления C, но есть два особых случая:

 

_name
представляет name как имя оператора объявления. Тип является указателем на экземпляр текущего класса или на класс, для которого перезаписан динамически компонуемый метод. Такой указатель будет разыменован %casts в методе как name. Поэтому self должен быть представлен как _self, где self представляет разыменованный объект или класс для методов класса, а _self — неопределённый указатель.

 

class @ name
представляет name как указатель на экземпляр класса. Такой указатель не будет разыменовываться, но будет проверяться с использованием %casts.

 

Тип результата метода может использовать class @. В этом случае тип результата генерируется как указатель на struct class, который полезен при реализации методов, и который в коде приложения не может использоваться кроме как для присвоений переменным с типом void *. Тип результата для конструкторов и подобных методов должен быть void *, чтобы подчеркнуть универсальные аспекты конструкции.

 

Предварительная обработка

Согласно описанным выше лексическим соглашениям, файл реализации source.dc копируется в поток стандартного вывода. Строки, начинающиеся с %, предварительно обрабатываются следующим образом:

 

% class method {
method заменяется заголовком функции C; заголовок декларируется как static с именем class_method, если method не имеет статической компоновки. В последнем случае class необязателен. ooc проверяет все варианты, которыми метод может быть определён для class. Имена функций запоминаются по мере необходимости для инициализации описания class и соответствующего метакласса, если таковые имеются. Может быть необязательный тэг, предшествующий class, если method не имеет статической компоновки.

 

%casts
Это заменяется определениями локальных переменных для безопасного разыменовывания указателей параметров на объекты в текущем классе. Для статически компонуемых методов это сопровождается проверками, чтобы удостовериться, что параметры указывают на объекты других классов. %casts следует использовать там, где могут быть определены локальные переменные; для статически компонуемых методов это должно быть последнее определение. Обратите внимание на то, что нулевые указатели не проходят проверки и завершают работу программу.

 

%init
Это должно быть ближе к концу файла реализации. Если description представляло новый метакласс, генерируются конструктор для метакласса, селекторы для класса и инициализации для метакласса. Инициализация для класса генерируется в любом случае.

 

Если метод m не компонуется статически, есть два селектора: m с теми же параметрами, как у метода, выбирающего метод, определённый для self, и super_m с явным описанием класса в виде дополнительного первого параметра. Второй селектор используется, чтобы передать вызов метода в суперкласс класса, где этот метод определён.

Если динамически компонуемый или относящийся к классу метод имеет список с переменным числом аргументов, селектор передаёт такому методу va_list * app.

Если селектор распознаёт, что не может быть применён к объекту, он вызывает forward и передаёт ему объект, указатель на область результата, или нулевой указатель, свой собственный адрес, своё имя в виде строки и весь свой список аргументов. forward должен быть динамически компонуемым методом в корневом классе; он может использоваться для перенаправления сообщения от одного объекта другому.

Тэги

respondsTo() — метод в корневом классе, который получает объёкт и тэг, то есть строку C, содержащую идентификатор, и возвращающую либо нулевой указатель, либо селектор, который примет объект и другие параметры, и вызовет метод, соответствующий тэгу.

Тэг, после которого может быть найден метод класса или динамически компонуемый метод, определяется как показано ниже. По умолчанию используется либо имя метода, либо tag в заголовке метода в файле описания класса:

 

tag : ] declarator ( declarator { , declarator } [ , ... ] );

 

Заголовок метода в реализации может перезаписать этот тэг:

 

mtagclass method {

 

Если тэг mtag определён, используется он, если нет, используется tag. Если mtag или tag пусты, но указано двоеточие, respondsTo() не сможет найти метод.

Файл отчёта

ooc использует файлы отчета, содержащие фрагменты всего кода, который будет генерировать ooc. Имена, подобные app для указателя списка аргументов, в файле отчёта могут быть изменены. В сам ooc встроено только имя self.

Файл отчёта содержит один или несколько отчётов. Применяются обычные лексические соглашения. Каждому отчёту предшествует строка, начинающаяся с % и содержащая имя отчёта, которое может завершаться пробелами. Имя отчёта — произвольный текст, но он должен быть уникальным.

Отчёт состоит из строк слов, разделённых одиночными пробелами или символами табуляции, называемых пробелами. Если встречаются два смежных пробела или если пробел начинает или заканчивает строку, получается пустое слово.

Пустое слово, не находящееся в начале строки вывода, распечатывается как пробел. В частности это означает, что два последовательных пробела в отчёте представляют одиночный пробел при распечатке. Любое слово, не начинающееся с одинарной левой кавычки `, распечатывается как есть.

Слово, начинающееся с `%, вызывает распечатку отчёта. Именем отчёта является оставшееся слово.

Если определена опция -l, `#line с последующим словом вызывает распечатку штампа строки; в противном случае фраза игнорируется. Если слово это класс, метод или имя компонента класса, штамп строки относится к его позиции в файле описания класса. Иначе, и в частности для пустых слов, штамп строки относится к текущей позиции входного файла.

Слово, начинающееся с `{, начинает группу. Группа завершается словом, начинающимся с `}. Все другие слова, начинающиеся с одинарной левой кавычки `,  во время печати заменяются. Некоторые замены определены глобально, другие настроены определёнными группами. Таблица замен приведены в конце этого раздела.

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

 

`{%              статические методы для текущего `class

`{%−             динамические методы для текущего `class

`{%+             методы класса для текущего `class

`{()             параметры для текущего `method

`{dcl            заголовки класса в файле описания `desc

`{pub            общедоступные строки в файле описания `desc

`{prot           защищённые строки в файле описания `desc

`{links class    динамические методы и методы класса определённые для class

`{struct class   компоненты для class

`{super          `desc и все его суперклассы вплоть до `root

 

Цикл завершается словом, начинающимся с `}. Если завершающееся слово в цикле по параметрам это `}, и если цикл будет продолжаться для большего количества параметров, после этого слова распечатывается запятая с последующим пробелом. Если завершающее слово `}n, и если группа создала какой-либо вывод, для этого слова распечатывается символ перевода строки. В противном случае по завершении не распечатывается ничего.

Условная группа начинается с `{if или `{ifnot сопровождаемых двумя словами. Слова заменяются если это необходимо и если сравниваются. Если они равны, выполняется группа, начинающаяся с `{if; если они не равны, выполняется группа, начинающаяся с `{ifnot. Если какая-либо группа не выполняется и если она сопровождается группой, начинающейся с `{else, выполняется эта группа. Иначе группа `{else пропускается.

В целом лучше, если `}, завершающее группу `{if, непосредственно предшествует `{else в той же строке отчёта.

Вот таблица замен слов вместе с событиями, которые устанавливают эти замены:

 

устанавливаются на глобальном уровне

 `            нет текста (пустая строка)

 ``           ` (одинарная левая кавычка)

 `t           табуляция

 `n           перевод строки (ограничивается одной пустой строкой)

 

устанавливаются после загрузки описаний классов

 `desc        последнее описание из командной строки

 `root        имя корневого класса

 `metaroot    имя корневого метакласса

 

устанавливаются для классов         %%− %+ `{dcl `{prot `{pub `{super

 `class       имя класса

 `super       имя суперкласса класса

 `meta        имя метакласса класса

 `supermeta   имя суперкласса метакласса

 

устанавливаются для метода                `{% `{%− `{%+ `{links class

 `method      имя метода

 `result      имя результата метода

 `linkage     компоновка метода: %%- или %+

 `tag         тэг метода

 `,...        , ... если декларируются переменные аргументов,

                 пусто, если нет

 `_last       имя последнего параметра, есть переменные аргументов,

                не определяется, если нет

 

устанавливаются для оператора декларации          `{() `{struct class

 `name        имя оператора декларации

 `const       const с последующим пробелом, если так декларируется

 `type        void * для объектов, в противном случае задекларированный тип

 `_           _ если используется в декларации, в противном случае пусто

 `cast        имя класса объекта, в противном случае пусто

 

устанавливаются для строк из файла описания        `{dcl `{prot `{pub

 `class       устанавливается для описания класса, в противном случае пусто

 `line        текст строки, если не описание класса, в противном случае не определяется

 `newmeta     1 если определён новый метакласс, 0 если нет

 

description в командной строке ooc выполняет настройку для класса. Запрос заголовка метода в исходном файле выполняет настройку для класса и метода. Циклы `{dcl, `{prot и `{pub устанавливаются для строк из файла описания класса. Циклы `{%, `{%-, `{%+ и `{links class устанавливаются для метода. Цикл `{() устанавливается для оператора декларации параметра. Цикл `{struct class устанавливается для оператора декларации компонента класса. Цикл `{super выполняется из description для всех его суперклассов.

Переменные окружения

OOCPATH — разделяемый двоеточиями список путей. Если имя файла не содержит разделителей путей, ooc ищет файл (описания классов, исходники и файлы отчётов), добавляя каждую запись OOCPATH перед требуемым именем файла. По умолчанию OOCPATH содержит рабочий каталог и стандартное место.

 

FILES       class.d               описание для class

            class.dc              реализация для class

            report.rep            файл отчёта

            AWKPATH/*.awk         модули

            AWKPATH/*.dbg         модули отладчика

            OOCPATH/c.rep         отчёты реализаций файлов

            OOCPATH/dc.rep        отчёт реализации implementation thunks report

            OOCPATH/etc.rep       общие отчёты

            OOCPATH/h.rep         отчёт интерфейсного файла

            OOCPATH/header.rep    общие отчёты

            OOCPATH/m.rep         отчёт зависимостей makefile

            OOCPATH/r.rep         отчёты представлений файлов

            OOCPATH/va.rep        общие отчёты

            OOCPATH/[chr]-R.rep   версии корневого класса

 

Препроцессор C применяется к тому, что ooc выводит, а что получает на входе, то есть условную компиляцию не следует применять к средствам управления ooc.

 

Предыдущая  Содержание  Следующая