3.4. Условная компиляция программ

Принципы условной компиляции тесно связаны с построением программ на Турбо Паскале. Разрешая группировать блоки VAR, TYPE и прочие по функциональным признакам и размещать их в различных местах программы, Турбо Паскаль предоставляет еще и средства управления порядком компиляции (не путать с режимами!). Любой, кто отлаживал свои программы, знает, как исключить из работы фрагмент текста: надо оформить его как комментарий или обойти оператором перехода типа GOTO. Но все это нарушает исходный текст. Турбо Паскаль вводит особый набор ключей компиляции для решения подобных вопросов. Их немного:

{$DEFINE КлючевоеСлово } задание ключевого слова,

{$UNDEF КлючевоеСлово } сброс ключевого слова,

{$IFDEF КлючевоеСлово } проверка задания слова,

{$IFNDEF КлючевоеСлово } проверка отсутствия задания ключевого слова,

{$IFOPT КлючИзнак } проверка режима компиляции,

{$ELSE) альтернативная ветвь,

{$ENDIF) обязательный конец условия.

Ключ $DEFINE определяет (задает) условное ключевое слово, которое становится активным и известным компилятору и по которому будут срабатывать другие ключи: $IFDEF — проверка условия активности этого слова и $IFNDEF — проверка отсутствия его задания (рис. 3.3).

| { $DEFINE variant0 }

| BEGIN

| {$IFDEF variant0 }

| WriteLn ( 'Вариант программы номер 0' );

| {$ENDIF)

| {$IFNDEF variant0 }

| WriteLn ( 'Ненулевая версия программы' );

| {$ENDIF}

| END.

Рис. 3.3

- 58 -

Если в тексте программы определено ключевое слово (здесь variant0), то будет откомпилирован блок, зависящий от активности этого слова, т.е. заключенный между ключами {$IFDEF variant0} и {$ENDIF}. Альтернативный вариант блока будет компилироваться только, когда ключевое слово variant0 неопределено (пассивно). На это указывают обрамляющие его ключи {$IFNDEF variant0}...{$ENDIF}. Но если, например, изменить в тексте ключа $DEFINE слово variant0 на variant1 и заново откомпилировать программу, то все получится наоборот: будет пропущен первый блок (его слово не определено), но откомпилирован второй (условие отсутствия слова выполняется).

Можно заметить, что обязательная директива {$ENDIF} всегда замыкает блок, начатый ключом {$IF...}. Пример на рис. 3.3 можно без ущерба для смысла переписать в ином виде (рис. 3.4).

| { SDEFINE variant0}

| BEGIN

| {$IFDEF variant0 }

| WriteLn ( 'Вариант программы номер 0');

| {$ELSE}

| WriteLn ('Ненулевая версия программы');

| {$ENDIF}

| END.

Рис. 3.4

Здесь задействован ключ {$ELSE}, направляющий ход компиляции в альтернативное русло, если не выполняется условие предшествующего ключа {$IF...}. Для такого сложного условия ключ конца все равно будет один.

Блоки, компилируемые условно, могут содержать любое число операторов. Части программы, находящиеся вне блоков условной компиляции {$IF...}...{$ENDIF}, никак не зависят от ключевых слов. Само ключевое слово может содержать сколько угодно символов (только латинских и цифр), хотя распознаются только первые 63 из них. Ключевые слова имеют смысл только в ключах-командах условной компиляции и никак не перекликаются с идентификаторами самой программы.

Однажды объявленное ключевое слово можно отменить по ходу процесса компиляции (перевести из активного состояния в пассивное) ключом

- 59 -

{$UNDEF КлючевоеСлово}

После такой строки в тексте слово считается не заданным.

До сих пор речь шла о вводимых программистом ключевых словах. Кроме них, всегда определены три слова:

VER55 — ключевое слово версии компилятора (языка); для версий 5.0 и 4.0 оно было другим — VER50 и VER40 соответственно;

MSDOS — ключевое слово типа ОС; в MS-DOS, PC-DOS или их аналогах это слово именно такое;

CPU86 — ключевое слово семейства центрального процессора; если он не из семейства 80X86, то это слово будет другим.

К этому списку слов может быть добавлено еще одно, если компилятор обнаружил наличие математического сопроцессора 80X87:

CPU87 — ключевое слово, определенное, если в ПЭВМ имеется математический сопроцессор.

Ключевое слово сопроцессора позволяет установить порядок компиляции в зависимости от комплектации ПЭВМ:

{$IFDEF CPU87 -

{$N+ включаем режим использования сопроцессора }

TYPE

объявляем типы с повышенной точностью;

{$ELSE}

{$N- не используем возможности сопроцессора }

TYPE

объявляем типы с обычной точностью:

{$ENDIF}

В списке ключей условной компиляции был еще один ключ {$IFOPT}. Принцип его работы такой же, как и ключа {$IFDEF}. Отличие состоит лишь в условии срабатывания. Здесь им является состояние какого-либо ключа режима компиляции. Например, если программа компилируется в режиме {$N+}, заданном в тексте или умолчанием, то условие {$IFOPT N+} — истинно, a {$IFOPT N-} — ложно.

Теперь есть возможность управлять ходом компиляции, опираясь на состояние различных режимов. Ключ {$IFOPT} может иметь альтернативную ветвь {$ELSE} и по-прежнему обязан иметь закрывающую блок условной компиляции директиву {$ENDIF}.

Напомним, что все ключи условной компиляции имеют смысл только в процессе компиляции программ и не принимают участия в выполнении их.

- 60 -