Programové jednotky Dos, Overlay

Programová jednotka Dos obsahuje příkazy, které usnadňují spolupráci s operačním systémem (Dnes je ovšem aktuálnější jednotka WinDos, která umožňuje spolupráci s operačním systémem Windows). Jednotka Overlay umožňuje využívat překryvné moduly a maximálně tak šetřit pamětí (v dnešní době se již nepoužívá, pár kilobytů nehraje dneska tak zásadní roli).

Jednotka Dos

Typy proměnných

Typy obsahující informace o souborech

type
   FileRec = record        {Držadlo pro soubory, obsahuje potřebné informace}
        Handle    : word; {Držadlo}
        Mode    : word; {Mód, ve kterém je soubor otevřen, viz módy přístupu}
        RecSize : word;    {Velikost položky v bytech}
        Private : array[1..26] of byte;    {Vnitřní data}
        UserData: array[1..16] of byte;    {Data přístupná uživateli}
        Name    : array[0..79] of char; {Jméno (celá cesta) k souboru}
        end;
   TexBuf = array[0..127] of char;    {Tyto typy slouží pro práci s textovými soubory}
   TextRec = record
        Handle    : word;    {Držadlo}
        Mode    : word;    {Mód přístupu, viz módy přístupu}
        BufSize : word; {Velikost textového bufferu}
        Private    : word;    {??}
        BufPos    : word; {Aktuální pozice v bufferu}
        BufEnd    : word; {Konec bufferu}
        BufPtr    : ^TextBuf;    {Ukazatel na buffer}
        OpenProc :pointer;    {Procedura pro otevření souboru}
        InOutProc:pointer;    {Procedura pro čtení/zápis}
        FlushProc:pointer;    {Procedura pro vyprázdnění bufferu}
        CloseProc:pointer;    {Procedura pro uzavření}
        UserData :array[1..16] of byte; {Uživatelská data}
        Name    : array[0..79] of char;    {Jméno souboru - celá cesta}
        Buffer    : TextBuf;    {Buffer}
       end;

Proměnná typu soubor musí obsahovat veškeré výše uvedené položky. Ty však nejsou "veřejně" přístupné, chceme-li se k nim dostat, musíme provést přetypování. Je tedy možná následující konstrukce:

if FileRec(fout).Mode=fmClosed then Writeln('Soubor zatím není otevřen');

FileRec(fout) zde tedy neznamená funkci, ale pouhou typovou změnu (type-casting) proměnné.

Typy pro práci se soubory

Tyto řetězcové typy se používají především při práci s procedurou FSplit.

type
   PathStr    = string[79];    {Celé jméno, včetně cesty a přípony}
   DirStr    = string[67];    {Cesta}
   NameStr    = string[8];    {Jméno bez přípony}
   ExtStr    = string[4];    {Přípona}

Typy pro vyhledávání souborů

type
   SearchRec = record
        Fill :    array[1..21] of byte;    {Data operačního systému, neměnit}
        Attr :    byte;    {Atribut souboru - viz konstanty atributů}
        Time :    longint;{Zhuštěný údaj o datu vytvoření souboru, 
                "zčitelnit" lze pomocí procedury UnPackTime}
        Size :    longint;{Velikost souboru v bytech}
        Name :    string[12];{Jméno souboru}
          end;        

Typy pro práci s datem a časem

type
   DateTime = record
        Year, Month, Day, Hour, Min, Sec : word;
          end;

Anglicky snad umíte, že... Povolené hodnoty pro rok jsou 1980 až 2099, pro měsíce a dny jsou jasné...

Povolené časové hodnoty

Typy pro práci s registry

Tento typ slouží pro potřeby procedur Intr a MsDos. Přistupovat lze buď k šestnáctibitovým registrům, či k osmibitovým. (Architekturu procesoru doufám znáte).

type Registers = record
           case integer of
            0: (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags:word);
            1: (AL,AH,BL,BH,CL,CH,DL,DH : byte;)
           end;

Proměnné

Jednotka Dos vlastně definuje jedinou svou proměnnou :

var DosError : integer;

Tato proměnná obsahuje číslo chybového stavu (či nulu, nenastala-li chyba.) Kódy chyb jsou shodné s kódy v systému MS-DOS :

Kód Popis Anglicky
0 Bez chyby No error
2 Soubor nenalezen File not found
3 Cesta nenalezena Path not found
5 Přístup odepřen Access denied
6 Špatné manipulační číslo ( = držadlo z FileRec) Invalid handle
8 Nedostatek paměti Not enough memory
10 Špatné prostředí procesu Invalid environment
11 Špatný formát Invalid format
18 Více souborů není No more files

Číslo 18 se používá v souvislosti s FindFirst a FindNext.

Konstanty

Konstanty příznaků

Předpokládám, že znáte význam význam registru příznaků (Flags) a jeho jednotlivých složek.
Uvedené konstanty zjednodušují zjištění nastavených příznaků. Např. R.Flags and FCarry <> 0 je true, pokud je nastaven příznak Carry (při poslední operaci došlo k přenosu ...).

const
   FCarry    = $0001;
   FParity    = $0004;
   FAuxiliary    = $0010;
   FZero    = $0040;
   FSign    = $0080;
   FOverflow    = $0800;

Konstanty režimů přístupu k souboru

const
   fmClosed    = $D7B0;    {Soubor je uzavřen}
   fmInput    = $D7B1;    {Soubor je otevřen pro zápis}
   fmOutput    = $D7B2;    {Soubor je otevřen pro čtení}
   fmInOut    = $D7B3;    {Soubor je otevřen pro čtení i zápis}

Konstanty atributů souborů

const
   ReadOnly    = $01;
   Hidden    = $02;
   SysFile    = $03;
   VolumeID    = $04;
   Directory    = $10;
   Archive    = $20;
   AnyFile    = $3F;  

Procedury a funkce

Stav disku

Stav disku
Pořadí Příkaz Význam
1 Diskfree(Drive : Word):Longint; Velikost volného místa na disku v bytech
2 DiskSize(Drive: Word) : Longint; Celková velikost disku v bytech

Správa souborů

Procedury a funkce pro správu souborů (jednotka Dos)
Pořadí Příkaz Význam
1 FindFirst(Path:string;Attr:byte;var S:SearchRec); Najde první soubor vyhovující kritériím (lze použít hvězdičková konvence), výsledek zapíše do S
2 FindNext(var S:SearchRec); Najde další výskyt požadovaného souboru
3 FExpand(Path:PathStr) : string; Rozvine jméno souboru na úplné (včetně disku a celé cesty)
4 FSearch(Path:PathStr;DirList : string) : string; Hledá v seznamu adresářů DirList soubor s názvem Path, vrátí celou cestu, nejčastěji se používá spolu s DirList=GetEnv('PATH'); - s aktuálním nastavením cest...
5 GetFAttr(var f; var Attr : word); Vrátí atributy daného souboru, jednotlivé atributy viz konstanty atributů
6 SetFAttr(var f; Attr : word); Nastaví atributy daného souboru

Práce s datem a časem

Procedury a funkce pro práci s datem i časem (jednotka Dos)
Pořadí Příkaz Význam
1 GetDate(var Year,Month,Day,DayOfWeek : word); Vrátí aktuální datum
2 GetTime(var Hour, Minute, Second, Sec100 : word); Vrátí aktuální čas
3 SetDate(Year, Month, Day : word); Nastaví nové aktuální datum
4 SetTime(Hour, Minute, Second, Sec100 : word); Nastaví nový aktuální čas
5 GetFTime(var f; var Time : longint); Vrátí datum a čas poslední aktualizace daného souboru (ve zhuštěné formě)
6 SetFTime(var f; Time : longint); Nastaví čas poslední aktualizace souboru
7 PackTime(var DT : DateTime; var Time:longint); Zabalí normální datum a čas(DT) do zhuštěné podoby Time
8 UnpackTime(Time : longint; var DT : DateTime); Rozbalí zhuštěné datum a čas (Time) do čitelné podoby (DT)

Správa přerušení

Funkce a procedury pro správu přerušení (jednotka Dos)
Pořadí Příkaz Význam
1 GetIntVec(IntNo : byte; var Vector : pointer); Do Vector uloží ukazatel na obslužnou rutinu přerušení číslo IntNo
2 SetIntVec(IntNo : byte; Vector : pointer); Nastaví obslužnou rutinu přerušení na danou adresu
3 Intr(IntNo : byte; var Regs : Registers); Spustí přerušení IntNo s příslušnými registry - viz Registry
4 MsDos(var Regs: Registers); Spustí přerušení $21 - služby MS-Dosu s příslušnými registry - viz Registry
5 SwapVectors; rohodí současné vektory přerušení s hodnotami umístěnými v SaveIntnn. Nejčastěji se používá před zavoláním procedury Exec. Zavoláním SwapVectors zajistíme, že spuštěný proces se nebude "vrtat" v přerušených našeho programu a naopak.

Raději si to ukážeme na příkladu :

SwapVectors; {Prohodíme vektory přerušení na původní systémové hodnoty}
Exec(...);    {Spouštíme nějaký externí proces, 
        ten nebude mít ponětí, že je spuštěn z našeho programu}
SwapVectors; {Prohodíme vektory zpět, na naše "programové" hodnoty}

Správa procesů

Příkazy pro správu procesů (jednotka Dos)
Pořadí Příkaz Význam
1 DosExitCode : word; Vrací ukončovací kód podřazeného procesu (0..normální ukončení, 1..ukončení pomocí Ctrl-C,2..ukončení po chybě, 3..ukončení pomocí Keep - rezidentní programy)
2 DosVersion : word; Číslo verze MS-Dosu Lo(DosVersion) je první hodnota a Hi(DosVersion) je druhá hodnota (ta za tečkou)
3 Exec(Path, CmdLine : string); Spustí proces (prostě nějaký EXE nebo COM soubor, chceme-li spustit příkaz MS-DOSu, použijeme "COMMAND.COM /C ...")
4 EnvCount : integer; Počet proměnných nastavených v daném prostředí (taková proměnná je např. PATH, ...)
5 GetEnv(EnvVar : string) : string; Vrátí danou hodnotu určené proměnné
6 EnvStr(Index : integer) : string; Vrátí specifikovaný řetězec (proměnnou), která je definována v prostředí na Index-tém místě
7 GetCBreak(var Break: boolean); Vrátí-li true, Ctrl-Break ukončuje program
8 SetCBreak(var Break : boolean); Nastaví, jestli Ctrl-Break ukončuje program
9 GetVerify(var Verify : boolean); Vrátí, zde zápis na disk ověřuje
10 SetVerify(Verify : boolean); Nastaví, zda se zápis na disk bude ověřovat
11 Keep(ExitCode : word); Ukončí program, ale ponechá ho v paměti (rezidentní), ExitCode je kód ukončení, v paměti zůstává vše, je nutné správně nastavit alokování paměti pomocí {$M}, rezidentní program musí být navázán na nějaké přerušení (pokud se jedná o důležité přerušení, nezapomeňte zavolat i původní obslužnou rutinu, jinak zbortíte počítač)

Jednotka Overlay

Jednotka Overlay se dá použít pouze v reálném režimu procesoru (dnes skoro vše běhá v režimu chráněném). Chceme-li ji použít, je nutné, aby jednotky, které chceme použít jako překryvné byly přeloženy s direktivami překladače {$F+} a {$O+}. Hlavní program pak musí být přeložen s direktivou {$F+}. Dále je nutné, aby překryvné jednotky byly v uses uvedeny až za jednotkou Overlay. Pokud mají nějakou inicializační část, je nutné, aby před zavoláním této inicializační části byla zavolána procedura OvrInit; (ta musí být tedy uvedena v inicializační části nějaké jednotky, která následuje za Overlay a přitom je před překryvnými jednotkami, nejčastěji se tedy vytvoří samostatná jednotka MyInit, která pouze zavolá ve své inicializační části OvrInit a jinak nic nedělá).

Ze standardních programových jednotek lze jako překryvnou použít pouze jednotku Dos. Dále nelze jako překryvné použít ty jednotky, které do paměti nahrávají grafický driver či obsahují interrupt funkce či procedury.

Typy proměnných

Pro svou práci definuje jednotka Overlay jediný speciální typ proměnné.

type OvrReadFunc = function(OvrSeg : word) : integer;

Konstanty

Tyto konstanty slouží ke zjištění výsledku dané operace (výsledná hodnota je uložena v OvrResult)

const
   ovrOK      = 0; {Operace proběhla bez chyby}
   ovrError      =-1; {Chyba správce překryvných jednotek}
   ovrNotFound     =-2; {Překryvný soubor nenalezen}
   ovrNoMemory   =-3; {Nedostatek paměti}
   ovrIOError     =-4; {I/O chyba}
   ovrNoEMSDriver=-5; {EMS není k dispozice}
   ovrNOEMSMemory=-6; {Nedostatek paměti pro EMS} 

Inicializované proměnné

Inicializované proměnné obsahují informace o nastavení manažeru překryvných jednotek. Jejich změnou lze dosáhnout změny nastavení. Většina těchto proměnných je definována již v jednotce System, pouze pět zde uvedených je definováno přímo v jednotce Overlay. Většinu z těchto proměnných není důvod měnit, programátor s nimi prakticky nepřijde do styku, k nastavení parametrů se totiž používá spíše uvedených procedur a funkcí.

Inicializované proměnné jednotky Overlay
Pořadí Proměnná:Typ Význam
1 OvrCodeList : word; Code segment, za žádných okolností bychom ji neměli měnit
2 OvrDebugPtr : pointer; Ukazatel pro potřeby debuggingu
3 OvrDosHandle : word; Správce překryvných jednotek
4 OvrEmsHandle : word; Správce EMS
5 OvrFileMode : byte; Druh přístupu k překryvnému souboru, standardně = 0 (Read-Only), může být změněna (např. při práci v síti)
6 OvrHeapEnd : word; Konec paměti pro překryvné moduly, hodnota nastavena pomocí OvrInit; uživatel ať ji nemění
7 OvrHeapOrg : word; Začátek paměti pro překryvné moduly, nastaveno pomocí OvrInit, uživatel ať se v tom nehrabe
8 OvrHeapPtr : word; Současná pozice v paměti, uživatel ať to raději nechá na pokoji
9 OvrHeapSize : word; Velikost paměti vyhrazené pro překryvné jednotky, 0 znamená, že Overlay nejsou použity. Uživatel tuto hodnotu nesmí měnit
10 OvrLoadCount : word; Aktuální počet natahovaných překryvných modulů
11 OvrLoadList : word; Seznam natažených překryvných modulů, slouží manažeru, raději ji neměňte
12 OvrReadBuf : OvrReadFunc; Kontrolní funkce, která je volána po každém načtení překryvného modulu z disku, výsledná hodnota 0 znamená bezproblémový návrat, jinak se generuje chyba 209 (Overlay file read error). Tato proměnná slouží k vlastní obsluze chyb. Parametr OvrSeg slouží pouze k předání hodnoty původní funkci, která by měla vždy být volána.
13 OvrResult : integer; Tady je kód, který vrací procedury a funkce jednotky Overlay podle své úspěšnosti (viz konstanty)
14 OvrTrapCount : word; Počet přístupů na disk (do odstavné oblasti) kvůli překryvným jednotkám, také ji neměňte

Procedury a funkce

Procedury a funkce jednotky Overlay
Pořadí Příkaz Význam
1 OvrInit(FileName:string); Inicializuje ovladač překryvných jednotek, FileName je jméno souboru, kde jsou tyto jednotky uloženy; standardně je to NazevProgramu.ovr
2 OvrInitEMS; Překryvné jednotky budou využívat EMS (což program značně zrychlí). Nepovede-li se (např. není-li EMS není přítomna), vrací chybu, ale program pokračuje dál, jako by se nic nestalo
3 OvrGetBuf:longint; Vrací současnou velikost paměti vyhrazené pro překryvné jednotky
4 OvrGetRetry:longint; Vrací velikost odstavné paměti (to je ta část paměti, kde jsou jednotky, než jsou zapsány na disk)
5 OvrSetBuf(Size:longint); Umožní zvětšit velikost paměti vyhrazené pro překryvné jednotky (Size musí být větší než původní vyhrazené místo a menší nebo rovna MemAvail)
6 OvrSetRetry(Size: longint); Umožní nastavit velikost odkládací oblasti (na počátku je tato hodnota nulová)
7 OvrClearBuf; Smaže obsah "překryvné" paměti (vše se bude znovu natahovat z disku) - jenom zpomaluje program