13.2. Položky definované Generátorem sestav Generátor sestav automaticky definuje (buďto vždy anebo na základě určitých popisů v popisu sestavy) položky PAGE-COUNTER, LINE-COUNTER, PRINT-SWITCH a CBL-CTR. Uživatel již nesmí tyto položky popisovat, smí je však používat kdykoliv ve zdrojovém programu, kde jsou přípustné položky s uvedenými popisy. V popisech v REPORT SECTION smí být tyto položky použity pouze v klauzuli SOURCE (viz 13.5.7.). 13.2.1. PAGE-COUNTER Generátor sestav vytvoří pro každou sestavu, která má v RD uvedenu klauzuli PAGE, položku PAGE-COUNTER s implicitně přijatým popisem 01 PAGE-COUNTER PIC S9(4) COMP. Obsahuje-li zdrojový program několik sestav (RD) s klauzulí PAGE, bude pro každou z nich vytvořena jedna taková položka PAGE-COUNTER. Při použití je pak nutno ji kvalifikovat jménem sestavy (s výjimkou použití v rámci téže sestavy v klauzuli SOURCE, kdy lze kvalifikaci vynechat). Generátor sestav má v položce PAGE-COUNTER uloženo běžné číslo stránky tiskové sestavy. Příkaz INITIATE nastavuje do položky PAGE-COUNTER hodnotu 1. Při každém přechodu na novou stránku přičte Generátor sestav k položce PAGE-COUNTER jedničku, přičemž toto přičtení se provádí po vytvoření PAGE-FOOTING, ale před vytvořením PAGE-HEADING. Uživatel smí hodnotu položky PAGE-COUNTER libovolně měnit (např. chce-li první stránku sestavy očíslovat jiným číslem než 1 - toto číslo pak musí do položky PAGE-COUNTER dosadit mezi provedením příkazu INITIATE a prvního příkazu GENERATE, anebo chce-li během zpracování začít číslovat stránky znovu od 1 apod.). Generátor sestav mimo počátečního nastavení a přičítání jedničky s položkou PAGE-COUNTER sám nepracuje, takže případné uživatelovy změny této položky jeho činnost neovlivní. Bývá zvykem používat položku PAGE-COUNTER v klauzuli SOURCE v popisu skupiny PAGE HEADING a případně též PAGE FOOTING. 13.2.2. LINE-COUNTER Generátor sestav vytvoří pro každou sestavu, která má v RD uvedenou klauzuli PAGE, položku LINE-COUNTER s implicitně přijatým popisem 01 LINE-COUNTER PIC S9(4) COMP. Obsahuje-li zdrojový program několik sestav (RD) s klauzulí PAGE, bude pro každou z nich vytvořena jedna taková položka LINE-COUNTER. Při použití je pak nutno ji kvalifikovat jménem sestavy (s výjimkou použití v rámci téže sestavy v klauzuli SOURCE, kdy lze kvalifikaci vynechat). Generátor sestav má v položce LINE-COUNTER neustále uloženo pořadové číslo na stránce pro ten řádek, na němž právě stojí tiskárna. (Výjimka nastává při klauzuli NEXT GROUP NEXT PAGE (viz 13.5.3.) a dále bezprostředně po každém přechodu na novou stránku, například před tiskem REPORT HEADING, kdy Generátor sestav dává do položky LINE-COUNTER hodnotu 0.) Po tisku skupiny, jejíž popis neobsahuje klauzuli NEXT GROUP, bude v LINE-COUNTER uloženo pořadové číslo naposledy vytisknutého řádku. Pokud však popis skupiny obsahuje klauzuli NEXT GROUP (s výjimkou NEXT GROUP NEXT PAGE), bude po tisku skupiny navíc proveden posuv papíru bez tisku, načež položka LINE-COUNTER bude obsahovat pořadové číslo toho řádku, na němž zůstane tiskárna nastavena. Příkaz INITIATE dosazuje do položky LINE-COUNTER hodnotu 0.Během vytváření sestavy Generátor sestav testuje a nastavuje hodnotu položky LINE-COUNTER podle klauzulí LINE a NEXT GROUP v popisech vytvářených skupin, přičemž respektuje předepsané hranice oblastí zadané pomocí klauzule PAGE. Při obvyklém zpracování nebývá zvykem, aby uživatel s položkou LINE-COUNTER jakkoliv pracoval. Změní-li uživatel v některém příkazu v PROCEDURE DIVISION hodnotu LINE-COUNTER, způsobí to obecně změnu anebo i zničení formátu právě tisknuté stránky, za což nese odpovědnost plně uživatel. Zvětšení resp. zmenšení hodnoty LINE-COUNTER o celé číslo n (samozřejmě pouze v rámci příslušné oblasti stránky, např. při tisku normální skupiny v rozmezí celé-číslo-3 až celé-číslo-5 z klauzule PAGE) má většinou takový následek, jako kdyby se pro tuto stránku zmenšila resp. zvětšila všechna celá čísla uvedená v klauzuli PAGE o hodnotu n; tedy stránka se o n řádků zkrátí resp. prodlouží. Formát stránky se nezmění, vytiskne-li uživatel příkazem WRITE s AFTER n řádků a současně zvětší hodnotu LINE-COUNTER o n; změna LINE-COUNTER ovšem sama o sobě posuv papíru nezpůsobí. Dá-li uživatel do LINE-COUNTER číslo větší nebo (s výjimkou klauzule LINE PLUS 0) rovné celému-číslu-5 (FOOTING) z klauzule PAGE, způsobí tím přechod na novou stránku před tiskem následující normální skupiny sestavy. 13.2.3. PRINT-SWITCH Obsahuje-li zdrojový program alespoň jednu klauzuli RD, vytvoří Generátor sestav (jedinou) položku PRINT-SWITCH s implicitně přijatým popisem 77 PRINT-SWITCH PIC 9(4) COMP. Položka PRINT-SWITCH je společná pro všechny sestavy (RD) popsané ve zdrojovém programu. Příkaz INITIATE dosazuje do položky PRINT-SWITCH hodnotu 0. Pomocí položky PRINT-SWITCH může uživatel potlačit tisk kterékoliv skupiny sestavy. Musí mít pro tuto skupinu uvedenu deklarativní sekci (viz 13.7.), v níž musí do položky PRINT-SWITCH dosadit hodnotu 1 (např. příkazem MOVE 1 TO PRINT-SWITCH nebo příkazem SUPPRESS PRINTING). Generátor sestav po návratu z deklarativní sekce testuje, zda v položce PRINT-SWITCH je hodnota 1; pokud ano, potlačí tisk této skupiny sestavy. V obou případech dosadí Generátor sestav do položky PRINT-SWITCH opět hodnotu 0. 13.2.4. CBL-CTR Generátor sestav vytvoří pro každou sestavu položku s implicitně přijatým popisem 01 CBL-CTR PIC S9(4) COMP. Obsahuje-li zdrojový program několik sestav (RD) , bude pro každou z nich vytvořena jedna taková položka CBL-CTR. Při použití je pak nutno ji kvalifikovat jménem sestavy (s výjimkou použití v rámci téže sestavy v klauzuli SOURCE). Zjistí-li Generátor sestav při provádění příkazu GENERATE, že došlo k řídicí změně, uloží do položky CBL-CTR zakódovanou úroveň této řídicí změny: při řídicí změně úrovně FINAL (jež nastává při provádění prvního příkazu GENERATE a při provádění příkazu TERMINATE) uloží do CBL-CTR hodnotu 0, při řídicí změně řídicí položky nejvyšší úrovně (mimo FINAL) hodnotu 1, při řídicí změně řídicí položky druhé nejvyšší úrovně hodnotu 2 atd. Tato hodnota se do položky CBL-CTR nastavuje na začátku provádění příkazů GENERATE nebo TERMINATE bezprostředně po zjištění řídicí změny, takže je již nastavena při provádění všech deklarativních sekcí (USE BEFORE REPORTING), které se v rámci provádění tohoto příkazu GENERATE nebo TERMINATE vyvolají. Generátor sestav položku CBL-CTR pouze nastavuje, ale sám ji nevyužívá. Proto může uživatel její hodnotu jakkoliv změnit, a činnost Generátoru sestav tím nebude nijak ovlivněna. Nezmění-li uživatel hodnotu položky CBL-CTR, zůstává tato hodnota nezměněna až do takového příštího příkazu GENERATE nebo TERMINATE, při němž se opět zjistí řídicí změna. Pomocí položky CBL-CTR může tedy uživatel zjistit úroveň poslední řídicí změny, která vznikla během výpočtu, a využít tuto informaci při řízení výpočtu. Především je výhodné používat položku CBL-CTR v těch částech deklarativních sekcí, které dostávají řízení při řídicích změnách různých úrovní. 13.3. Výstupní soubor sestavy Každé sestavě RD je nutno přiřadit jeden nebo dva výstupní soubory, jejichž prostřednictvím budou vystupovat logické věty této sestavy na vnější médium. Tyto soubory jsou určeny tím, že mají v FD uvedenu klauzuli REPORT (viz 4.4.6.) se jménem příslušné sestavy. Neobsahuje-li sestava RD klauzuli CODE, pak výstupní soubor musí být typu LINE SEQUENTIAL, pokud sestava RD obsahuje klauzuli CODE, pak výstupním souborem musí být sekvenční soubor s větami pevné resp. proměnné délky. S výjimkou povinné klauzule REPORT mohou mít tyto soubory zcela libovolné popisy s tím rozdílem, že za jejich klauzulemi FD nemusí být (a za normálních okolností také nikdy nebudou) popsány žádné logické věty (01). Každé jméno sestavy (RD) tedy musí být uvedeno v klauzuli REPORT buďto v jedné klauzuli FD některého výstupního souboru, anebo ve dvou takových klauzulích FD. Je-li v FD přiřazeného výstupního souboru uvedena klauzule RECORD, budou mít všechny logické věty vystupující prostřednictvím tohoto souboru délku nejvýše rovnou celému-číslu-2 z této klauzule RECORD (v závislosti na typu výstupního souboru). Není-li v FD uvedena klauzule RECORD, pak popsal-li uživatel explicitně pro tento soubor nějakou 01 (nepočítají se 01 uvedené v klauzuli LABEL), bude délka logických vět nejvýše rovna maximální délce ode všech těchto explicitně popsaných 01, zatímco nepopsal-li uživatel pro tento soubor explicitně žádnou 01, bude délka logických vět nejvýše rovna 133 bytů (srv. 4.4.6.). Je velmi výhodné zjistit si délku nejdelšího tisknutého řádku tiskové sestavy, při použití klauzule CODE ji zvětšit o tři (jeden byte pro identifikační znak a dva byty pro řídicí znaky tiskárny) a tuto hodnotu uvést v klauzuli RECORD v FD výstupního souboru. Logické věty pak budou zapisovány v této délce (v případě sekvenčního souboru) resp. v této nebo kratších délkách (v případě souboru typu LINE SEQUENTIAL). Z téhož důvodu je výhodné v FD uvádět klauzuli RECORDING V ovšem pouze tehdy, je-li v popisu RD uvedena klauzule CODE. Logické věty vytvářené Generátorem sestav mají tuto strukturu: a) Pokud v RD není uvedena klauzule CODE: ------------------------------------- | D | ------------------------------------- b) Pokud v RD je uvedena klauzule CODE (viz 13.4.3.): ------------------------------------- | Z | R | R | D | ------------------------------------- R = 2 byty, do nichž Generátor sestav dává řídicí znaky tiskárny, jímž se řídí posuv papíru v tiskárně podle požadavků uvedených v popisu sestavy. Z = 1 byte, do něhož Generátor sestav dává tzv. identifikační znak, definovaný pomocí klauzule CODE (viz 13.4.3.). D = zbytek logické věty (tzv. datová oblast). Generátor sestav naplňuje datovou oblast logické věty podle popisů tiskových položek vytvářené sestavy (viz 13.5.). Neobsazené části datové oblasti jsou automaticky vymezerovány. Uživatel musí přiřazené výstupní soubory sám otevřít příkazem OPEN OUTPUT (provedeným před příkazem INITIATE) a uzavřít příkazem CLOSE bez volby REEL/UNIT (provedeným až po příkazu TERMINATE). Poznámka: Generátor sestav vytváří řádky určené pro tisk ve své pracovní oblasti a provádí pak jejich zápis implicitním příkazem WRITE s klauzulí FROM. Po každém provedení příkazu WRITE tuto pracovní oblast celou vymezeruje. Poznámka: Výstup logických vět jedné sestavy prostřednictvím dvou výstupních souborů se provádí především tehdy, je-li jedním z těchto souborů reálná tiskárna a druhým výstupní zařízení jiného typu, na něž zapisujeme kopii tiskové sestavy pro archivaci a pro případné pozdější vytisknutí na tiskárně. Každá logická věta sestavy se vždy zapisuje prostřednictvím obou těchto souborů. 13.4.Klauzule RD Chce-li uživatel pracovat s Generátorem sestav, musí jakožto poslední sekci v DATA DIVISION uvést sekci REPORT SECTION a v ní popsat jednu nebo více sestav. Popis každé sestavy se skládá z klauzule RD, za níž následují popisy skupin patřících k této sestavě. Formát: RD jméno-sestavy - - | {CONTROL IS | CONTROLS ARE} | | {položka ... | FINAL [položka] ... } | - - - - | PAGE {LIMIT IS | LIMITS ARE} celé-číslo-1 {LINE |LINES} | | [HEADING celé-číslo-2] | | [FIRST DETAIL celé-číslo-3] | | [LAST DETAIL celé-číslo-4] | | [FOOTING celé-číslo-5] | - - [ WITH CODE {'znak' | speciální-jméno}]. Pravidla: 1) Jméno-sestavy může uživatel zvolit libovolně tak, aby vyhovovalo pravidlům pro vytváření jména-položky (viz 1.4.) a aby se neshodovalo se jménem žádného jiného objektu popsaného v DATA DIVISION (výjimka: jméno-sestavy může být shodné se jménem, pokud toto jméno nebude uvedeno v příkazech CALL, UFO, MATCH, GENERATE ani jako kvalifikátor). Toto jméno-sestavy se pak uvádí v klauzuli REPORT v FD, v příkazech INITIATE, TERMINATE a případně též GENERATE a dále jako kvalifikátor pro jména položek z této sestavy. 2) Klauzule CONTROL, PAGE a CODE mohou být uvedeny v libovolném vzájemném pořadí. 3) Klauzule RD musí být zakončena tečkou. 4) Za klauzulí RD musí následovat popis alespoň jedné skupiny sestavy (tj. popis položky s číslem úrovně 01 a popisy položek k ní podřízených). 5) Slova CONTROL (IS) a CONTROLS (ARE) jsou ekvivalentní. 13.4.1. Klauzule CONTROL Formát: {CONTROL IS | CONTROLS ARE} {položka ... | FINAL [položka] ... } Funkce: Položky uvedené v klauzuli CONTROL nazýváme řídicí položky sestavy. Tyto řídicí položky mají při vytváření sestavy velmi důležitou úlohu a podstatně ovlivňují činnost Generátoru sestav. Pravidla: 1) Položky uvedené v klauzuli CONTROL smí být definovány kdekoliv v DATA DIVISION, nikoliv však v REPORT SECTION. Mohou být libovolného typu, smí mít kvalifikaci i indexy i proměnnou adresu, nesmí však mít proměnnou délku (tj. nesmí mít podřízené položky s klauzulí OCCURS DEPENDING) a též nesmí mít délku větší než 255 bytů. Libovolné dvě řídicí položky se smí v paměti překrývat (např. smí být jedna částí druhé). Řídicí položky musí mít přidělenu paměť až do provedení příkazu TERMINATE; jsou-li tedy částí 01 nějakého vstupního souboru, musí být příkaz TERMINATE proveden před uzavřením tohoto souboru (smí však být proveden po uplatnění klauzule AT END); jsou-li částí 01 třídicího souboru, musí být příkaz TERMINATE proveden ještě ve výstupní rutině; jsou-li v LINKAGE SECTION, nesmí jim být odňata paměť před provedením příkazu TERMINATE; jsou-li indexovány, musí jejich indexy mít přípustnou hodnotu i při TERMINATE. Přidělená paměť však nemusí být táž jako při posledním příkazu GENERATE. 2) Řídicí položky jsou uspořádány do hierarchie, přičemž jejich hierarchická úroveň je určena jejich pořadím v klauzuli CONTROL. První uvedená položka má nejvyšší úroveň, druhá uvedená položka má druhou nejvyšší úroveň atd., až poslední uvedená položka má nejnižší úroveň. Je-li uvedeno reservované slovo FINAL, označuje nejvyšší hierarchickou úroveň, ještě vyšší než u první uvedené řídicí položky. 3) Na začátku provádění kteréhokoliv příkazu GENERATE (kromě prvního) pro tuto sestavu se zjišťuje, zda se od provádění bezprostředně předcházejícího příkazu GENERATE (téhož nebo i některého jiného) pro touž sestavu změnila hodnota některé z řídicích položek. Při zjištění změny některé z řídicích položek (tzv. řídicí změny určité hierarchické úrovně) se v rámci provádění příkazu GENERATE provádějí (a to před vlastním vytvořením skupiny typu DETAIL) některé speciální akce, jako např. sumarizace, vytvoření skupin CONTROL FOOTING a CONTROL HEADING, nulování sumátorů apod. (viz popis příkazu GENERATE). 4) Při testování změn řídicích položek se nejprve testuje změna řídicí položky nejvyšší úrovně, pak změna řídicí položky druhé nejvyšší úrovně atd. Je-li zjištěna změna řídicí položky jisté úrovně, provádějí se příslušné akce pro tuto úroveň a také pro všechny nižší úrovně nezávisle na tom, zda se řídicí položky těchto nižších úrovní též změnily nebo nezměnily. Předpokládají se tedy implicitně i řídicí změny na všech nižších úrovních. (Např. v předešlém příkladu se tedy při změně čísla závodu předpokládá i změna čísla střediska, i kdyby náhodou číslo střediska zůstalo stejné jako u posledního střediska starého závodu.) 5) Řídicí změna nejvyšší úrovně příslušné k reservovanému slovu FINAL vzniká během zpracování sestavy pouze dvakrát: při provádění příkazu GENERATE následujícího po INITIATE a dále při provádění příkazu TERMINATE (to jest na začátku a na konci vytváření sestavy). Implicitně se pak předpokládají i řídicí změny na všech nižších úrovních. 6) Pro každou z řídicích položek (včetně FINAL) může uživatel popsat nejvýše jednu skupinu typu CONTROL HEADING a nejvýše jednu skupinu typu CONTROL FOOTING (viz popis klauzule TYPE). 7) Rezervované slovo FINAL nemusí být v klauzuli CONTROL vůbec uváděno, neboť překladač je vždy předpokládá implicitně. Tedy i když uživatel slovo FINAL v klauzuli CONTROL neuvede, smí popsat skupiny typu CONTROL HEADING FINAL a CONTROL FOOTING FINAL a též použít klauzuli RESET FINAL. 8) Pokud uživatel chce, aby se při zpracování sestavy nepracovalo s žádnými řídicími položkami, neuvede v RD klauzuli CONTROL vůbec, což je ekvivalentní s jejím uvedením ve tvaru CONTROL FINAL. Nesmí pak popsat žádné jiné skupiny typu CONTROL HEADING a CONTROL FOOTING než se slovem FINAL.