14.5. Výstup logických vět ze třídění, příkaz RETURN Pro určení, co se má provádět se setříděnými logickými větami vystupujícími ze třídění, má uživatel dvě možnosti, obě přípustné v příkazu SORT i v příkazu MERGE: zadat výstupní rutinu, v níž bude sám příkazem RETURN odebírat od systémového třídicího programu setříděné logické věty a zpracovávat je dle svého uvážení (zadává se pomocí klauzule OUTPUT PROCEDURE), anebo zadat jeden nebo více souborů, do nichž má systémový třídicí program setříděné logické věty zapsat (zadává se pomocí klauzule GIVING). A) Výstupní rutina, klauzule OUTPUT PROCEDURE Výstupní rutinu může uživatel zadat jak v příkazu SORT, tak i v příkazu MERGE, a to pomocí klauzule OUTPUT PROCEDURE IS procedura-1 [{THRU|THROUGH} procedura-2] V tomto případě (obdobně jako u vstupní rutiny) příkaz SORT resp. MERGE v podstatě provede příkaz PERFORM procedura-1 [{THRU|THROUGH} procedura-2] Odskočí se tedy na začátek procedury-1 (tj. na začátek výstupní rutiny) a provádějí se příkazy zde uvedené. Správný průběh třídění je možný jen tehdy, má-li výstupní rutina následující strukturu: 1) Na jejím začátku jsou vhodné inicializační příkazy, např. otevření výstupního souboru, nastavení pomocných položek apod. (Na začátek výstupní rutiny se totiž odskakuje pouze jednou na začátku předávání setříděných logických vět zpět uživateli - nikoliv při každé logické větě!) 2) Dále uživatel provede příkaz RETURN (viz dále). Příkaz RETURN předá řízení systémovému třídicímu programu, jenž předá (vrátí) uživateli jednu logickou větu (a to postupně v pořadí dle setřídění), tj. umístí ji do společné paměťové oblasti všech 01 popsaných za SD. Pak předá řízení zpět do výstupní rutiny. Dokončí se provádění příkazu RETURN a (vzhledem k tomu, že nedošlo k uplatnění klauzule AT END) přechází se na provádění prvního příkazu za tečkou. 3) Příkaz RETURN má nepovinnou klauzuli AT END, která uživateli umožňuje rozpoznat, zda systémový třídicí program již vrátil všechny logické věty, které byly předány do třídění. Pokud systémový třídicí program ještě předal do 01 logickou větu (první až poslední), klauzule AT END se neuplatní a přejde se na první příkaz za tečkou. Zde by měly být uvedeny příkazy pro zpracování právě získané logické věty (minimálně by ji měl uživatel uklidit z 01 jinam, jinak ji příští příkaz RETURN přemaže) a odskok na nové provádění bodu 2. Pokud systémový třídicí program vyvolaný příkazem RETURN již nepředává logickou větu (tzn. logická věta předaná při předchozím příkazu RETURN byla poslední), uplatní se klauzule AT END v příkazu RETURN a provádějí se příkazy zde uvedené; mimo jiné by zde měl být uveden odskok na bod 4. (Klauzule AT END není sice u příkazu RETURN povinná, lze ji však vynechat pouze je-li si uživatel jist, že by se stejně neuplatnila - tedy např. u příkazu RETURN, jenž získává pouze první vrácenou logickou větu, jež má nějaký zvláštní význam. Získávání "běžných" logických vět pak již ovšem provádí příkazem RETURN s klauzulí AT END.) 4) Po uplatnění klauzule AT END musí uživatel přejít na provádění závěrečných příkazů výstupní rutiny (např. uzavření výstupního souboru apod.). Po provedení posledního příkazu výstupní rutiny se přijde na návratový můstek vygenerovaný překladačem na konci výstupní rutiny, jenž automaticky předá řízení zpět do příkazu SORT resp. MERGE (přesně stejně, jako kdyby na konci výstupní rutiny končil úsek programu prováděný jednoduchým příkazem PERFORM). Výstupní rutina má tvar posloupnosti procedur, která se jako celek provádí při jednom třídění (tj. při jednom provádění příkazu SORT nebo MERGE) pouze jednou. Uvnitř výstupní rutiny však bude pravděpodobně cyklus, při jehož každém opakování se příkazem RETURN získává od systémového třídicího programu jedna logická věta. Je přípustné (byť nezvyklé) přijít na konec výstupní rutiny i před uplatněním klauzule AT END v příkazu RETURN. Příkaz RETURN Příkaz RETURN smí být použit výhradně ve výstupní rutině při třídění prováděném příkazem SORT nebo MERGE. Při jednom provedení příkazu RETURN se od systémového třídicího programu získá jedna logická věta a uloží se do 01 popsané za SD, jak je popsáno podrobněji výše. (Příkaz RETURN má při získávání setříděných logických vět od systémového třídicího programu stejnou úlohu jako příkaz READ při čtení sekvenčního souboru.) Formát: RETURN jméno-třídicího-souboru RECORD [INTO položka] [ AT END příkaz ... ] Pravidla: 1) Za slovem RETURN musí být uvedeno jméno toho třídicího souboru, jemuž odpovídající třídění se právě provádí. (Provedení příkazu RETURN pro třídicí soubor, jemuž odpovídající třídění není právě v činnosti, způsobí vážnou chybu.) 2) Klauzule "INTO položka" přípustná v příkazu RETURN má přesně stejný význam jako u příkazu READ (viz 8.2.). Způsobí tedy, že po úspěšném provedení příkazu RETURN (neuplatnila-li se klauzule AT END) se získaná logická věta přesune ještě i do položky uvedené za slovem INTO, a to pomocí příkazu MOVE třid-věta TO položka kde vysílající položka "třid-věta" je první popsaná 01 za příslušnou klauzulí SD. Pro získání logické věty od systémového třídicího programu má tedy uživatel dvě možnosti: a) Provede příkaz RETURN bez klauzule INTO, takže získaná logická věta bude umístěna pouze ve společné paměťové oblasti všech 01 popsaných za SD. b) Provede příkaz RETURN s klauzulí INTO, takže získaná logická věta bude umístěna jak v 01, tak i v položce uvedené za slovem INTO. 3) Klauzule AT END se uplatní při provádění toho příkazu RETURN, jenž bezprostředně následuje po příkazu RETURN získavším od systémového třídicího programu poslední logickou větu (podrobněji viz výše). 4) Nechť v SD je uvedeno RECORDING V. Je-li zadán parametr CBL TALLY, bude po úspěšném provedení příkazu RETURN do položky TALLY dosazena délka právě získané logické věty (bez dvoubytového řídicího pole). Bez použití parametru CBL TALLY uživatel délku získané logické věty nedostává k dispozici a musí si ji zjistit sám (nejobvyklejší je mít na vhodném místě v každé logické větě uloženu buď přímo tuto délku anebo nějaký údaj, z něhož se dá délka logické věty vypočítat). Příklad: Máme sloučit dohromady již setříděné soubory VSTA a VSTB. Logické věty, u nichž hodnota položky MUZ-ZENA je M, mají být zapsány do souboru VYSTM, ostatní do souboru VYSTZ, Ostatní potřebné informace jsou zřejmé přímo z programu. ID DIVISION. PROGRAM-ID. POPULACE. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT VSTA ASSIGN S-VSTA. SELECT VSTB ASSIGN I-VSTB. SELECT SMES ASSIGN S-SMES. &systém. jméno se ignoruje SELECT VYSTM ASSIGN S-VYSTM. SELECT VYSTZ ASSIGN S-VYSTZ. DATA DIVISION. FILE SECTION. FD VSTA. 01 FILLER PIC X(50). FD VSTB. 01 FILLER PIC X(50). SD SMES. 01 CLOVEK. 02 CISLO PIC 9(6). 02 MUZ-ZENA PIC X. 02 FILLER PIC X(43). FD VYSTM. 01 VM PIC X(50). FD VYSTZ. 01 VZ PIC X(50). PROCEDURE DIVISION. MERGE SMES ASCENDING CISLO USING VSTA VSTB OUTPUT PROCEDURE ROZDEL. STOP RUN. ROZDEL SECTION. OPEN OUTPUT VYSTM VYSTZ. ZNOVU. RETURN SMES AT END GO TO POSL. IF MUZ-ZENA = 'M' WRITE VM FROM CLOVEK ELSE WRITE VZ FROM CLOVEK. GO TO ZNOVU. POSL. CLOSE VYSTM LOCK VYSTZ LOCK. B) Klauzule GIVING Klauzule GIVING, která může být uvedena jak v příkazu SORT, tak i v příkazu MERGE, má formát GIVING jméno-souboru ... Za slovem GIVING je třeba uvést jméno jednoho souboru nebo několika souborů, do nichž mají být zapsány setříděné logické věty. Systémový třídicí program tento soubor resp. všechny tyto soubory otevře, zapíše do nichž sekvenčně všechny setříděné logické věty v patřičném pořadí dle setřídění, načež tyto soubor uzavře. Uživatel nezadává žádnou výstupní rutinu a nepoužívá příkaz RETURN. Je-li v klauzuli GIVING uvedeno několik souborů, zapisuje se každá ze setříděných vět do každého z těchto souborů (takže zároveň můžeme vytvářet jednu nebo více kopií souboru, do něhož zapisujeme setříděné věty, nebo tyto setříděné věty zároveň vypisovat na tiskárně resp. na obrazovce apod.). Soubor uvedený v klauzuli GIVING je v přeloženém programu representován instrukcemi, které jsou prakticky stejné, jako kdyby vznikly překladem výstupní rutiny tvaru: A. OPEN OUTPUT soubor. B. RETURN jméno-třídicího-souboru INTO soub-věta AT END GO TO C. WRITE soub-věta. GO TO B. C. CLOSE soubor. Zde "soub-věta" označuje tu 01, která je popsána za FD příslušného souboru jako první ze všech 01 neuvedených v klauzuli LABEL. Z uvedeného plynou následující pravidla a požadavky: a) Soubor uvedený v klauzuli GIVING musí být buďto sekvenční soubor (do něhož je možno zapisovat) nebo indexový resp. relativní soubor se sekvenčním přístupem (jedná se pak o prvotní vytváření nebo sekvenční prodlužování souboru dat). b) Na začátku provádění příkazu SORT resp. MERGE nesmí být soubor uvedený za slovem GIVING již otevřený, neboť příkaz SORT resp. MERGE si jej otevírá sám. c) Soubor se vždy otevírá příkazem OPEN OUTPUT bez klauzule WITH NO REWIND. d) Není-li v FD souboru uvedeného za slovem GIVING uvedeno RECORDING V ani RECORDING U, způsobí klauzule INTO v implicitním příkazu RETURN normální přesun "MOVE třid-věta TO soub-věta" (kde "třid-věta" je první 01 popsaná za SD) dle pravidel příkazu MOVE, jak je uvedeno výše. Logická věta zapisovaná do souboru má pak délku rovnou délce 01 za FD (přesněji: parametru RECSIZE u souboru uvedeného za GIVING) nezávisle na tvaru a délce "třid-věty" získané implicitním příkazem RETURN. e) Je-li v FD souboru uvedeného za slovem GIVING uvedeno RECORDING V nebo RECORDING U, má klauzule INTO v implicitním příkazu RETURN jiný význam než u explicitně použitého příkazu RETURN a než při RECORDING F: Implicitní příkaz WRITE následující po implicitním příkazu RETURN zapíše do výstupního souboru dat logickou větu o přesně stejné délce a obsahu, jakou má logická věta právě získaná ze třídění implicitním příkazem RETURN. Tak tomu bude nezávisle na tom, zda v SD je RECORDING F nebo V. f) Příkaz SORT resp. MERGE na závěr své činnosti soubor uvedený za GIVING sám uzavře, a to příkazem CLOSE bez klauzulí REEL, UNIT, WITH NO REWIND i WITH LOCK.