Читаем UNIX полностью

Упражнение: 8.6

Добавьте к грамматике встроенную функцию atan2(x, y) для вычисления величины угла, тангенс которого равен x/y. Добавьте встроенную функцию rand(), вырабатывающую случайные вещественные числа, равномерно распределенные на интервале [0,1). Как бы вам пришлось изменить грамматику, чтобы разрешить встроенные функции с разным числом аргументов?

Упражнение 8.7

Как ввести дополнительное средство для выполнения команд прямо в hoc, подобно операции ! в программах UNIX?

Упражнение 8.8

Переработайте текст math.c так, чтобы можно было использовать таблицу, а не предложенное выше множество идентичных функций.

Еще одно замечание относительно make

Поскольку теперь программа hoc3 размещается не в одном, а в пяти файлах, makefile становится более сложным:

$ cat makefile

YFLAGS = -d # force creation of y.tab.h

OBJS = hoc.o init.o math.o symbol.o # abbreviation

hoc3: $(OBJS)

      cc $(OBJS) -lm -o hoc3

hoc.o: hoc.h

init.o symbol.o: hoc.h y.tab.h

pr:

       @pr hoc.y hoc.h init.c math.c symbol.c makefile

clean:

       rm -f $(OBJS) y.tab.[ch]

$

Строка YFLAGS = -d добавляет флаг -d в командную строку запуска yacc, создаваемую make. Этот флаг предписывает yacc создать файл y.tab.h, содержащий операторы #define. Строка OBJS = ... вводит сокращение для записи конструкции, используемой последовательно несколько раз. Синтаксис здесь не такой, как для переменных интерпретатора, скобки обязательны. Флаг -lm указывает, что математические функции нужно искать в библиотеке libm.a.

Теперь программа hoc3 образуется из четырех файлов , причем некоторые из них в свою очередь зависят от файлов .h. "Зная" эти зависимости, make может рассчитать, какая требуется перетрансляция в случае изменения любого из указанных файлов. Если вы хотите выяснить действия make, не запуская процесс, то попробуйте ввести команду

$ make -n

С другой стороны, если необходимо установить временную согласованность файлов, с помощью флага -t (touch исправить) вы можете как бы модифицировать файлы, не производя перетрансляции.

Обратите внимание на то, что мы ввели не только множество зависимостей между исходными файлами, но и несколько полезных процедур, сконцентрировав их в одном файле. По умолчанию программа make выполняет первое действие, указанное в файле makefile. Однако если на первом месте окажется элемент, помечающий правило зависимости, такой, как symbol.o или pr, то выполняться будет он. Считается, что в случае "пустой" зависимости элемент всегда берется не из последней версии, поэтому при запросе он обязательно должен изменяться. Итак,

$ make pr | lpr

инициирует распечатку зависимостей файлов на принтере. (Появление символа @ в "@pr" подавляет эхо выполняемой команды, запущенной с помощью make.) Команда же

make clean

удаляет выходные файлы yacc, а также файлы .o.

Такой механизм пустых зависимостей в файле makefile часто оказывается более предпочтительным по сравнению с командным файлом как средство для концентрации в одном файле всех связанных операций. Область применения команды make не ограничивается только разработкой программ, она позволяет сгруппировать в единый набор все операции, имеющие временные зависимости.

Несколько замечаний относительно lex

Программа lex порождает лексические анализаторы аналогично тому, как yacc генерирует программы грамматического разбора: вы создаете описание лексических правил вашего языка с помощью регулярных выражений и фрагментов Си программ, которые будут выполняться при обнаружении строки, соответствующей шаблону. Программа lex строит по этой информации распознаватель. Программы lex и yacc взаимодействуют таким же образом, как и описанные выше лексические анализаторы. Мы не собираемся здесь детально рассматривать lex; наша цель — заинтересовать вас, а подробности вы найдете в справочном руководстве по UNIX (том 2B).

Вначале приведем lex-программу из файла lex.l, которая заменяет применявшуюся до сих пор функцию yylex:

$ cat lex.l

%{

#include "hoc.h"

#include "y.tab.h"

extern int lineno;

%}

%%

Перейти на страницу:

Похожие книги

Все жанры