8.7. Zpracování sekvenčního souboru V tomto odstavci a v následujících dvou odstavcích je přehledně popsáno zpracování jednotlivých typů souborů, které jsou v MX Cobolu přípustné. Je uveden vždy formát klauzulí SELECT a FD a použitelné příkazy, přičemž se neuvádějí poznámková slova a klauzule a dále ty klauzule, které mohou být zapsány pouze jedním způsobem, který je významově rovnocenný s vynecháním klauzule. Klauzule SELECT má u sekvenčního souboru tvar: SELECT jméno-souboru ASSIGN {systémové-jméno|fyzické-jméno } [ORGANIZATION {[LINE | BINARY] SEQUENTIAL}] V systémovém jméně musí být organizace S. Klauzule FD má u sekvenčního souboru tvar: FD jméno souboru [RECORDING {F|V|U}] [RECORD [celé-číslo-1 TO] celé-číslo-2] [{REPORT|REPORTS} jméno-sestavy] [ LINAGE {celé-číslo|položka} [TOP {celé-číslo|položka}] [BOTTOM {celé-číslo|položka}] [FOOTING {celé-číslo|položka}] ] 8.7.1. Vytvoření sekvenčního souboru Pod pojmem vytvoření sekvenčního souboru rozumíme jednak prvotní vytváření (je-li otevřen OPEN OUTPUT) a jednak (u diskových a disketových souborů otevřených OPEN EXTEND) sekvenční prodlužování. U sekvenčního souboru je potřeba rozlišovat dva případy. Zda se jedná o sekvenční soubor v binárním nebo v textovém formátu. Sekvenční soubor je pokládán za textový v případě, jestliže je v klauzuli SELECT uvedeno ORGANIZATION LINE SEQUENTIAL, anebo je v FD souboru uvedena některá z klauzulí REPORT nebo LINAGE anebo je-li pro soubor použit příkaz WRITE s klauzulí AFTER nebo BEFORE. Ve všech ostatních případech se soubor pokládá za binární. A) Otevření souboru Na začátku zpracování musí být soubor otevřen příkazem OPEN {OUTPUT|EXTEND} jméno-souboru B) Zápis logické věty Logická věta se zapíše příkazem WRITE, který může mít u sekvenčního souboru plný formát (viz 8.3.). Logické věty zapisované do binárního souboru se zapíší vždy v plné délce, logické věty zapisované do textového souboru se zapisují tak, že jsou vynechány pravostranné mezery a za poslední nemezerový znak zleva se automaticky zapíše znak "nový řádek" (hex. 0a). Obsahuje-li věta pouze znaky mezera, nebude zapsán ani jediný znak z jejího obsahu, přičemž o existenci takovéto věty bude svědčit pouze osamocený znak "nový řádek". C) Význam klauzule AFTER/BEFORE Klauzule AFTER/BEFORE, které smí být uvedeny v příkazu WRITE pro sekvenční textový soubor, slouží k řízení vertikálního posuvu papíru při tisku na tiskárně. Tyto klauzule však smí být uvedeny pro kterýkoliv i diskový nebo disketový soubor. Na rozdíl od překladače Cobol DOS-4/JS není první byte věty rezervován pro žádný řídící znak tiskárny, ani se s tímto dřívějším řídícím znakem nikde nepracuje. Vlastní text logické věty vždy začíná již od prvního bytu věty, který se uplatní jako kterýkoliv jiný byte věty. Při zápisu logické věty se nikterak nerozlišuje, zda je médiem souboru papír v tiskárně nebo magnetické médium. Řízení vertikálního posuvu se děje umísťováním řídících znaků mezi logické věty souboru. Kromě již zmíněného znaku "nový řádek" se do souboru zapisuje ve vhodný okamžik ještě znak "nová stránka" (hex. 0c). Je-li pro textový soubor uvedena klauzule RECORDING je vždy ignorována. Tj. při zápisu logických vět souboru s RECORDING V se nikdy na médium (ani na disk nebo disketu) nezapisuje dvoubytový údaj s délkou věty. Pravidla: 1) Není-li v žádném příkazu WRITE pro zápis věty textového souboru uvedena klauzule AFTER/BEFORE (tzn. to, že se jedná o textový soubor je určeno buď slovem LINE v klauzuli SELECT anebo uvedením některé z klauzulí REPORT nebo LINAGE v FD souboru), budou všechny příkazy WRITE přeloženy tak, jako by u nich byla uvedena klauzule BEFORE 1. 2) Je-li alespoň u jednoho příkazu WRITE pro daný soubor uvedena klauzule AFTER/BEFORE je tím řečeno, že se jedná o textový soubor (tzn. není nutno uvádět slovo LINE v klauzuli SELECT anebo v FD některou z klauzulí REPORT nebo LINAGE). a) U příkazů WRITE, které mají uvedenu klauzuli AFTER/BEFORE se respektuje toto explicitní určení posuvu, zatímco u příkazů WRITE, které klauzuli AFTER/BEFORE uvedenu nemají si překladač domyslí vždy klauzuli BEFORE 1. Existuje-li pro daný soubor alespoň jeden příkaz WRITE bez klauzule AFTER/BEFORE a ostatní jsou uvedeny s touto klauzulí, ohlásí překladač upozornění. b) Klauzule FROM má obvyklý význam (viz 8.3.). Argument uvedený za FROM se tedy přesunuje počínaje prvním bytem. Protože v MX Cobolu se nepoužívá řídící byte tiskárny není potřeba v položce za FROM vyhrazovat pro tento účel první byte, nýbrž je nutné vědět, že již první byte této položky obsahuje informaci, která se zapisuje na médium. 3) ... 4) Pro vysvětlení rozdílu mezi volbami AFTER a BEFORE je třeba představit si akci (na tiskárně) rozdělenou na dvě nezávislé části: na tisk řádku (bez posuvu papíru) a na posuv papíru (bez tisku). a) Příkaz WRITE s AFTER provádí nejprve posuv papíru bez tisku a pak teprve tisk řádku bez dalšího posuvu papíru. (tedy WRITE AFTER znamená piš po posuvu. Po provedení příkazu WRITE stojí tiskárna na právě vytisknutém řádku. b) Příkaz WRITE s BEFORE provádí nejprve tisk řádku a pak teprve posun papíru. (Tedy WRITE BEFORE znamená piš před posuvem.) Řádek se vytiskne na to místo, na němž tiskárna stála před provedením příkazu WRITE, načež se (s výjimkou tisku bez posuvu) papír posune, takže po provedení příkazu WRITE stojí tiskárna na některém z následujících volných řádků. Je přípustné (i když nezvyklé) pro týž soubor střídat příkazy WRITE s AFTER (posuv a tisk) s příkazy WRITE s BEFORE (tisk a posuv). Pokud si však uživatel nepromyslí dostatečně způsob posuvu papíru, získá takto často neočekávaný tvar protokolu (dvojí tisk na týž řádek anebo nadbytečně vynechávané řádky). 5) V klauzuli AFTER/BEFORE smí být uvedeny pouze tyto typy argumentů: a) Celé kladné číslo anebo celočíselná numerická položka, jejíž hodnota musí být nezáporná. Provede se posuv o počet řádků rovný hodnotě tohoto argumentu, a to před tiskem (při AFTER) anebo po tisku (při BEFORE). b) Celé číslo 0. Provede se tisk bez posuvu (stejně při AFTER i při BEFORE). c) Slovo CSP anebo speciální jméno přidělené v paragrafu SPECIAL-NAMES funkčnímu jménu CSP. Provede se tisk bez posuvu (stejně při AFTER i při BEFORE); d) Některé ze slov C01, C02, ... , C12 anebo speciální jméno přidělené v paragrafu SPECIAL-NAMES některému z funkčních jmen C01, C02, ..., C12. Provede se bez ohledu na druh slova přechod na novou stránku. MX Cobol tedy mezi těmito slovy resp. speciálními jmény nerozlišuje. e) Slovo PAGE, které má přesně stejný význam jako slovo C01. Provede se tedy přechod na novou stránku (tj. do souboru se zapíše znak "nová stránka", hex. 0c), a to před tiskem (při AFTER) anebo po tisku (při BEFORE). D) Klauzule AT EOP (AT END-OF-PAGE) Slova AT EOP a END-OF-PAGE jsou ekvivalentní. Klauzule AT EOP může být uvedena pouze pro soubor, který má v FD uvedenu klauzuli LINAGE. Klauzule AT EOP se platní tehdy, jestliže pořadové číslo tištěného řádku na logické stránce je vyšší nebo rovno pořadovému číslu řádku FOOTING (v případě je-li FOOTING uvedeno) nebo jestliže je pořadové číslo tištěného řádku rovno pořadovému číslu řádku LINAGE (v případě není-li FOOTING uvedeno). Uplatnění klauzule znamená tolik, že se provedou příkazy uvedené za AT EOP. V případě, že se klauzule neuplatní, příkazy za AT EOP se neprovedou a řízení se předá za tečku. Klauzule AT EOP sama neprovádí přechod na začátek následující logické stránky, nýbrž pouze umožňuje indikovat, že se při tisku běžné stránky pokročilo natolik, že přechod na začátek následující stránky je vhodný. Nicméně je fakt, že dojde-li k zaplnění běžné logické stránky u souboru, který má v FD klauzuli LINAGE, bude následující tištěný řádek, který již na běžnou logickou stránku nelze umístit automaticky vytištěn jako první na následující logické stránce. Součástí automatického přechodu na novou stránku je vynechání prostoru na konci minulé a na začátku nové stránky, je-li to ovšem požadováno uvedením příslušných klauzulí BOTTOM a TOP. Protože koncept vytváření logických stránek je nezávislý na použitém médiu, funguje klauzule AT EOP vždy uvedeným způsobem bez ohledu na to, zda se tištěné řádky (vlastně logické věty) budou zapisovat na fyzickou tiskárnu, na disk, na disketu atp. E) Klauzule INVALID KEY Klauzule INVALID KEY smí být uvedena u příkazu WRITE pro jakýkoliv sekvenční soubor, k jejímu uplatnění však může dojít jen tehdy, bude-li fyzickým zařízením disk nebo disketa. Klauzule INVALID KEY se uplatní v případě, že je již zaplněno celé médium. Přesněji řečeno v okamžiku, kdy se pří pokusu o zápis logické věty nepodařilo zapsat logickou větu celou, ale pouze její část. Po uplatnění klauzule INVALID KEY je uživatel povinen soubor uzavřít příkazem CLOSE. Logická věta, kterou se nepodařilo z kapacitních důvodů zapsat celou je ovšem zničena. F) Uzavření souboru Vytváření resp. rozšiřování sekvenčního souboru dat je nutno ukončit příkazem CLOSE jméno-souboru 8.7.2. Čtení a opravování sekvenčního souboru A) Otevření souboru Na začátku zpracování musí být soubor otevřen příkazem OPEN { INPUT | I-O } jméno-souboru Volby INPUT a I-O jsou rovnocenné; při obou způsobech otevření je přípustné logické věty jak číst tak i opravovat. B) Čtení logické věty Logická věta (následující v sekvenčním pořadí) se přečte z média do 01 příkazem READ jméno-souboru [INTO položka] [ AT END příkaz ... ] Je-li soubor popsán jako binární s RECORDING F, přečte se tolik bytů, kolik činí délka věty, je-li soubor popsán jako binární s RECORDING V, zjistí se z údaje délky před logickou větou kolik bytů je dlouhá a počínaje prvním bytem za údajem délky se umístí do paměťové 01. Je-li věta kratší než paměťová oblast 01, zůstávají zbylé byty v původním stavu, tak jak byly před provedením příkazu READ. Uživatel pak musí sám poznat kde jsou ještě platné údaje ve větě. Je-li soubor popsán jako textový sekvenční soubor, tak se nejprve paměťová oblast 01 vymezeruje a poté se do ní přečte logická věta, která končí znakem "nový řádek" (hex. 0a). Znak nový řádek se však do paměťové oblasti 01 neumisťuje. Logická věta obsahující pouze mezery je na médiu reprezentována osamoceným znakem "nový řádek", po přečtení do paměti se projeví tak, že paměťová oblast 01 bude obsahovat samé mezery. Logická věta způsobující přechod na novou stránku je na médiu reprezentována osamoceným znakem "nová stránka" (hex. 0c), po přečtení do paměti se projeví tak, že kromě prvního bytu 01, který bude obsahovat znak "nová stránka" budou ostatní byty mezery. C) Oprava logické věty Opravování logických vět je pochopitelně přípustné pouze v případě, je-li soubor umístěn na magnetickém médiu. Lze opravit pouze tu logickou větu, která byla přečtena posledním předcházejícím příkazem READ, přičemž ovšem při tomto příkazu READ nesměla nastat podmínka "konec souboru"(tedy nesměla se uplatnit klauzule AT END resp. příslušná deklarativní sekce). Každou přečtenou logickou větu lze v MX Cobolu opravit nejen jednou, ale i bezprostředně po sobě vícekrát. Uživatel tedy přečte logickou větu do 01 příkazem READ a opraví ji v paměti (tj. v 01). Její délku ovšem změnit nemůže (viz 8.3.). U textového souboru tento požadavek znamená, že poslední nemezerový znak ve větě zůstane posledním nemezerovým znakem, jeho hodnota se ovšem může jinak změnit stejně jako hodnota znaků stojících vlevo od posledního nemezerového znaku. Ty se ovšem mohou změnit i na mezery. Opravu logické věty na disku nebo na disketě provede uživatel příkazem - - - - | |položka | | REWRITE logická-věta | FROM | | |figurativní-konstanta| | | |ALL-klauzule | | - - - - anebo též příkazem WRITE v plném formátu (viz 8.3.), kde však k uplatnění klauzulí AT EOP ani INVALID KEY nemůže nikdy dojít a je tedy zbytečné tyto klauzule uvádět. U sekvenčního souboru tedy příkaz WRITE znamená buďto zápis nové logické věty (po otevření OPEN OUTPUT nebo OPEN EXTEND) anebo opravu právě přečtené věty (po otevření OPEN INPUT nebo OPEN I-O, pouze ovšem u diskového nebo disketového souboru). V tomto druhém případě je tedy příkaz WRITE ekvivalentní s příkazem REWRITE s těmito výjimkami: a) Při RECORDING V musí mít 01 uvedená za slovem WRITE (resp. argument uvedený v klauzuli LENGTH) přesně stejnou délku jako přečtená věta, jinak dojde k nesprávnému naplnění řídícího pole délky a tím vlastně ke zničení celého souboru dat. b) Nesmí být použita klauzule AFTER/BEFORE. D) Uzavření souboru Zpracování je vhodné ukončit příkazem CLOSE jméno-souboru Poznámka: Je přípustné během výpočtu týž sekvenční soubor otevřít jednak pro vytváření nebo rozšiřování(OPEN OUTPUT, OPEN EXTEND - pak se smí provádět pouze příkazy WRITE znamenající zápis) a jednak pro čtení a opravování (OPEN INPUT nebo OPEN I-O - pak se smí provádět příkazy READ, REWRITE a příkazy WRITE znamenající opravu). Před novým otevřením je nutno soubor uzavřít příkazem CLOSE. Příklad: Budeme číst logické věty o délce 60 bytů a jednak je zapisovat na vhodné fyzické zařízení, jednak je tisknout (na každé stránce je hlavička, dva volné řádky a pět skupin po deseti logických větách oddělených volnými řádky). IDENTIFICATION DIVISION. PROGRAM-ID. PREPIS. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT VSTUP ASSIGN "VSTUP". SELECT VYSTUP ASSIGN "VYSTUP". SELECT TISK ASSIGN "PRN" ORGANIZATION LINE SEQUENTIAL. DATA DIVISION. FILE SECTION. FD VSTUP. 01 VSTUPA PIC X(60). FD VYSTUP. 01 VYSTUPA PIC X(60). FD TISK. 01 TISKA PIC X(60). WORKING-STORAGE SECTION. 77 CISLO-STRANKY PIC 999 VALUE 1. PROCEDURE DIVISION. OPEN INPUT VSTUP OUTPUT VYSTUP TISK. CTENI. READ VSTUP AT END CLOSE VYSTUP STRING 'HOTOVO ' INTO TISKA POINTER 2 WRITE TISKA AFTER 1 CLOSE TISK VSTUP STOP RUN. WRITE VYSTUPA FROM VSTUPA. ON 1 AND EVERY 50 STRING SPACE 12 INTO TISKA POINTER 2 WRITE TISKA BEFORE PAGE STRING 'STRANKA CISLO ' CISLO-STRANKY INTO TISKA POINTER 2 WRITE TISKA BEFORE 3 ADD 1 TO CISLO-STRANKY. STRING VSTUPA INTO TISKA POINTER 2. ON 10 AND EVERY 10 WRITE TISKA BEFORE 2 ELSE WRITE TISKA BEFORE 1. GO TO CTENI.