XXI.  

ŘÍZENÍ  PŘEKLADU


Jazyk Turbo Pascal implementuje sadu direktiv pro řízení procesu překladu. Tyto direktivy jsou uváděny ve zdrojových textech ve složených závorkách, přičemž za levou (otevírací) závorkou bezprostředně následuje znak dolar ($), odlišující direktivu od komentáře, a název (značka) direktivy. Na velikosti písmen názvu nezáleží.

Podle funkce lze direktivy klasifikovat na přepínačové, parametricképodmínkové.

XXI.1. 

Přepínačové direktivy

Přepínačové direktivy přepínají způsob kompilace zdrojového textu vzhledem k jisté vlastnosti mezi dvěma stavy. Název direktivy je tvořen jediným písmenem a volba stavu se provádí symbolem plus (+) resp. minus (-), uvedeným bezprostředně za názvem. Například:

{$N+}
Uvnitř jedné složené závorky lze současně uvést i více názvů a stavů přepínačových direktiv, které se pak navzájem oddělují čárkami (mezery ani jiné nadbytečné oddělovače se mezi nimi vyskytovat nesmí):
{$N+,E+}
Podle rozsahu platnosti lze přepínačové direktivy klasifikovat na globálnílokální. Globální direktivy smí být uvedeny nejpozději za hlavičkou programu resp. programové jednotky a jimi definovaný stav je platný během kompilace celého textu modulu. Lokální direktivy lze naopak uvádět kdekoliv, kde je povolen výskyt komentáře (nelze je tedy uvést pouze uvnitř lexikálních elementů), a jimi definované stavy jsou platné až do dalšího výskytu téže direktivy s opačným znaménkem, opět však nejvýše do konce textu modulu.

Implicitní stavy přepínačových direktiv jsou uplatněny vždy na začátku kompilace každého dílčího modulu. Modifikovat je lze v zaškrtávacích polích dialogu Compiler Options, který je přístupný příkazem Compiler nabídky Options vývojového prostředí. Zaškrtnuté resp. nezaškrtnuté pole pak odpovídá stavu plus resp. minus příslušné direktivy.

Tabulka 21: Přiřazení polí dialogu Compiler Options direktivám
direktiva pole dialogu
{$Astav} Word align data
{$Bstav} Complete boolean eval
{$Dstav} Debug information
{$Estav} Emulation
{$Fstav} Force far calls
{$Gstav} 286 instructions
{$Istav} I/O checking
{$Lstav} Local symbols
direktiva pole dialogu
{$Nstav} 8087/80287
{$Qstav} Overflow checking
{$Pstav} Open parameters
{$Rstav} Range checking
{$Sstav} Stack checking
{$Tstav} Typed @ operator
{$Vstav} Strict var-strings
{$Xstav} Extended syntax

{$Astav}

Globální direktiva zarovnávání dat. Ve stavu {$A+} jsou všechny proměnné a typové konstanty větší než jeden byte zarovnávány na hranici slova tak, že začínají na sudých adresách. Na procesorech 8086 je přístup k datům na sudých adresách rychlejší než přístup k datům na adresách lichých.

{$Bstav}

Lokální direktiva režimu vyhodnocování booleovských výrazů. Týká se vyhodnocování binárních logických operací andor. Ve stavu {$B+} (režim úplného vyhodnocování) jsou vždy vyhodnoceny oba operandy, i když je výsledek operace znám již po vyhodnocení prvního z nich, zatímco ve stavu {$B–} (režim zkráceného vyhodnocování) se v takovém případě již vyhodnocení druhého operandu neprovádí.

Pokud má totiž první operand operace and resp. or hodnotu False resp. True, je hodnotou operace False resp. True, nezávisle na hodnotě operandu druhého. Vyhodnocení druhého operandu pak má smysl pouze tehdy, je-li jeho důsledkem nějaký vedlejší efekt — je-li například druhým operandem volání logické funkce, která před poskytnutím výsledku vykoná nějakou přidruženou akci.

{$Dstav}

Globální direktiva generování ladicích informací o zdrojovém textu modulu pro debugger. Ve stavu {$D+} direktiva generování ladicích informací povoluje a tím umožňuje krokování běhu modulu, nastavení breakpointů a lokalizaci případné běhové chyby ve zdrojovém textu.

Při překladu programové jednotky jsou povolené ladicí informace automaticky uloženy do tpu-souboru, do cílového kódu programu (exe-souboru) se však povolené ladicí informace ukládají pouze v případě nastavení položky Debugging dialogu Debugger na hodnotu Standalone. Dialog je přístupný příkazem Debugger nabídky Options vývojového prostředí. Zahrnutí ladicích informací do cílového kódu programu umožňuje jeho ladění mimo vývojové prostředí, externím ladicím programem (Turbo Debugger).

{$Estav}

Globální direktiva emulace aritmetického koprocesoru. Má smysl pouze při současném nastavení direktivy {$N+} (použití koprocesoru povoleno). Ve stavu {$E+} je do kódu programu zahrnuta knihovna pro komunikaci s koprocesorem, která umožňuje jeho případnou emulaci. Program pak buď používá přímo koprocesor (je-li přítomen) nebo jej programově emuluje. Ve stavu {$E–} je do kódu programu zahrnuta podstatně menší knihovna, která emulaci koprocesoru neumožňuje (program pak lze spustit pouze za přítomnosti koprocesoru).

Direktiva je ignorována při zakázaném použití koprocesoru. Do kódu programu se pak vkládá pouze knihovna pro výpočty s reálnými čísly základního typu Real.

{$Fstav}

Lokální direktiva implicitního modelu volání podprogramů. Týká se všech následujících podprogramů ve zdrojovém textu modulu, které nejsou veřejnými podprogramy jednotky (ty jsou přeloženy vždy pro daleký model volání) ani nejsou vnořené v bloku jiného podprogramu (ty jsou přeloženy vždy pro blízký model volání) ani nemají požadovaný model volání explicitně vyznačen direktivou far resp. near. Ve stavu {$F+} resp. {$F–} jsou všechny tyto podprogramy přeloženy pro daleký resp. blízký model volání.

Podprogramy s blízkým modelem volání jsou adresovány pouze ofsetovou částí adresy, proto mohou být volány pouze z toho segmentu kódu programu, ve kterém jsou alokovány (tj. z toho modulu zdrojového textu, ve kterém jsou deklarovány) a nemohou být předávány jako parametry ani nemohou být ovládány prostřednictvím procedurálních proměnných.

{$Gstav}

Lokální direktiva generování kódu pro procesor 80286. Ve stavu {$G–} je cílový kód tvořen pouze instrukcemi procesorů 8086 a 8088, kterými byly vybaveny starší modely počítačů. Ve stavu {$G+} je množina povolených instrukcí rozšířena o speciální instrukce procesoru 80286, což se může projevit zvýšením rychlosti výpočtu a snížením rozsahu kódu programu. Takto kompilovaný program pak ovšem není slučitelný s procesory 8086 a 8088.

{$Istav}

Lokální direktiva ošetření chyb vstupních a výstupních operací. Ve stavu {$I+} je důsledkem každé chyby při vstupně-výstupních operacích běhová chyba programu. Ve stavu {$I–} je číslo vzniklé chyby pouze uloženo do speciální proměnné. Program pak běží dál, ale veškeré vstupně-výstupní operace jsou ignorovány, dokud není chybový příznak vynulován voláním funkce IOResult — chyba musí být ošetřena programem.

{$Lstav}

Globální direktiva generování ladicích informací o lokálních symbolech v blocích podprogramů a v implementačních částech programových jednotek. Ve stavu {$L+} je generování ladicích informací o lokálních symbolech povoleno.

Direktiva {$L+} je ignorována, pokud je v modulu zakázáno generování ladicích informací direktivou {$D–}.

{$Nstav}

Globální direktiva použití aritmetického koprocesoru. Ve stavu {$N+} povoluje provádění výpočtů s reálnými čísly využitím aritmetického koprocesoru 8087 (nebo jeho emulace) a použití speciálních číselných typů koprocesoru (Single, Double, ExtendedComp). Ve stavu {$N–} může být pro reprezentaci reálných čísel použit pouze typ Real.

{$Qstav}

Lokální direktiva kontroly přetečení při výpočtu hodnoty ordinálních výrazů. Ve stavu {$Q+} vsune kompilátor do kódu vyhodnocení výrazu kontrolní test, který při vzniku přetečení generuje běhovou chybu programu. Ve stavu {$Q–} se kontrolní kód nevkládá a přetečení je ignorováno — program běží dál, ale výsledek výpočtu výrazu je chybný.

Testy přetečení poněkud zpomalují běh programu a zvětšují rozsah jeho kódu, proto se obvykle používají jen ve fázi ladění. V konečné verzi programu by již měly být všechny chyby, které přetečení způsobují, odstraněny.

{$Pstav}

Globální direktiva předefinování významu rezervovaného slova string v deklaracích odkazem volaných formálních parametrů podprogramů. Ve stavu {$P–} je předefinování zakázáno — formální parametr, v jehož deklaraci je uvedeno rezervované slovo string, je typu string [255] (jako ve starších verzích Turbo Pascalu). Ve stavu {$P+} má rezervované slovo string v deklaraci odkazem volaného formálního parametru stejný význam jako identifikátor OpenString — typem formálního parametru je otevřený řetězec string [X], kde X je deklarovaná maximální délka skutečného parametru, kterým pak smí být proměnná libovolného řetězcového typu.

{$Rstav}

Lokální direktiva kontroly rozsahu indexů polí a řetězců a hodnot, přiřazovaných ordinálním proměnným. Ve stavu {$R+} vsune překladač do kódu přístupu k prvku pole (řetězce) resp. do kódu přiřazovacího příkazu kontrolní test, který při překročení deklarovaného rozsahu indexu resp. hodnoty proměnné generuje běhovou chybu programu. Ve stavu {$R–} se kontrolní kód nevkládá a překročení rozsahu je ignorováno — program běží dál, ale důsledky překročení rozsahu nejsou nijak ošetřeny.

Testy překročení rozsahu poněkud zpomalují běh programu a zvětšují rozsah jeho kódu, proto se obvykle používají jen ve fázi ladění. V konečné verzi programu by již měly být všechny chyby, které překročení rozsahu způsobují, odstraněny.

{$Sstav}

Lokální direktiva kontroly přeplnění zásobníku. Ve stavu {$S+} je součástí každého volání podprogramu kontrolní kód, který otestuje, zda je na zásobníku dostatek místa pro lokální proměnné podprogramu a jiná dočasná uložení dat. Při záporném výsledku je pak generována chyba běhu programu. Pokud dojde k přeplnění při vypnuté kontrole, program pravděpodobně havaruje.

{$Tstav}

Lokální direktiva režimu typové kontroly kompatibility ukazatelových typů. Ve stavu {$T–} je kontrola striktní — dva ukazatelové typy jsou uznány kompatibilními pouze pokud jsou identické nebo pokud je jeden z nich ukazatelem univerzálním. Ve stavu {$T+} jsou za kompatibilní považovány i ukazatelové typy s identickými bázovými typy.

Dalším aspektem, který na stavu této direktivy závisí, je typ výrazu @Objekt, kde Objekt je neprocedurální proměnná (hodnotou výrazu je ukazatel na uvedenou proměnnou). Ve stavu {$T–} je typem výrazu ukazatel univerzální (Pointer), kdežto ve stavu {$T+} ukazatel typový, jehož bázovým typem je typ proměnné Objekt.

{$Vstav}

Lokální direktiva kontroly identity typů formálních a skutečných řetězcových parametrů podprogramů. Při překladu volání podprogramů provádí překladač kontrolu identity typů formálních a skutečných parametrů volaných odkazem. Ve stavu {$V–} však není striktní identita vyžadována u parametrů řetězcových typů — skutečný parametr pak smí být libovolného typu řetězec.

{$Xstav}

Globální direktiva rozšířené syntaxe volání funkcí. Volání funkce je podle syntaxe jazyka výrazem a proto se standardně, tj. ve stavu {$X–}, může vyskytovat pouze tam, kde je výraz očekáván. Ve stavu {$X+} lze volání funkce použít i jako příkaz — pokud ovšem v daném kroku nezáleží na výsledku funkce nýbrž na vedlejších efektech jeho výpočtu.

XXI.2. 

Parametrické direktivy

Parametrickými direktivami jsou specifikovány vkládané a připojované soubory a požadavky na přidělení paměti. Název direktivy je opět tvořen jediným písmenem a parametry jsou od něj odděleny (aspoň jednou) mezerou.

{$I soubor}

Vložení obsahu textového souboru do zdrojového textu modulu. Při překladu zdrojového textu modulu se postupuje tak, jakoby na pozici výskytu direktivy byl uveden obsah souboru soubor.

Parametr soubor je systémová specifikace vkládaného souboru. Pokud neobsahuje příponu, bere se implicitně .pas. Pokud neobsahuje cestu k adresáři, je vkládaný soubor hledán nejprve v aktuálním adresáři a dále v adresářích, uvedených v položce Include directories dialogu Directories, který je přístupný příkazem Directories nabídky Options vývojového prostředí.

Direktiva nesmí být uvedena uvnitř příkazové části a vkládané soubory lze do sebe vnořit maximálně v patnácti úrovních.

{$L soubor}

Připojení externího kódu ke kódu modulu. Soubor soubor musí obsahovat kód v relokatibilním formátu (tzv. object-kód). Může být získán například překladem assemblerského podprogramu nebo jako produkt konverze binárního souboru utilitou binobj.exe. Ve zdrojovém textu modulu se pak uvádí pouze hlavička externího podprogramu a místo jeho těla direktiva external. Identifikátor podprogramu, uvedený v deklaraci hlavičky, se ovšem musí shodovat s veřejným jménem podprogramu, které je součástí připojovaného souboru.

Parametr soubor je systémová specifikace připojovaného souboru. Pokud neobsahuje příponu, bere se implicitně .obj. Pokud neobsahuje cestu k adresáři, je soubor hledán nejprve v aktuálním adresáři a dále v adresářích, uvedených v položce Object directories dialogu Directories, který je přístupný příkazem Directories nabídky Options vývojového prostředí.

Na umístění direktivy ve zdrojovém textu modulu nezáleží (nesmí být uvedena pouze uvnitř lexikálního elementu), pro přehlednost je vhodné umístit ji buď na jeho začátek nebo poblíž deklarace hlavičky podprogramu, jehož kód připojovaný soubor obsahuje.

{$M zásobník, minheap, maxheap}

Požadavek na přidělení paměti pro zásobník a heap programu. Direktivu lze uvést pouze na začátku zdrojového textu, nejpozději za hlavičkou programu (ve zdrojových textech programových jednotek je ignorována). Všechny tři parametry jsou celočíselné a vzájemně se oddělují jednou nebo více čárkami, středníky nebo mezerami.

Parametr zásobník je požadovaná velikost zásobníku v bytech. Povolené jsou hodnoty 1024 až 65 520. Parametr minheap resp. maxheap je požadovaná minimální (nezbytně potřebná) resp. maximální (nejvýše využitelná) velikost heapu v bytech, povolené jsou hodnoty 0 až 655 360, přičemž musí být minheap <= maxheap. Pokud je při spouštění programu méně volné paměti pro heap než požaduje minheap, nebude program spuštěn. Pokud je jí dostatek, ale méně než požaduje maxheap, přidělí se celá. Pokud je jí ještě více, přidělí se právě maxheap bytů.

Implicitní hodnoty parametrů direktivy (standardně 16 384, 0, 655 360) lze nastavit v dialogu Memory Sizes, který je přístupný příkazem Memory sizes nabídky Options vývojového prostředí.

XXI.3. 

Podmínkové direktivy

Podmínkové direktivy povolují nebo zakazují kompilaci částí zdrojového textu modulu. Kritériem mohou být například přítomnost aritmetického koprocesoru, verze překladače nebo uživatelem definované podmínkové symboly. Název každé direktivy je tvořen několika písmeny (jedním slovem) a případný parametr od něj musí být oddělen alespoň jednou mezerou.

{$DEFINE symbol}

Definuje podmínkový symbol symbol. Symbol zůstává definován až do výskytu direktivy {$UNDEF symbol} se stejným parametrem, nejpozději však do ukončení kompilace modulu. Je-li uvedený symbol již definován, nemá direktiva žádný efekt.

Později lze pomocí jiných direktiv otestovat, zda je uvažovaný symbol definován či nikoliv a podle výsledku testu přeložit či naopak vynechat označenou část zdrojového textu.

Syntax symbolů odpovídá syntaxi identifikátorů, na velikosti písmen rovněž nezáleží. Podmínkové symboly však nemají žádnou souvislost s datovými objekty programu — vyskytují se pouze ve zdrojovém textu modulu a do jeho cílového kódu se mohou promítnout pouze přeložením či vynecháním označené části zdrojového textu.

Existují následující standardní symboly (uvádím jen některé, ostatní se používají v programech pro Windows a chráněný mód DOSu):

VER70 Je definován při použití překladače jazyka Turbo Pascal (resp. Borland Pascal) verze 7.0. Jiné verze definují vlastní symboly (například VER55 je definován verzí Turbo Pascal 5.5).

MSDOS

Je definován při překladu programu pro reálný mód operačního systému MS DOS.

CPU86

Je definován při překladu programu na počítači s procesorem z řady 80x86.

CPU87

Je definován při překladu programu na počítači s aritmetickým koprocesorem z řady 80x87.

Definice standardních symbolů proběhne automaticky na začátku kompilace každého modulu. Dále s nimi lze zacházet jako s uživatelskými podmínkovými symboly. Například uvedení direktivy {$DEFINE CPU87} způsobí, že symbol CPU87 bude definován i za nepřítomnosti koprocesoru.

{$UNDEF symbol}

Zruší definici symbolu symbol. Uvedený symbol není po dobu kompilace zbývající části modulu definován (pokud není později redefinován direktivou {$DEFINE symbol} se stejným parametrem). Direktiva nemá žádný efekt, není-li uvedený symbol v okamžiku jejího zpracování definován.

{$IFDEF symbol}

Zdrojový text modulu mezi touto direktivou a prvním následujícím výskytem direktivy {$ELSE} nebo {$ENDIF} bude kompilován pouze pokud je definován podmínkový symbol symbol.

{$IFNDEF symbol}

Zdrojový text modulu mezi touto direktivou a prvním následujícím výskytem direktivy {$ELSE} nebo {$ENDIF} bude kompilován pouze pokud není definován podmínkový symbol symbol.

{$IFOPT stav_přepínače}

Zdrojový text modulu mezi touto direktivou a prvním následujícím výskytem direktivy {$ELSE} nebo {$ENDIF} bude kompilován pouze pokud se uvedený přepínač překladu nachází v uvedeném stavu. Například za direktivou {$IFOPT N+} bude zdrojový text kompilován jen při povoleném použití koprocesoru.

{$ELSE}

Zdrojový text modulu mezi touto direktivou a prvním následujícím výskytem direktivy {$ENDIF} bude kompilován v případě, pokud nebyla splněna podmínka v odpovídající direktivě {$IF...}.

{$ENDIF}

Ukončuje podmíněnou kompilaci, zahájenou odpovídající direktivou {$IF...}. Počet direktiv {$ENDIF} musí v každém modulu odpovídat počtu direktiv {$IF...} — ke každé direktivě {$IF...} musí být uvedena odpovídající {$ENDIF} a naopak.