5. PROCEDURE DIVISION 5.1. Členění PROCEDURE DIVISION A) Příkaz Základními prvky, z nichž je vytvářena PROCEDURE DIVISION, jsou příkazy. Každý příkaz vyjadřuje určitou akci, která bude při výpočtu provedena, když na příkaz přijde řízení. Typ příkazu je určen jeho prvním slovem, tzv. "slovesem". Formáty a popisy všech příkazů jsou uvedeny v následujících kapitolách. B) Věta (též "věta programu") Věta je posloupnost jednoho nebo několika příkazů oddělených mezerami (resp. čárkami nebo středníky), přičemž za posledním z těchto příkazů je tečka. Věta má tedy formát: příkaz ... . Poznámka: V MX COBOLu lze řadit příkazy (včetně tzv. podmíněných příkazů) do vět bez jakéhokoliv omezení. Poznámka: Příkazy ve větě mohou být také oddělovány pomocí bezvýznamného slova THEN. Slovo THEN může stát též před prvním nebo za posledním příkazem věty; dokonce celá věta může sestávat pouze z jediného slova THEN. C) Paragraf Paragraf se skládá ze záhlaví paragrafu (což je jméno paragrafu zakončené tečkou), za nímž následuje žádná, jedna nebo několik vět (takže za posledním příkazem v paragrafu nutně musí být tečka). Paragraf má tedy formát: jméno-paragrafu. [věta] ... Jak vidět, je přípustný i prázdný paragraf, který se skládá pouze ze záhlaví paragrafu a neobsahuje žádné příkazy. D) Sekce Sekce začíná záhlavím sekce (což je jméno sekce a slovo SECTION zakončené tečkou), za nímž v deklarativní části PROCEDURE DIVISION následuje ještě klauzule USE (viz 5.5.). Za záhlavím může následovat žádná, jedna nebo několik vět (které stojí na začátku sekce samostatně, aniž by patřily do některého paragrafu) a dále žádný, jeden nebo několik paragrafů. Sekce má tedy formát: jméno-sekce SECTION. [USE-klauzule.] [věta] ... [paragraf] ... Jak vidět, je přípustná sekce obsahující pouze samostatné věty anebo sekce obsahující pouze paragrafy. Je přípustná i prázdná sekce, která se skládá pouze ze záhlaví sekce a neobsahuje žádné samostatné věty ani žádné paragrafy. E) Oddíl PROCEDURE DIVISION Oddíl PROCEDURE DIVISION začíná svým záhlavím, které může obsahovat též klauzuli USING (viz 11.7.), za nímž může následovat tzv. deklarativní část (viz 5.5.). Pak může následovat žádná, jedna nebo několik samostatných vět (které nepatří do žádné sekce ani do žádného paragrafu), dále žádný, jeden nebo několik paragrafů (které nepatří do žádné sekce), a konečně žádná, jedna nebo několik sekcí. Oddíl má tedy formát: PROCEDURE DIVISION [USING položka ...] . - - | DECLARATIVES. | | | | [sekce] ... | | | | END DECLARATIVES. | | | - - [věta] ... [paragraf] ... [sekce] ... Jak vidět, oddíl může být i prázdný nebo se může skládat pouze ze samostatných vět nebo pouze z paragrafů nebo pouze ze samostatných vět a z paragrafů, před první sekcí smí být samostatné věty nebo samostatné paragrafy nebo obojí atd. Poznámka: V praxi se sekce používají pouze v souvislosti s příkazy PERFORM, SORT a MERGE (a samozřejmě v deklarativní části oddílu); mimo tyto případy má smysl používat sekce pouze za účelem zvýšení přehlednosti zdrojového programu. Příklad: PROCEDURE DIVISION. OPEN INPUT SOUBOR. CTENI. READ SOUBOR AT END CLOSE SOUBOR EXHIBIT NAMED SOUCET STOP RUN. PERFORM KONTROLA GO TO CTENI. KONTROLA SECTION. IF CENA NOT NUMERIC DISPLAY '*' STITEK GO TO VEN. MOVE 1 TO I. TEST. IF ZNAK = FIX (I) ADD CENA TO SOUCET ELSE IF I < 9 ADD 1 TO I GO TO TEST. VEN. EXIT. Paragrafy a sekce v PROCEDURE DIVISION se souhrnně nazývají procedury. Jejich význam spočívá v tom, že umožňují přerušit provádění příkazů v tom pořadí, v jakém po sobě následují ve zdrojovém programu; pomocí příkazů GO, PERFORM atd. lze předat řízení na začátek kterékoliv procedury, takže jako další se bude provádět první příkaz této procedury. Jména paragrafů a sekcí může programátor volit libovolně ve shodě s pravidly uvedenými v 1.4. Celkový počet procedur ve zdrojovém programu není omezen. F) Rozsahy podmíněných příkazů a příkazů PERFORM Některé příkazy mohou způsobit přeskočení několika následujících příkazů téže věty programu. Každý z těchto příkazů má určitý "rozsah", čímž rozumíme posloupnost příkazů začínající vždy příslušným příkazem a končící a) u příkazu IF resp. ON bez klauzule ELSE: místem, na které se skáče při nepravdivosti podmíněného výrazu resp. při "neoznačeném" průchodu; b) u příkazu IF resp. ON s klauzulí ELSE: místem, na které se skáče při dosažení klauzule ELSE; c) u příkazu PERFORM bez uvedené procedury: místem za posledním příkazem z úseku programu, který se má jednou nebo několikrát provádět (na tomto místě bude vygenerován implicitní "návratový můstek" tohoto příkazu PERFORM); d) u příkazu SEARCH: místem, na které se skáče při dosažení klauzule WHEN resp. u formátu bez klauzule AT END při nenalezení hledaného speciálního indexu; e) u příkazu s některou z klauzulí AT END, INVALID KEY, ON SIZE ERROR, ON OVERFLOW, AT EOP, AT END-OF-PAGE, NO DATA: místem, na které se skáče při neuplatnění této klauzule. Rozsah příkazu nikdy nemůže přesáhnout tečku ukončující celou větu programu (a v praxi většinou končí právě na ní), může však skončit i dříve. Určení rozsahu příkazu a určení, která klauzule ELSE, END-IF, WHEN resp. END-PERFORM patří ke kterému příkazu IF, ON, SEARCH resp. PERFORM provádíme tak, že postupujeme větou programu od jejího prvního příkazu až po ukončující tečku a hledáme klauzule ELSE, END-IF, WHEN a END-PERFORM: 1) Klauzule ELSE patří k nejbližšímu předcházejícímu příkazu IF nebo ON, jenž dosud neměl klauzuli ELSE a jehož rozsah dosud nebyl ukončen. 2) Klauzule END-IF patří k nejbližšímu předcházejícímu příkazu IF nebo ON, jehož rozsah dosud nebyl ukončen. Klauzule END-IF ukončuje rozsah tohoto příkazu IF/ON. 3) Klauzule WHEN vždy patří k nejbližšímu předcházejícímu příkazu SEARCH. Přitom rozsah tohoto příkazu SEARCH nesmí být dosud ukončen, jinak by klauzule WHEN byla prohlášena za chybnou. 4) Klauzule END-PERFORM patří k nejbližšímu předcházejícímu příkazu PERFORM bez uvedené procedury, jehož rozsah dosud nebyl ukončen. Klauzule END-PERFORM ukončuje rozsah tohoto příkazu PERFORM. 5) Klauzule ELSE, END-IF a WHEN ukončují rozsahy všech příkazů PERFORM bez procedury začínajících mezi odpovídajícím IF/ON/SEARCH a tímto ELSE/END-IF/WHEN, jejichž rozsahy dosud nebyly ukončeny, a to přesně stejně jako kdyby pro každý z nich byla bezprostředně před tímto ELSE/END-IF/WHEN explicitně uvedena klauzule END-PERFORM (se všemi důsledky vyplývajícími z ostatních bodů). 6) Klauzule ELSE, WHEN a END-PERFORM (explicitně uvedené nebo implicitně předpokládané dle bodů 5 a 8) ukončují rozsahy všech příkazů IF/ON začínajících mezi odpovídajícím IF/ON/SEARCH/PERFORM a tímto ELSE/WHEN/END-PERFORM, jejichž rozsahy dosud nebyly ukončeny, a to přesně stejně jako kdyby pro každý z nich byla bezprostředně před tímto ELSE/WHEN/END-PERFORM explicitně uvedena klauzule END-IF. V případě klauzule END-PERFORM se tedy odskakuje na vygenerovaný "návratový můstek" odpovídajícího příkazu PERFORM. 7) Klauzule ELSE, END-IF, WHEN a END-PERFORM (explicitně uvedené nebo implicitně předpokládané dle bodů 5, 6 a 8) ukončují rozsahy (tj. určují cílová místa skoku) pro všechny příkazy SEARCH a příkazy s klauzulemi uvedenými v bodě e začínající mezi odpovídajícím IF/ON/SEARCH/PERFORM a tímto ELSE/END-IF/WHEN/PERFORM, jejichž rozsahy dosud nebyly ukončeny. V případě klauzulí ELSE a WHEN překladač ovšem generuje odskok na stejné místo, na které skáče tato klauzule ELSE resp. WHEN. V případě klauzule END-PERFORM se odskakuje na vygenerovaný "návratový můstek" odpovídajícího příkazu PERFORM bez uvedené procedury. 8) Tečka ukončující větu programu ukončuje rozsahy všech příkazů této věty, jejichž rozsahy dosud nebyly ukončeny. Její účinek je stejný, jako kdyby pro každý dosud neukončený příkaz IF/ON resp. PERFORM bez procedury byla bezprostředně před touto tečkou explicitně uvedena klauzule END-IF resp. END-PERFORM, a to v obráceném pořadí, než jak začínají ve větě odpovídající příkazy IF/ON a PERFORM bez procedury. Dosud neukončené příkazy s klauzulemi uvedenými v bodě e (viz výše) začínající před prvním z těchto příkazů IF/ON/PERFORM budou odskakovat až na první příkaz za tečkou. Klauzule ELSE/END-IF/WHEN/END-PERFORM, která nemůže být podle pravidel 1-4 přiřazena k žádnému příkazu IF/ON/SEARCH/PERFORM, je prohlášena za chybnou. Obráceně ovšem příkaz IF resp. ON nemusí mít klauzuli ELSE nebo klauzuli END-IF anebo žádnou z těchto klauzulí a příkaz PERFORM bez uvedené procedury nemusí mít klauzuli END-PERFORM. Z výše uvedených pravidel vyplývá, že začíná-li příkaz IF resp. ON resp. SEARCH resp. PERFORM bez procedury mezi IF/ON a ELSE resp. mezi ELSE a END-IF resp. mezi IF/ON a END-IF (při formátu bez ELSE) resp. mezi PERFORM a END-PERFORM resp. mezi SEARCH a prvním WHEN resp. mezi dvěma WHEN, pak všechny klauzule ELSE/END-IF/WHEN/END-PERFORM patřící k tomuto příkazu musí povinně ležet v témže rozmezí, neboť rozsah příkazu za ně nemůže zasahovat. (Přitom se zde jedná jak o explicitně uvedené tak i o implicitně předpokládané klauzule END-IF a END-PERFORM.) Jsou tedy syntakticky chybné např. následující kombinace: IF/ON ... PERFORM ... ELSE/END-IF ... END-PERFORM IF/ON ... SEARCH ... ELSE/END-IF ... WHEN IF/ON ... ELSE ... PERFORM ... END-IF ... END-PERFORM IF/ON ... ELSE ... SEARCH ... END-IF ... WHEN PERFORM ... IF/ON ... END-PERFORM ... ELSE/END-IF PERFORM ... SEARCH ... END-PERFORM ... WHEN SEARCH ... IF/ON ... WHEN ... ELSE/END-IF SEARCH ... PERFORM ... WHEN ... END-PERFORM SEARCH ... WHEN ... IF/ON ... WHEN ... ELSE/END-IF SEARCH ... WHEN ... PERFORM ... WHEN ... END-PERFORM SEARCH ... SEARCH ... WHEN ... WHEN IF ... ELSE ... IF ... END-IF ... ELSE IF ... IF ... ELSE ... ELSE ... END-IF ... END-IF S touto výjimkou je ve větě programu přípustná jakákoliv kombinace výše uvedených příkazů (viz body a až e výše); klauzule ELSE a END-IF jsou ovšem přípustné pouze pro příkazy IF a ON a klauzule END-PERFORM je přípustná pouze pro příkaz PERFORM bez procedury, zatímco pro ostatní příkazy neexistují explicitní omezovače rozsahu (jejich rozsahy mohou být v případě potřeby omezeny např. pomocí "PERFORM ... END-PERFORM") Provádění věty programu začíná zásadně od jejího prvního příkazu a probíhá (až po ukončující tečku) dle těchto pravidel: 1) Pokud určitý příkaz nezpůsobuje odskok, přechází se po jeho provedení na bezprostředně následující příkaz. Totéž nastává též pro příkaz IF s pravdivým podmíněným výrazem a pro příkaz ON s "označeným" průchodem, dále pro příkaz PERFORM bez procedury, má-li se odpovídající úsek programu provádět alespoň jednou, a konečně pro každý příkaz s uplatnivší se klauzulí AT END, INVALID KEY atd. 2) Příkaz IF s nepravdivým podmíněným výrazem resp. příkaz ON s "neoznačeným" průchodem způsobí odskok dle těchto pravidel: a) Má-li tento příkaz IF/ON klauzuli ELSE, skočí se za tuto klauzuli ELSE. b) Nemá-li tento příkaz IF/ON klauzuli ELSE, skočí se za konec rozsahu tohoto příkazu IF/ON (tj. na klauzuli END-IF uvedenou explicitně nebo předpokládanou implicitně v důsledku tečky nebo v důsledku některé z klauzulí END-PERFORM nebo WHEN. 3) Dosažení klauzule ELSE způsobí odskok za konec rozsahu odpovídajícího příkazu IF/ON (stejně jako v bodě 2b). 4) Příkaz SEARCH, jenž nalezl hledaný speciální index, skočí za příslušnou klauzuli WHEN. 5) Dosažení klauzule WHEN nebo provedení příkazu SEARCH bez klauzule AT END, jenž nenalezl hledaný speciální index, nebo provedení příkazu s neuplatnivší se klauzulí AT END, INVALID KEY atd. způsobí odskok za konec rozsahu tohoto příkazu (tj. za tečkou nebo na explicitně uvedenou nebo implicitně předpokládanou klauzuli END-IF resp. END-PERFORM). 6) Příkaz PERFORM bez procedury, jehož odpovídající úsek programu se nemá provádět ani jednou, způsobí odskok za návratový můstek vygenerovaný na konci jeho rozsahu (tj. za tečku nebo za explicitně uvedenou nebo implicitně předpokládanou klauzuli END-PERFORM). 7) Dosažení konce rozsahu příkazu PERFORM bez procedury (tj. návratového můstku vygenerovaného v důsledku tečky nebo v důsledku explicitně uvedené nebo implicitně předpokládané klauzule END-PERFORM) způsobí a) v případě, že se úsek programu má ještě znovu provádět: návrat na první příkaz v odpovídajícím úseku programu; b) v případě, že se úsek programu už nemá znovu provádět: přechod za tento návratový můstek. 8) Dosažení klauzule END-IF nebo tečky nezpůsobí žádný odskok, nýbrž se přejde na provádění příkazu resp. návratového můstku následujícího za tímto END-IF resp. za touto tečkou. 9) Výše uvedená pravidla platí ovšem pouze do případného provedení příkazu způsobujícího opuštění věty bez návratu (GO a případně též PERFORM, CALL, FETCH, UFO, vyvolání deklarativní sekce atd.) nebo ukončení výpočtu (STOP RUN nebo chyba). Vzhledem k tomu, že výše uvedená pravidla jsou poměrně složitá a že v praxi daleko nejužívanějším prostředkem pro ukončení rozsahu příkazu bývá tečka, mluví se v této příručce většinou zjednodušeně a nepřesně o "odskoku za konec rozsahu tohoto příkazu". 5.2. Odkazy na procedury Programátorské slovo "procedura" se vyskytuje ve formátech příkazů GO, PERFORM, ALTER, CALL, UFO, SORT a MERGE a označuje jednu proceduru (sekci nebo paragraf) v PROCEDURE DIVISION. Je-li ve formátu uvedena "procedura", je třeba ve zdrojovém programu zapsat jednu z těchto tří možností: jméno-paragrafu jméno-sekce jméno-paragrafu {OF | IN} jméno-sekce Zápis "jméno-paragrafu" nebo "jméno-sekce" je přípustný pouze tehdy, když v celé PROCEDURE DIVISION existuje právě jedna procedura s tímto jménem. Výjimka je přípustná v případě, leží-li příkaz odvolávající se na jméno paragrafu v téže sekci jako tento paragraf. V tom případě lze použít i samotné "jméno-paragrafu" bez kvalifikace, i kdyby v jiné sekci existoval paragraf s týmž jménem. Začátek oddílu PROCEDURE DIVISION před první sekcí se přitom považuje za jednu sekci. Překladač však pro jistotu hlásí upozornění. Při zápisu "jméno-paragrafu OF/IN jméno-sekce" musí v PROCEDURE DIVISION existovat právě jedna sekce uvedeného jména; zápis pak určuje tento paragraf. Říkáme, že paragraf je určen pomocí kvalifikace. Slova OF a IN jsou ekvivalentní. Jméno paragrafu musí být kvalifikováno jménem sekce tehdy, když v jiné sekci existuje paragraf s týmž jménem, přičemž příkaz odvolávající se na paragraf leží v jiné sekci než tento paragraf. Kvalifikaci lze však použít i tehdy, když se jméno paragrafu neshoduje se jménem žádné jiné procedury, takže je kvalifikace nadbytečná. Příklady: GO TO PARAGRAF PERFORM PAR OF SEK1 THRU PAR IN SEK2 GO TO P1 S1 P2 S2 S3 P4 IN S4 DEPENDING I Poznámka: Z výše uvedených pravidel vyplývá, že při volbě jmen procedur (s výjimkou těch procedur, na které nebudou v programu žádné odkazy) je třeba dodržovat následující pravidla: a) Jméno sekce se nesmí shodovat se jménem žádné jiné procedury (sekce ani paragrafu). b) Dva paragrafy z téže sekce (anebo ze začátku PROCEDURE DIVISION před první sekcí) nesmí mít stejná jména. c) Dva paragrafy z různých sekcí smí mít stejná jména (je to možné i v případě, že jeden z těchto dvou paragrafů leží na začátku oddílu před první sekcí; na takový paragraf však nelze odkazovat ze žádné sekce, nýbrž jen ze začátku oddílu, neboť jeho jméno nemůže být opatřeno kvalifikací). Poznámka: Jméno procedury se smí shodovat se jménem kteréhokoliv objektu z DATA DIVISION (položky, speciálního indexu, podmínkového jména, souboru, komunikační oblasti, sestavy); takové jméno však nesmí být použito jako argument v příkazu CALL nebo UFO. 5.3. Aritmetický výraz Aritmetický výraz je v COBOLu přípustný v příkazu COMPUTE a v podmíněném výrazu (v relačním testu a ve znaménkovém testu). Aritmetickým výrazem nazýváme přípustnou posloupnost složenou z těchto prvků: a) operandy: numerické položky numerické literály ZERO, ZEROS, ZEROES (ekvivalentní s 0) b) aritmetické operátory: + ... sečítání nebo unární plus - ... odečítání nebo unární minus * ... násobení / ... dělení ** .. umocňování (píše se bez mezery) c) závorky: ( ... levá závorka ) ... pravá závorka Poznámka: Operátory + a - se používají ve dvojím významu: a) Jako tzv. duální plus a minus (pro sečítání a odečítání), vztahující se ke dvěma členům (předcházejícímu a následujícímu). Tak je tomu v případě, stojí-li + resp. - za operandem nebo za pravou závorkou. b) Jako tzv. unární plus a minus, vztahující se jen k jednomu členu (následujícímu). Tak je tomu v případě, stojí-li + resp. - na začátku aritmetického výrazu nebo za levou závorkou nebo za duálním operátorem. Unární plus je neúčinné, unární minus znamená změnu znaménka. Operátory *,/ a ** se vždy vztahují ke dvěma členům. Příklad: a) duální + a -: A + B, A + (B - C) - (D - E) b) Unární + a -: - A, - A * B, A / (- B ** ( - C)), A * -B, A / + B, A ** - B Tabulka 6: Přípustné pořadí prvků v aritmetickém výrazu. ------------------------------------------------------- | . smí stát | operand| + | ) * | | . prvek | ( | - | / ** | | za . | | | | | prvkem . | | | | |------------|---------|---------------------|--------| | operand | ne | ano | ano | | ) | | (+,- je pak duální) | | |------------|---------|---------------------|--------| | ( | ano | ano | ne | | duální +,- | | (+,- je pak unární) | | | * / ** | | | | |------------|---------|---------------------|--------| | unární +,- | ano | ne | ne | ------------------------------------------------------- Kromě toho platí tato pravidla: 1) Na začátku aritmetického výrazu smí stát operand, levá závorka, plus a minus (jsou to pak unární operátory). 2) Každé levé závorce musí odpovídat právě jedna pravá závorka a naopak; musí jich tedy být stejný počet. Vždy musí být levá závorka před sobě odpovídající pravou závorkou a mezi nimi musí být právě tolik levých závorek, kolik je tam pravých závorek. 3) Konec aritmetického výrazu nastává v situaci, kdy za operandem nebo za pravou závorkou je tečka nebo tam není ani operátor ani pravá závorka anebo je tam pravá závorka, které však v tomto aritmetickém výrazu neodpovídá žádná levá závorka. Poznámka: Za aritmetický výraz považujeme tedy i samotný operand, tj. numerickou položku nebo numerický literál nebo ZERO (ZEROS, ZEROES). Význam: Při provádění příkazu obsahujícího aritmetický výraz se tento aritmetický výraz vyčísluje, čímž se získá jeho numerická hodnota. Při vyčíslování aritmetického výrazu platí tato pravidla o prioritách: a) Nejvyšší prioritu mají závorky (od vnitřních k vnějším). b) Pořadí priorit aritmetických operátorů je následující: unární + nebo - (největší priorita) ** (menší priorita) * nebo / (ještě menší priorita) duální + nebo - (nejmenší priorita) c) Není-li v pořadí prováděných aritmetických operací určeno závorkami ani výše uvedenými prioritami aritmetických operátorů (např. A + B + C + D), provádějí se tyto aritmetické operace v pořadí zleva doprava. Příklad: Aritmetický výraz - A - B * - C / (D + E) + F * - G ** - H se vyčísluje stejně, jako kdyby byl uzávorkován takto: ((- A) - ((B * (- C)) / (D + E))) + (F * ((- G) ** (- H))). Poznámka: V aritmetickém výrazu - A**B má unární minus vyšší prioritu než umocňování, takže se tento výraz vyčísluje jako (- A)**B. Je však vhodné se výrazům tohoto typu vyhnout, neboť některé jiné implementace jazyka COBOL by tento výraz vyčíslily jako - (A ** B). Poznámky: 1) Použití numerické položky s nepřípustným obsahem (tzn. obsahem neodpovídajícím popisu) může vést k nesprávnému výpočtu anebo dokonce k chybě a k ukončení výpočtu. 2) Dělení operandem s nulovou hodnotou vede k chybě a k ukončení výpočtu; u příkazů COMPUTE a DIVIDE lze tomu zabránit uvedením klauzule ON SIZE ERROR (která se pak uplatní). 3) Je-li B celočíselná numerická položka nebo celočíselný numerický literál, přičemž B má nejvýše 4 dekadická místa, pak pro mocninu A ** B platí: a) Při B > 0 je A ** B = A*A*...* A (násobí se B-krát hodnota argumentu A). b) Při B = 0 je A ** B = 1 (i v případě, že A = 0). c) Při B < 0, A != 0 je A ** B = 1 - / (A * A * ... * A) násobí se (-B)-krát hodnota argumentu A). d) Při B < 0, A = 0 dojde v programu icbexpi k chybě (dělení nulou v exponenciálním tvaru). 4) Je-li B neceločíselná numerická položka (tzn. s neceločíselným popisem, i kdyby okamžitá hodnota byla celočíselná) nebo neceločíselný numerický literál nebo numerický literál s více než 4 ciframi, pak mocnina A ** B se spočítá pomocí funkce pow(x,y) jazyka C. Poznámka: Podrobný popis způsobu, kterým je vyčíslován aritmetický výraz, je uveden v kapitole 6.10 (Formát mezivýsledků aritmetického výrazu). Základní zásady pro psaní efektivně vyčíslovaných aritmetických výrazů jsou: a) Nepsat příliš složité aritmetické výrazy. b) Lze-li celý výpočet provést v pevné řádové tečce, nedopustit převádění operandů z pevné řádové tečky do exponenciálního tvaru. c) K výpočtům používat zásadně jen binární položky s maximálně 9 ciframi anebo položky s USAGE COMP-1 a COMP-2. 9. POMOCNÉ VSTUPY A VÝSTUPY 9.1. Pomocné soubory Práce s vnějšími zařízeními (tj. vstupy a výstupy) se dá v COBOLu provádět těmito způsoby: 1) Pomocí souborů deklarovaných ve FILE-CONTROL klauzulemi SELECT a popsaných ve FILE SECTION klauzulemi FD, pro něž jsou prováděny příkazy OPEN, CLOSE, WRITE, READ, REWRITE, DELETE, START, MATCH, SORT, MERGE a příkazy pro Generátor sestav. 2) Pomocí příkazů DISPLAY, EXHIBIT, ACCEPT, STOP a READY TRACE, které provádějí vstup a výstup pro některé soubory definované operačním systémem, aniž by uživatel musel pro ně deklarovat nějaké soubory pomocí klauzulí SELECT a FD. a) Zápis na standardní výstup stdout se provádí pomocí příkazů DISPLAY a EXHIBIT bez klauzulí AT i UPON nebo s klauzulí UPON STDOUT resp. UPON SYSLST resp. UPON SYSOUT resp. UPON PRINTER anebo pomocí příkazu DISPLAY NEWPAGE. Na týž výstup stdout se zapisuje i stopa programu způsobená provedením příkazu READY TRACE. b) Zápis na standardní výstup stderr (což většinou znamená zápis na obrazovku v řádkovém režimu) se provádí pomocí příkazů DISPLAY a EXHIBIT s klauzulí UPON STDERR resp. UPON CONSOLE resp. UPON SYSLOG a pomocí příkazu STOP literál. c) Zápis na obrazovku v obrazovkovém režimu se provádí pomocí příkazu DISPLAY s klauzulí AT nebo s klauzulí UPON CRT. d) Čtení ze standardního vstupu stdin se provádí pomocí příkazu ACCEPT bez klauzulí AT i FROM nebo s klauzulí FROM STDIN resp. FROM SYSIPT resp. FROM SYSIN. e) Čtení z klávesnice v řádkovém režimu se provádí pomocí příkazu ACCEPT s klauzulí FROM CONSOLE. f) Čtení z klávesnice v obrazovkovém režimu se provádí pomocí příkazu ACCEPT s klauzulí AT nebo s klauzulí FROM CRT. Pravidla: Při zpracování pomocí příkazů DISPLAY, EXHIBIT, ACCEPT, STOP a READY TRACE se standardní soubory stdout, stderr a stdin pokládají za sekvenční textové soubory (viz 3.4.4.A). Do souborů stdout a stderr se (při neuvedení parametru CBL AFTER a s výjimkou příkazu DISPLAY NEWPAGE) zapisuje stejným způsobem, jako to činí příkaz WRITE s klauzulí BEFORE 1.