XV.  

MODULÁRNÍ  PROGRAMOVÁNÍ


Turbo Pascal poskytuje prostředky pro vytváření tzv. programových jednotek, používaných převážně jako knihovny podprogramů a jiných prostředků (datových typů, konstant apod.). Produktem překladu zdrojového textu jednotky je samostatný modul, který může být později připojen ke kódu libovolného počtu hostitelských programů, aniž by bylo nutno jej při každém použití znovu přeložit. Jednotka tedy může být šířena ve tvaru přeloženého kódu, distributor nemusí poskytovat její zdrojový text.


POZNÁMKA: Vzorem termínu „(programová) jednotka“ je anglické slovo „unit“. V programátorské hantýrce se proto běžně vyskytují i termíny „unita“ resp. „unit“, vyslovované jako „junyta“ resp. „junyt“ a skloňované jako podstatná jména ženského (v druhém případě však často i mužského) rodu.

XV.1. 

Použití prostředků jednotek v hostitelských programech

Všechny programové jednotky, jejichž prostředky uvažovaný program využívá, musí být vyjmenovány v klauzuli uses, uvedené bezprostředně za hlavičkou jeho zdrojového textu (resp. na začátku zdrojového textu programu bez hlavičky). Výjimkou je standardní jednotka System (knihovna standardních prostředků jazyka), kterou každý program použije automaticky.

Obrázek 71: Klauzule uses

Cílový kód programu je pak sestaven spojením všech dílčích modulů — hlavního modulu programu a modulů všech použitých jednotek. Obsahuje-li zdrojový text uvažovaného programu například klauzuli

uses Matice, Vektory;
bude jeho cílový kód sestaven spojením čtyř modulů — hlavního modulu programu a modulů jednotek System, MaticeVektory.

Překlad zdrojového textu modulu (programu nebo jednotky) lze z vývojového prostředí odstartovat některým ze tří příkazů nabídky Compile:


POZNÁMKA: Pokud je ve vývojovém prostředí vydán příkaz ke spuštění programu před jeho kompilací, je automaticky provedeno Make.

Kód každé z přeložených jednotek je uložen na disk pod jménem jejího zdrojového textu a příponou .tpu. Po každé kompilaci programu je automaticky spuštěn spojovací program, který zajistí sloučení všech dílčích modulů do jediného celku cílového kódu programu. Cílový kód je ponechán v operační paměti (za účelem následného spouštění a ladění programu ve vývojovém prostředí) a případně i uložen na disk pod jménem souboru zdrojového textu programu a příponou .exe.


POZNÁMKA: Moduly jednotek, uvedených v klauzuli uses překládaného modulu, jsou vyhledávány v aktuální knihovně jednotek (standardně soubor turbo.tpl v podadresáři bin adresáře Turbo Pascalu) a v aktuálním pracovním adresáři. Případné další adresáře, které mají být prohledávány, lze zadat formou výčtu (oddělovačem je středník) v poli Unit directories dialogu Directories, který je přístupný příkazem Directories nabídky Options vývojového prostředí. V poli EXE & TPU directory téhož dialogu lze specifikovat adresář, ve kterém budou vytvářeny cílové soubory (implicitně se ukládají do pracovního adresáře).

XV.2. 

Struktura programové jednotky

Zdrojový text jednotky je formálně rozdělen do těchto částí: hlavička jednotky, interfejsová část, implementační částinicializační část. Všechny části jsou povinné a ve zdrojovém textu jednotky musí být obsaženy v uvedeném pořadí.

Obrázek 72: Programová jednotka

Hlavička jednotky   Na rozdíl od hlavičky programu nemůže hlavička jednotky obsahovat žádné parametry a je povinná. Podle rezervovaného slova unit totiž kompilátor rozlišuje zdrojový text jednotky od zdrojového textu programu a podle identifikátoru jednotku vyhledává při kompilaci modulů, které deklarují její použití.


POZNÁMKA: Aby jednotka byla překladačem nalezena, musí být její zdrojový text resp. kód uložen v souboru, jehož jméno tvoří prvních osm písmen identifikátoru jednotky. Například zdrojový text resp. kód jednotky s identifikátorem MojePrvniJednotka musí být uložen v souboru mojeprvn.pas resp. mojeprvn.tpu.

Obrázek 73: Hlavička jednotky

Interfejsová část   Tvoří rozhraní mezi jednotkou a moduly, které ji používají — obsahuje veškeré údaje, potřebné pro přístup k veřejným prostředkům jednotky. Je uvozena rezervovaným slovem interface, za ním následuje případná klauzule uses (jednotka může využívat prostředky jiných jednotek) a zbytek je tvořen deklaracemi veřejných konstant, typů, proměnných a (pouze) hlaviček veřejných podprogramů jednotky.

Obrázek 74: Část interface

Klauzule uses se uvádí v případech, kdy jsou veřejné prostředky jednotky deklarovány pomocí (veřejných) prostředků jiných jednotek. Prostředky těchto pomocných jednotek jsou pak přístupné v celém zdrojovém textu uvažované jednotky, nikoli však v dalších modulech, které uvažovanou jednotku používají:

unit Prvni;           unit Druha;                  program Hlavni;

interface             interface                     uses Druha;
 const Min = 10;       uses Prvni;                  var I: Int;
       Max = 20;       type Int = Min .. Max;
...                   ...                          ...
Jednotka Druha má v klauzuli uses své interfejsové části deklarováno užití jednotky Prvni, smí tedy použít externí konstanty MinMax k deklaraci typu Int. Program Hlavni deklaruje pouze užití jednotky Druha, proto smí použít její veřejný typ Int, ne však veřejné konstanty MinMax jednotky Prvni. Pokud by program Hlavni obsahoval například příkaz I := Min, byla by při jeho kompilaci hlášena chyba — neznámý identifikátor Min. Pro úspěšný překlad programu Hlavni by musela být jeho klauzule uses rozšířena o identifikátor jednotky Prvni.

Implementační část   Implementační část programové jednotky začíná bezprostředně za částí interfejsovou, od níž je oddělena rezervovaným slovem implementation. Obsahuje případnou klauzuli uses, dodatečné deklarace těl veřejných podprogramů jednotky a deklarace privátních prostředků jednotky (soukromých, neviditelných pro moduly jednotku využívající) — různé pomocné proměnné, podprogramy a další prostředky, které jsou využívány veřejnými podprogramy nebo v inicializační části jednotky. Dodatečné deklarace veřejných podprogramů lze v implementační části uvádět v libovolném pořadí a s hlavičkou ve zkráceném tvaru, jako by byly předběžně deklarovány s direktivou forward.

Obrázek 75: Část implementation

Prostředky jednotek, uvedených v klauzuli uses implementační části, mohou být využity pouze ve zbytku zdrojového textu uvažované jednotky — v její implementační a inicializační části. Pokud jsou klauzule uses uvedeny současně v interfejsové i v implementační části uvažované jednotky, nesmí obsahovat týž identifikátor (prostředky jednotek, jejichž užití bylo deklarováno již v interfejsové části uvažované jednotky, jsou přístupné i v její části implementační a inicializační).

Inicializační část   Pokud není třeba žádných inicializačních akcí, obsahuje inicializační část jednotky pouze rezervované slovo end, jinak odpovídá syntaxí příkazové části bloku. V příkazové části jsou přístupné veřejné i privátní prostředky vlastní jednotky i veřejné prostředky jednotek externích (uvedených v klauzuli uses interfejsové nebo implementační části vlastní jednotky).

Obrázek 76: Inicializační část

Příkazová část jednotky je vykonávána pouze jako součást programu, kterým byla jednotka použita. Samostatně jednotku spouštět nelze (podobně jako nelze samostatně spouštět podprogram). Při ladění jednotky je proto vždy zapotřebí použít její prostředky nějakým testovacím programem.


PŘÍKLAD: Následující jednotka implementuje jednoduché prostředky pro souřadnicově orientovaný výstup textu na displej a práci s barvami.

{======================================================================}
unit Displej;
{======================================================================}

interface

 const
 {---------------------------------------------------------------------}
   Cerna      = 0;                        TmavoSeda    =  8;
   Modra      = 1;                        IntModra     =  9;
   Zelena     = 2;                        IntZelena    = 10;
   Azurova    = 3;                        IntAzurova   = 11;
   Cervena    = 4;                        IntCervena   = 12;
   Fialova    = 5;                        IntFialova   = 13;
   Hneda      = 6;                        Zluta        = 14;
   SvetleSeda = 7;                        Bila         = 15;
 {---------------------------------------------------------------------}
 { barvy normální intenzity               barvy se zvýšenou intenzitou }

 {---------------------------------------------------------------------}
   Atribut: Byte = Bila + Cerna * 16;
 {---------------------------------------------------------------------}
 { Aktuální atribut, vkládaný do videopaměti při výpisu znaku. Čtyři   }
 { nejnižší bity určují barvu popředí (0 až 15), tři následující barvu }
 { pozadí (0 až 7) a nejvyšší bit nastavuje příznak blikání (1 bliká,  }
 { 0 nebliká). Počáteční hodnota (15 = 00001111 binárně) definuje bílé }
 { znaky na černém pozadí, neblikající.                                }

 var
 {---------------------------------------------------------------------}
   Kurzor: record Sloupec, Radek : Byte end absolute $40:$50;
 {---------------------------------------------------------------------}
 { Aktuální poloha kurzoru. Sloupce jsou číslovány od 0 zleva, řádky   }
 { od 0 shora. Počáteční hodnota je dána polohou kurzoru v okamžiku    }
 { startu programu (na uvedené adrese udržuje souřadnice kurzoru       }
 { operační systém, deklarací proměnné Kurzor jsou pouze zpřístupněny. }

 {---------------------------------------------------------------------}
 procedure JdiNaXY (X, Y: Byte);
 {---------------------------------------------------------------------}
 { Nastaví kurzor na pozici o souřadnicích X (sloupec) a Y (řádka),    }
 { pokud neleží mimo obrazovku.                                        }

 {---------------------------------------------------------------------}
 procedure PisString (S: string);
 {---------------------------------------------------------------------}
 { Vypíše řetězec znaků S aktuálním atributem od aktuální polohy       }
 { kurzoru.                                                            }

 {---------------------------------------------------------------------}
 procedure Vymaz;
 {---------------------------------------------------------------------}
 { Vyplní obrazovku mezerami s aktuálním atributem.                    }

 {---------------------------------------------------------------------}
 procedure Inkoust (Ink: Byte);
 {---------------------------------------------------------------------}
 { Nastaví novou barvu popředí do proměnné Atribut. Ink je upraven na  }
 { rozsah 0-15. Pozadí a příznak blikání zůstávají zachovány.          }

 {---------------------------------------------------------------------}
 procedure Papir (Pap: Byte);
 {---------------------------------------------------------------------}
 { Nastaví novou barvu pozadí do proměnné Atribut. Pap je upraven na   }
 { rozsah 0-7. Popředí a příznak blikání zůstávají zachovány.          }

 {---------------------------------------------------------------------}
 procedure Blikani (Blik: Boolean);
 {---------------------------------------------------------------------}
 { Nastaví příznak blikání v proměnné Atribut. False nebliká, True     }
 { bliká. Barvy pozadí a popředí zůstávají zachovány.                  }

implementation

 type Znak = record                            { slovo ve videopaměti: }
              Symbol : Char;                   { znak                  }
              Barva  : Byte                    { atribut               }
             end;

 var  VideoRAM: array [0..24, 0..79] of Znak   { vystihuje strukturu   }
                absolute $B800:0;              { videopaměti           }

 procedure JdiNaXY (X, Y: Byte);
 {-----------------------------}
 begin { JdiNaXY }
  if (X < 80) and (Y < 25) then      { jsou-li požadované souřadnice   }
   with Kurzor do                    { kurzoru "uvnitř" obrazovky      }
    begin
     Sloupec := X;                   { vložení požadovaných souřadnic  }
     Radek   := Y;                   { do proměnné Kurzor              }
     Write('')                       { výpis prázdného řetězce slouží  }
    end                              { optický přesun kurzoru na novou }
 end; { JdiNaXY }                    { pozici obrazovky                }

 procedure PisZnak (Ch: Char);       { výpis znaku Ch na pozici kurzoru}
 {---------------------------}
 begin { PisZnak }
  with Kurzor do
   begin
    with VideoRAM[Radek, Sloupec] do { na aktuální pozici kurzoru      }
     begin
      Symbol := Ch;                  { vlož znak Ch                    }
      Barva  := Atribut              { s aktuálním atributem Atribut   }
     end;
    if Sloupec < 79 then             { není-li na konci řádky          }
     Inc(Sloupec)                    { posun o pozici vpravo           }
    else                             { je-li na konci řádky            }
     Writeln                         { posun na začátek nové řádky     }
   end                               { s případným "odrolováním"       }
 end; { PisZnak }

 procedure PisString (S: String);
 {------------------------------}

  var I: Byte;                       { pomocná proměnná                }

 begin { PisString }
  for I := 1 to Length(S) do         { všechny znaky řetězce           }
   PisZnak(S[I]);                    { vypiš                           }
  Write('')                          { přesuň kurzor i opticky         }
 end; { PisString }

 procedure Vymaz;                    { výmaz obrazovky                 }
 {--------------}

  var R, S: Byte;                    { pomocné proměnné                }

 begin { Vymaz }
  for R := 0 to 24 do                { do všech řádek                  }
   for S := 0 to 79 do               { do všech sloupců                }
    with VideoRAM[R, S] do
     begin
      Symbol := ' ';                 { vlož znak mezera                }
      Barva  := Atribut              { s aktuálním atributem           }
     end;
  JdiNaXY(0, 0)                      { přesuň kurzor do levého horního }
 end; { Vymaz }                      { rohu obrazovky                  }

 procedure Inkoust (Ink: Byte);
 {----------------------------}
 begin { Inkoust }
  Atribut := (Atribut and $F0) or (Ink and $0F)   { přepis bitů barvy  }
 end; { Inkoust }                                 { popředí atributu   }

 procedure Papir (Pap: Byte);
 {--------------------------}
 begin { Papir }
  Atribut := (Atribut and $8F) or                 { přepis bitů barvy  }
             ((Atribut and $07) shl 4)            { pozadí atributu    }
 end; { Papir }

 procedure Blikani (Blik: Boolean);
 {--------------------------------}
 begin { Blikani }
  if Blik then                                    { nastavení příznaku }
   Atribut := Atribut or $80                      { blikání atributu   }
  else                                            { potlačení příznaku }
   Atribut := Atribut and $7F                     { blikání atributu   }
 end; { Blikani }

end. { unit }

Při pozorném čtení z předchozího textu vyplývá, že žádný znak není procedurou PisString použit jako řídící (standardních výstupních procedur WriteWriteln je použito pouze pro posun kurzoru, nikoliv pro výpis znaků). Všechny znaky budou tedy zobrazeny.


PŘÍKLAD: Program DemoDisplej využívá prostředků jednotky Displej k tisku tabulky všech znaků znakové sady. Tabulka je tištěna na obrazovku po šestnáctiznakových řetězcích v jednotlivých řádkách (lexikografická reprezentace znaků #0, #32 a #255 je mezera).

{======================================================================}
program DemoDisplej;
{======================================================================}

 uses  Displej;                             { použit unit Displej      }

 const Okraj = #176;                        { znak okrajů tabulky      }
 var   I     : Byte;                        { pomocné proměnné         }
       Z     : Char;
       S     : string;

begin { program }
 Vymaz;                                     { výmaz obrazovky          }
 Papir(SvetleSeda);                         { barvy znaků pro další    }
 Inkoust(Cervena);                          { výpis                    }
 S := Okraj;                                { horní okraj tabulky      }
 for I := 0 to 16 do
  S := S + Okraj;
 JdiNaXY(32, 3);
 Blikani(True);
 PisString(S);
 for I := 0 to 15 do                        { vnitřní řádky tabulky    }
  begin
   JdiNaXY(32, 4 + I);                      { kurzor na levý okraj     }
   PisString(Okraj);                        { výpis levého okraje      }
   S := '';                                 { výpočet řetězce znaků    }
   for Z := Chr(16*I) to Chr(16*I+15) do    { uvnitř řádky tabulky     }
    S := S + Z;
   Blikani(False);                          { znaky nebudou blikat     }
   PisString(S);                            { výpis řetězce            }
   Blikani(True);                           { okraj bude blikat        }
   PisString(Okraj)                         { výpis pravého okraje     }
  end;
 S := Okraj;                                { dolní okraj tabulky      }
 for I := 0 to 16 do
  S := S + Okraj;
 JdiNaXY(32, 20);
 PisString(S);
 Readln                                     { čekání na stisk klávesy  }
end. { program }                            { Enter                    }

XV.3. 

Kruhové odkazy mezi programovými jednotkami

Pokud dvě nebo více jednotek používá navzájem svých prostředků, dochází ke kruhovým odkazům. Nechť například jednotka Prvni volá proceduru Proc2, deklarovanou v jednotce Druha a jednotka Druha proceduru Proc1, deklarovanou v jednotce Prvni. Problém tohoto kruhového odkazu je podobný jako při vzájemné rekurzi podprogramů a spočívá v pořadí kompilace jednotek. Aby mohla být zkompilována jednotka Prvni, musí být již zkompilována jednotka Druha, neboť Prvni používá její prostředky, a naopak.

Pokud jsou klauzule uses, tvořící kruhový odkaz, umístěny v interfejsových částech jednotek, dojde při kompilaci kterékoliv z jednotek k chybě — nedovolený kruhový odkaz. Pokud jsou však tyto klauzule umístěny až v implementačních částech jednotek (což je ovšem možné pouze pokud externí prostředky nejsou využívány již v interfejsových částech jednotek), překlad proběhne úspěšně.


PŘÍKLAD: Následující dvojice jednotek demonstruje kruhový odkaz — jednotka Prvni implementuje proceduru WriteXY pomocí prostředků jednotek Displej (viz výše) a Druha, jednotka Druha pak proceduru Chyba pomocí procedury WriteXY jednotky Prvni.

{======================================================================}
unit Prvni;
{======================================================================}

interface

 {---------------------------------------------------------------------}
 procedure WriteXY (X, Y: Byte; S: string);
 {---------------------------------------------------------------------}
 { Vypisuje řetězec S na pozici obrazovky o souřadnicích X (sloupec)   }
 { a Y (řádka).                                                        }

implementation

 uses Displej, Druha;     { používá proceduru JdiNaXY, implementovanou }
                          { jednotkou Displej a proceduru Chyba,       }
                          { implementovanou jednotkou Druha            }

 procedure WriteXY (X, Y: Byte; S: string);
 {----------------------------------------}
 begin { WriteXY }
  if (X < 80) and (Y < 25) then     { jsou-li specifikované souřadnice }
   begin                            { přípustné                        }
    JdiNaXY(X, Y);                  { nastavení pozice kurzoru         }
    Write(S)                        { výpis řetězce                    }
   end
  else                              { jinak                            }
   Chyba('Mimo obrazovku !')        { reakce na chybné souřadnice      }
 end; { WriteXY }

end. { unit }

{======================================================================}
unit Druha;
{======================================================================}

interface

 {---------------------------------------------------------------------}
 procedure Chyba (Zprava: string);
 {---------------------------------------------------------------------}
 { Zobrazí chybové hlášení Zprava uprostřed poslední řádky obrazovky.  }

implementation

 uses Prvni;              { používá proceduru WriteXY, implementovanou }
                          { jednotkou Prvni                            }

 procedure Chyba (Zprava: String);
 {-------------------------------}

  var X: Byte;                   { sloupec pozice prvního znaku zprávy }

 begin { Chyba }
  if Length(Zprava) > 78 then    { výpočet pozice prvního znaku zprávy }
   X := 0
  else
   X := (79-Length(Zprava)) div 2;
  WriteXY(X, 24, Zprava)         { výpis                               }
 end; { Chyba }

end. {unit}

Kruhové odkazy mezi jednotkami jsou umožněny jejich postupnou kompilací. Před kompilací implementační části jednotky Prvni musí být již zkompilována interfejsová část jednotky Druha a před kompilací implementační části jednotky Druha musí být již zkompilována interfejsová část jednotky Prvni. Interfejsové části obou jednotek však lze zkompilovat přímo, neboť neobsahují odkazy na žádné na nich závislé moduly. Po kompilaci interfejsových částí obou jednotek lze tedy bez problémů zkompilovat i zbývající části jednotek.

Za předpokladu zahájení kompilace jednotky Prvni (příkazem Make nebo Build vývojového prostředí) proběhne postupná kompilace zhruba v těchto krocích:

XV.4. 

Redeklarace a stínění v modulech

Bloky programových jednotek jsou hierarchicky nadřazeny bloku modulu (programu nebo jednotky), který je používá. Hierarchicky nejvyšším je blok (automaticky použité) jednotky System, následují bloky ostatních použitých jednotek v pořadí jejich indentifikátorů v klauzuli uses uvažovaného modulu, jehož vlastní blok je vnořen nejhlouběji. Pokud je tedy v modulu redeklarován identifikátor, který náleží některému z veřejných prostředků použitých jednotek, je externí význam identifikátoru zastíněn významem interním (lokálním).

unit Prvni;           unit Druha;

interface             interface
 procedure Kresba;     uses Prvni;
                       var  Kresba: Byte;
...                   ...
Například Kresba má v jednotce Prvni jednoznačně význam identifikátoru její veřejné procedury, kdežto v jednotce Druha proměnné typu Byte, neboť lokální význam identifikátoru je upřednostněn.
program Hlavni1;      program Hlavni2;

 uses Prvni, Druha;    uses Druha, Prvni;
...                   ...
V programu Hlavni1Kresba význam identifikátoru veřejné proměnné jednotky Druha, v programu Hlavni2 pak význam identifikátoru veřejné procedury jednotky Prvni — opět je upřednostněn „nejlokálnější“ význam, daný pořadím jednotek v klauzuli uses uvažovaného programu.

Kvalifikovaný identifikátor   Přístup k zastíněným prostředkům hierarchicky vyšších bloků je umožněn použitím tzv. kvalifikovaných identifikátorů. Kterýkoliv identifikátor konstanty, proměnné, typu nebo podprogramu lze kvalifikovat předřazením identifikátoru některé z použitých jednotek. Oddělovačem identifikátoru jednotky (vpředu) a identifikátoru jejího prostředku (vzadu) je tečka (uprostřed), podobně jako v přístupu k položkám záznamu. Význam kvalifikovaného identifikátoru je pak stejný v kterémkoliv bloku — například Prvni.Kresba má význam veřejné procedury Kresba jednotky Prvni jak v jednotce Prvni, tak v jednotce Druha a v programech Hlavni1Hlavni2).

Obrázek 77: Kvalifikovaný identifikátor

Záměrné redeklarace   Zastínění významu nekvalifikovaného identifikátoru jeho redeklarací lze využít pro lokální modifikaci prostředků jednotek, jejichž zdrojový text není k dispozici. Například níže uvedený modul využívá prostředků jednotky Displej, zavádí však vlastní proceduru Vymaz, která před každým výmazem obrazovky (realizovaným voláním veřejné procedury Vymaz jednotky Displej) vloží do proměnné Atribut hodnotu 15. Veškeré odkazy nekvalifikovaným identifikátorem Vymaz jsou pak v modulu směrovány na jeho lokální proceduru.

uses Displej;

procedure Vymaz;
{--------------}
begin { Vymaz }
 Atribut := 15;
 Displej.Vymaz
end; { Vymaz }
...
Stejným způsobem lze stínit a kvalifikovat také standardní identifikátory (deklarované jednotkou System).

XV.5. 

Závislost modulů

Každý modul je přímo závislý na jednotkách, které jsou vyjmenovány v jeho klauzuli (klauzulích) usesnepřímo závislý na jednotkách, na nichž jsou (přímo nebo nepřímo) závislé vyjmenované jednotky. Při kompilaci kteréhokoliv modulu musí být k dispozici všechny jednotky, na nichž je závislý, ať už přímo či nepřímo. Spojování kódů jednotlivých modulů se totiž provádí až při kompilaci programu. Cílový kód programu (soubor .exe) již obsahuje kód všech svých zdrojových modulů a může být provozován v jejich nepřítomnosti.

Je-li dodatečně pozměněn zdrojový text jednotky, je nutno ji rekompilovat. Pokud byla pozměněna interfejsová část jednotky, musí být rekompilovány i všechny jednotky na ní závislé. Pokud se však provedené změny týkaly pouze implementační a inicializační části jednotky, rekompilace závislých jednotek není nutná. Rekompilace na modifikované jednotce závislého programu je samozřejmě nutná vždy.

XV.6. 

Rozsah a rozložení kódu programu v operační paměti

Data   Veškeré globální statické proměnné a veškeré typové konstanty všech modulů, ze kterých je program vytvořen, jsou alokovány do společného datového segmentu programu, jehož velikost nesmí převýšit 64 KB. Lokální proměnné, deklarované v blocích podprogramů všech modulů, jsou při aktivaci svého podprogramu vytvořeny v zásobníkovém segmentu, který je rovněž společný pro celý program. Pro alokaci dynamických proměnných používají všechny moduly programu společný heap.

Direktiva {$M...}, definující požadovanované velikosti zásobníku a heapu programu (viz požadavek na přidělení paměti), se uvádí ve zdrojovém textu programu (ve zdrojových textech jednotek nemá žádný význam ani efekt).

Kód   Příkazová část každého modulu programu má k dispozici vlastní kódový segment. Maximální velikost každého z kódových segmentů programu opět nesmí přesáhnout 64 KB, jejich počet však může být libovolně vysoký. Souhrnný rozsah kódu je tedy omezen prakticky jen dostupnou kapacitou operační paměti.

Základní pořadí provedení příkazových částí jednotlivých modulů programu je dáno pořadím identifikátorů jednotek v klauzuli uses programu. Příkazová část jednotky je však v takto určeném okamžiku odstartována pouze v případě, že již nebyla vykonána dříve, a před ní jsou podle stejného pravidla vykonány příkazové části jednotek, na nichž je závislá. Naposled je odstartována příkazová část programu.

unit Prvni;           unit Druha;           program Hlavni;

interface             interface              uses Prvni, Druha;
implementation        implementation
begin                 begin                 begin
 Writeln('Prvni')      Writeln('Druha')      Writeln('Hlavni')
end.                  end.                  end.
Po kompilaci a spuštění programu Hlavni jsou na obrazovku vytištěny tři řetězce v pořadí 'První', 'Druhá' a 'Hlavní'. Přidáním klauzule uses Druha; do jednotky Prvni se změní pořadí vytištěných řetězců na 'Druhá', 'První' a 'Hlavní'.

Veřejné podprogramy, deklarované v interfejsových částech jednotek, jsou automaticky kompilovány pro daleký (far) model volání (jinak by nemohly být volány z jiných modulů s jinou segmentovou částí adresy), nezávisle na nastavení direktivy kompilátoru {$F} (viz implicitní model volání podprogramů).

XV.7. 

Standardní programové jednotky

Součástí programového balíku Turbo Pascalu je i sada programových jednotek, pro něž používám souhrnné označení „standardní jednotky“. V následujících kapitolách jsou popsány vybrané prostředky těchto standardních programových jednotek:

  jednotka     implementované prostředky  
System standardní prostředky jazyka
Printer výstup textu na tiskárnu
Dos přístup k rutinám operačního systému
Crt ovládání klávesnice, textových módů obrazovky a tónového generátoru
Graph ovládání grafických módů obrazovky