Директивы компилятора

В меню OPTIONS/COMPILER включены опции, с помощью которых можно управлять работой компилятора. В ряде случаев бывает необходимо временно отменить действие той или иной опции при трансляции некоторого фрагмента программы. Особенно часто, например, такая необходимость возникает при обращении к диску: если программа пытается прочитать несуществующий файл или записать данные на защищенный диск, возникнет ошибка периода исполнения и программа аварийно закончит свою работу. В то же время, если отключить опцию I/O CHECKING, этого не произойдет, программа сможет проанализировать последствия обращения к диску и предпринять альтернативные действия.

В Турбо Паскале можно использовать директивы компилятора, которые в виде особым образом оформленных комментариев вставляются в текст программы и модифицируют те или иные возможности компилятора в процессе компиляции. Директивы могут быть переключающими, условными и параметрическими. Переключающие директивы воздействуют на те опции, которые включены в диалоговое окно OPTIONS/COMPILER; условные директивы определяют условия, при которых компилируются те или иные фрагменты программы; параметрические директивы задают параметры, которые должен учитывать компилятор.

Все директивы оформляются в виде особых комментариев: они обрамляются фигурными скобками, а за открывающей скобкой должен без пробелов следовать знак доллара (десятичный код 36). Как только в процессе разбора исходного текста программы компилятор встретит такого рода последовательность символов, он воспримет их как директиву и нужным образом изменит свою работу.

Переключающая директива содержит букву, обозначающую опцию, и знак «+» или «-». Знак «+» означает установку опции в активное состояние, знак «-» - в пассивное состояние. Например, директива {$I-} означает временное отключение контроля ошибок ввода-вывода, директива {$R+} - включение контроля границ диапазона. В одной директиве можно перечислить несколько опций, например:

{ $A+,B-,D+,E+,F+,I+,L+,N+,O-,R+,S+,V+}

Следует учесть, что директивы компилятора действуют от момента своего появления в тексте до конца текущего модуля, т.е. локализуются в теле модуля, в то время как опции, установленные в самой среде, распространяются на все модули и основную программу. В случае конфликта между директивами и опциями, предпочтение отдается директивам. Таким образом, правильно расставленные директивы обеспечивают нужную компиляцию программы независимо от настройки среды. Они особенно полезны в случае, когда компиляция осуществляется автономным компилятором ТР.ЕХЕ.

Некоторые директивы компилятора могут действовать только на часть текста программы, такие директивы называются локальными; в отличие от этого глобальные директивы располагаются в самом начале текста программы (модуля) и действуют сразу на всю программу (модуль) в целом.

Ниже приводится список всех директив компилятора. В скобках дается действие директивы для знака «-». Знаком * отмечены локальные директивы.

{$А+} - выравнивать данные на границу слова (байта);

{SB+}* - вычислять логические выражения полностью (до получения результата);

{SD+} - разрешить (запретить) работу со встроенным отладчиком;

{$Е+} - включить (отключить) режим программной эмуляции сопроцессора;

{SF+} - использовать дальнюю (ближнюю) модель вызова;

{$G+}* - использовать (не использовать) полный набор команд микропроцессора Intel 80286 (микропроцессора Intel 8088);

{$I+}* - включить (отключить) контроль операций ввода-вывода;

{$L+} - включить (не включать) локальные символы в информацию для отладчика;

{SN+} - использовать числовой сопроцессор (реализовать операции с плавающей точкой программно);

{$O+} - разрешить (не разрешать) создание оверлейной структуры;

{$R+}* - включить (отключить) контроль границ диапазона;

{$S+}* - включить (отключить) контроль возможного переполнения стека;

{SV+}* - включить (отключить) контроль длины строк при обращении к процедуре или функции;

{$Х+} - использовать (не использовать) расширенный синтаксис.

К условным директивам относятся следующие локальные директивы компилятора:

{SDEFINE <условный символ>} - установить условный символ;

{SIFDEF <условный символ>} - проверить установку условного символа; если символ установлен, будет компилироваться вся следующая за директивой часть программы вплоть до директив {$ELSE} или {SENDIF}, в противном случае этот фрагмент программы будет пропущен компилятором;

{SIFNDEF <условный символ>) - проверить установку локального символа; обратна директиве {$IFDEF}, т.е. действует только в том случае, когда условный символ не установлен;

{$ELSE} - определяет начало альтернативного фрагмента программы; этот фрагмент будет компилироваться в том случае, если условный символ, проверенный предыдущей по тексту программы директивой {SIFDEF} пли {SIFNDEF}, не установлен; альтернативная часть вместе с директивой {SELSE} может опускаться;

{SENDIF} - ограничивает область действия директив {$IFDEF}, {IFNDEF} или {$ELSE}.

Установить условие - это значит с помощью опции OPTIONS/COMPILER/CONDITIONAL DEFINES среды Турбо Паскаля или с помощью директивы компилятора {$DEFINE} ввести некоторое слово (условный символ), которое затем будет управлять компиляцией какого-либо фрагмента программы. Если, например, использовать в качестве условного символа слово DEBUG, то можно написать такой фрагмент программы:

{$IFDEF Debug}

WriteLn ('Отладка: х=,х);

{$ENDIF}

Теперь, если установлен (задан в среде или введен с помощью директивы {SDEFINE}) условный символ DEBUG, в программе будет откомпилирован оператор WRITELN, если этот условный символ не задан, компилятор пропустит этот оператор.

Отметим, что условные символы никак не связаны с множеством идентификаторов самой программы и недоступны ей на этапе исполнения. Для предыдущего примера нельзя написать

WriteLn (Debug) ;

если, разумеется, в программе не определена переменная или константа с этим именем.

Одновременно в программе может быть установлено сколько угодно условных символов. Для тестирования нескольких условий используется вложение условных директив компилятора, например:

{$IFDEF Var1} 

{$IFDEF Var2}

a := n; {$ELSE}

a := 0;

{$ENDIF} 

{$ENDIF}

В директивах {$IFDEF} или {$IFNDEF} программист может использовать следующие стандартные условные символы, которые устанавливаются в среде автоматически:

VER70 - указывает версию 7.0 Турбо Паскаля (для других версий используются другие условные символы: VER40, VER50, VER55, VER60);

MSDOS - указывает на то, что программа будет исполняться под управлением операционной системы MS-DOS (PC DOS); версии Турбо Паскаля для других операционных систем не будут устанавливать этот символ;

CPU86 - указывает на то, что программа будет исполняться на ПК с микропроцессором, принадлежащим семейству Intel 80x86;

CPU87 - указывает на то, что в составе аппаратных средств ПК обнаружен (к моменту компиляции программы!) арифметический сопроцессор семейства Intel 80x87.

К параметрическим относятся директивы:

{$М <стек>,<нижн>,<верх>} - установить требуемые размеры памяти (глобальная директива); здесь <стек> - размер стека; <нижн> - нижняя граница динамической памяти; <верх> - верхняя граница динамической памяти;

{$I <имя файла>} - включение PAS-файла: <имя файла> - имя включаемого файла;

{$L <имя фапла>} - включение OBJ-файла: <имя файла> - имя включаемого файла.

В директиве {$М} все размеры задаются в байтах, следуют друг за другом в указанной последовательности и отделяются запятыми. Между буквой М и первой цифрой размера стека должен быть хотя бы один пробел, между последней цифрой верхней границы динамической памяти и закрывающей фигурной скобкой не должно быть никаких символов, например:

{$М 16384,0,655360}

Включаемый файл, определенный в директиве {$I}, должен содержать исходный текст фрагмента программы. Компилятор использует эту директиву как указание обратиться к дисковому файлу за очередной строкой программы. После того, как весь фрагмент программы из файла будет прочитан, компилятор продолжит чтение строк из файла редактора. Если в имени файла опущено расширение, используется стандартное расширение .PAS. Диск и каталог, в котором находится файл, задаются опцией OPTIONS/ENVIRONMENT/DIRECTORIES.

Директива ($L) предназначена для указания компилятору файла, в котором содержится результат трансляции ассемблерной процедуры или функции, объявленной в программе как внешняя {EXTERNAL, см. гл. 11). Если в имени файла опущено расширение, используется стандартное расширение. OBJ. Диск и каталог, в котором находится файл, задаются опцией OPTIONS/ENVIRONMENT/DIRECTORIES.