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 -