15. PŘÍKAZY COPY A REPLACE Poznámka: Příkazy COPY a REPLACE se ode všech ostatních příkazů jazyka COBOL liší tím, že to jsou příkazy pro překladač: provádějí se v době překladu a nikoliv v době výpočtu (proto se užívá též termínu "pseudopříkazy COPY a REPLACE"). V přeloženém programu již neodpovídají příkazům COPY a REPLACE žádné instrukce. 15.1. Příkaz COPY Funkce: Příkaz COPY způsobí vyhledání zadaného zdrojového textu (což jest normální soubor katalogizovaný v adresáři dle stejných pravidel jako vlastní zdrojový program) a jeho začlenění (zařazení, překopírování) do zdrojového programu. Formát: COPY { jméno-textu | 'jméno-textu' } [SUPPRESS] [ATTRIBUTE {řetězec | 'řetězec'}] [REPLACING {slovo-1 {BY|WITH} slovo-2}...]. Pravidla: 1) Příkaz COPY smí být ve zdrojovém programu uveden všude tam, kde se očekává slovo vytvořené dle pravidel pro jméno položky (včetně reservovaných slov), literál, závorka nebo aritmetický resp. relační operátor. Příkaz COPY se neuplatní, je-li zapsán tam, kde se očekává libovolný řetězec nebo vzor v klauzuli PICTURE, a dále uvnitř alfanumerického literálu, uvnitř libovolného řetězce, na poznámkovém řádku nebo v poznámkové části řádku za znakem &. 2) Příkaz COPY nemusí být zapsán celý na jediném řádku; může být zapsán i na několika řádcích zdrojového programu (stejně jako všechny ostatní příkazy jazyka COBOL). Kterékoliv slovo příkazu COPY smí ležet v poli A nebo v poli B řádku. 3) Příkaz COPY musí být vždy ukončen tečkou. Přitom zbytek řádku za touto ukončující tečkou by měl být mezerový nebo obsahovat poznámku (začínající znakem &). Napíše-li zde programátor nějaké klauzule nebo příkazy, budou tyto ignorovány, přičemž však překladač ohlásí upozornění. 4) Uvnitř příkazu COPY (tj. mezi slovem COPY a tečkou ukončující příkaz COPY) nesmí být uvedeno další slovo COPY nebo REPLACE (např. jako jméno-textu, řetězec, slovo-1 nebo slovo-2) ani zde nesmí začínat další příkaz COPY/REPLACE. 5) Parametr "jméno-textu" smí být uveden bez apostrofů nebo v apostrofech resp. uvozovkách. Měl by obsahovat identifikaci souboru obsahujícího zdrojový text, to jest jméno souboru (např. josef nebo 'josef.ab') nebo celou tzv. "cestu" (např. '/usr/mzdy/josef.c'). Má-li jméno-textu obsahovat lomítka, tečku apod., pak musí být zapsáno v apostrofech resp. uvozovkách. Překladač nemění malá písmena ve jméně-textu na velká (ani když je jméno-textu zapsáno bez apostrofů resp. uvozovek). Pod tímto jménem musí být v adresáři katalogizován zdrojový text, který má být pomocí tohoto příkazu COPY začleněn do zdrojového programu. Tento zdrojový text musí být v adresáři katalogizován v době překladu. 6) Zdrojový text se hledá v aktuálním adresáři resp. v adresáři určeném zadanou "cestou" dle obvyklých pravidel operačního systému (přesněji: C-příkazu "fopen"). 8) Za slovem ATTRIBUTE musí být uveden řetězec znaků složený pouze z písmen, číslic a pomlček o délce nejvýše 29 znaků, který nezačíná pomlčkou. Tento řetězec může ale nemusí být uzavřen v apostrofech; má-li však končit pomlčkou, pak v apostrofech uzavřen být musí. Překladač nahradí všechna malá písmena v tomto řetězci na odpovídající velká písmena. (Např. A, 5, ABC, 123, A-12, 1-2-3, 'W-', 'S1-A-' apod.; 'abc-' se změní na 'ABC-'.) 9) Parametry "slovo-1" a "slovo-2" mohou být jakákoliv slova vytvořená dle pravidel pro jméno položky (včetně reservovaných slov), literály, závorky nebo aritmetické resp. relační operátory. (Ani v klauzuli REPLACING však nesmí být porušena pravidla pro oddělování slov uvedená v 1.10.) Funkce: 1) Překladač zpracuje příkaz COPY tak, že vyhledá v adresáři zdrojový text se zadaným jménem a začlení jej celý do zdrojového programu bezprostředně za řádek, ne němž končí příkaz COPY. Zdrojový program se pak překládá přesně tak, jako kdyby příslušný zdrojový text byl přímo na místo příkazu COPY počínaje slovem COPY a konče posledním sloupcem toho řádku, na němž příkaz COPY končí (to jest včetně tečky za příkazem COPY, která tedy neukončuje tu větu resp. klauzuli zdrojového programu, v níž je příkaz COPY uveden). 2) Není-li uvedena ani klauzule ATTRIBUTE ani klauzule REPLACING, bude zdrojový text zařazen do zdrojového programu bez jakékoliv změny. Příklad: Nejčastějším případem použití příkazu COPY je, že v několika programech mají být zpracovávány logické věty s týmž popisem. Pak je vhodné vytvořit příslušné popisy jako samostatné soubory (zdrojové texty), katalogizovat je do adresáře a ve všech programech je zařadit pomocí příkazů COPY. Touto taktikou se jednak vyhneme zbytečnému opisování týchž popisů a jednak znemožníme omyly při popisování logických vět. V adresáři mějme katalogizován pod jménem BASA tento zdrojový text: 01 VEZEN. 02 JMENO PIC X(10). 02 CISLO PIC 999 COMP-3. 02 TREST PIC 999. Pak ve zdrojovém programu zapíšeme např.: FD BORY. COPY BASA. Překlad proběhne přesně tak, jako kdyby místo těchto dvou řádků zdrojového programu stály tyto řádky: FD BORY. 01 VEZEN. 02 JMENO PIC X(10). 02 CISLO PIC 999 COMP-3. 02 TREST PIC 999. Můžeme ovšem ve zdrojovém programu napsat též např.: FD SABINOV. 01 DOZORCE PIC X(50). COPY BASA. 02 HODNOST PIC X(5). 66 UDAJE RENAMES CISLO THRU HODNOST. Překlad proběhne přesně tak, jako kdyby místo těchto pěti řádků zdrojového programu stály tyto řádky: FD SABINOV. 01 DOZORCE PIC X(50). 01 VEZEN. 02 JMENO PIC X(10). 02 CISLO PIC 999 COMP-3. 02 TREST PIC 999. 02 HODNOST PIC X(5). 66 UDAJE RENAMES CISLO THRU HODNOST. Může ovšem být též výhodné uložit jakožto zdrojový text celý popis souboru (včetně FD) nebo několik struktur (01) za sebou anebo vhodnou posloupnost příkazů z PROCEDURE DIVISION (např. nějaký úsek programu volaný pomocí PERFORM) apod. Pokud by byl zdrojový text uložen pod jménem basa.cs, bylo by nutno psát COPY 'basa.cs' resp. COPY '/usr/bum/basa.cs' apod. 3) Je-li v příkazu COPY uvedena klauzule REPLACING, bude zdrojový text před zařazením do zdrojového programu změněn dále popsaným způsobem. Změna se však týká pouze toho textu, který se stává součástí zdrojového programu; zdrojový text katalogizovaný v adresáři se použitím příkazu COPY nikdy nijak nemění. Každé slovo zdrojového textu (jedná se o slova vytvořená dle pravidel pro jméno položky včetně reservovaných slov, literály, závorky a aritmetické resp. relační operátory) se postupně srovnává se všemi slovy-1 z dvojic "slovo-1 BY slovo-2" resp. "slovo-1 WITH slovo-2" z klauzule REPLACING: a) Shoduje-li se slovo zdrojového textu s některým slovem-1, nahradí se toto slovo ve zdrojovém programu (tj. pro účely překladu) odpovídajícím slovem-2 stojícím v téže dvojici za BY resp. WITH. Srovnávání našeho slova s dalšími slovy-1 z následujících dvojic "slovo-1 BY slovo-2" resp. "slovo-1 WITH slovo-2" se pak již neprovádí, takže je-li zadáno několik dvojic s týmž slovem-1, uplatní se pouze první z nich. (Rozdíl mezi slovy BY a WITH spočívá pouze v tom, že při BY se náhrada slovem-2 projeví i v protokolu o zdrojovém programu, zatímco při WITH se v protokolu ponechá původní slovo-1; srv. bod 8.) b) Neshoduje-li se slovo zdrojového textu s žádným slovem-1, převezme se toto slovo ze zdrojového textu do zdrojového programu beze změny. Tyto akce se provedou pro všechna slova zdrojového textu. Poznámka: Zásadně se tedy vždy nahrazuje jediné slovo jediným slovem; v MX COBOLu není možné nahradit jedno slovo více slovy (např. celou kvalifikací) nebo více slov jedním slovem nebo více slov více slovy, případně jedno nebo více slov zdrojového textu zrušit apod. Příklad: V adresáři mějme katalogizován pod jménem SCR3 tento zdrojový text: MOVE P TO HLAV-PODN. MOVE D TO HLAV-DATE. IF N = 0 MOVE 10 TO N. WRITE TISK. Použijeme-li pak ve zdrojovém programu příkaz COPY SCR3 REPLACING P BY 'SPOJENE LIHOVARY' D BY CURRENT-DATE N BY POCET 10 BY 20 WRITE BY RELEASE. bude do zdrojového programu zařazen tento opravený text: MOVE 'SPOJENE LIHOVARY' TO HLAV-PODN. MOVE CURRENT-DATE TO HLAV-DATE. IF POCET = 0 MOVE 20 TO POCET. RELEASE TISK. Poznámka: Pro shodu slova zdrojového textu se slovem-1 je nutné, aby obě tato slova měla přesně týž tvar. Výjimka nastává pouze u numerického literálu, který není celým číslem, kde se za navzájem ekvivalentní považují všechny literály s týmž počtem cifer mantisy, s týmž znaménkem a s touž hodnotou (např. +12.34, +12.34E0, +1.234E+01, +1234.E-2 atd.). Poznámka: Srovnávání se slovy-1 se netýká vzorů (a též slova IS) z klauzule PICTURE a libovolných řetězců, které nemohou být nahrazovány. 4) Je-li v příkazu COPY uvedena klauzule ATTRIBUTE, pak ve všech popisech položek a podmínkových jmen vyskytujících se ve zdrojovém textu překladač přidá před jména položek, podmínková jména a jména speciálních indexů řetězec znaků uvedený v klauzuli ATTRIBUTE a takto rozšířená jména teprve zařadí do zdrojového programu. Platí tato pravidla: a) Přidání řetězce před jméno se provádí pouze u popisů ve FILE SECTION, ve WORKING-STORAGE SECTION, v LINKAGE SECTION a v COMMUNICATION SECTION, nikoliv však u popisů v REPORT SECTION, ve SCREEN SECTION, ve FILE-CONTROL (SELECT, ACTUAL/NOMINAL/RECORD KEY), v I-O-CONTROL ani v PROCEDURE DIVISION. Přitom řetězec se přidává pouze k těmto jménům: - Ke jménu položky resp. k podmínkovému jménu následujícímu v popisu bezprostředně za číslem úrovně. - Ke jménu položky uvedenému za slovem REDEFINES, je-li číslo úrovně v popisu 02 až 49 (na úrovni 01 a 77 se řetězec ke jménu za REDEFINES nepřidává). - Ke jménům položek uvedeným v podklauzulích ASCENDING a DESCENDING klauzule OCCURS. - Ke jménům speciálních indexů uvedeným v podklauzulích INDEXED klauzule OCCURS. - Ke jménům položek i ke jménům jejich případných kvalifikátorů uvedeným v klauzuli RENAMES v popisu s číslem úrovně 66. - V COMMUNICATION SECTION ke všem jménům položek uvedeným v klauzuli CD jak ve slovních podklauzulích tak i v seznamu jmen (nikoliv však ke jménu komunikační oblasti následujícímu bezprostředně za slovem CD). b) Jméno položky resp. podmínkové jméno resp. jméno speciálního indexu ve zdrojovém textu, k němuž se přidává zleva řetězec z klauzule ATTRIBUTE, smí být nejvýše tak dlouhé, aby po přidání řetězce výsledná délka jména nepřesáhla 30 znaků. Výsledné jméno vzniklé přidáním řetězce musí vyhovovat pravidlům pro vytváření jmen položek. c) Uvedení klauzule ATTRIBUTE neovlivní následující jména, před něž tedy nebude zadaný řetězec přidáván: - Jména FILLER. - Jména souborů uvedená za FD, jména třídicích souborů uvedená za SD a jména komunikačních oblastí za CD. - Jména sestav uvedená v klauzuli REPORT/REPORTS v FD. - Jména položek uvedená v klauzuli REDEFINES při čísle úrovně 01 nebo 77 (proto je výhodné používat zápis klauzule REDEFINES s vynechaným jménem-položky-2). - Jména položek uvedená v podklauzuli DEPENDING klauzule OCCURS - je vhodné zde uvést položku, jejíž jméno se nemá měnit, tzn. položku popsanou mimo tento zdrojový text zařazovaný s klauzulí ATTRIBUTE. Potřebuje-li uživatel, aby příslušný řetězec byl přidán i před některé z výše vyjmenovaných jmen (což je někdy potřebné v případě klauzule REDEFINES i při čísle úrovně 01 nebo 77, v případě klauzule DEPENDING a u jmen souborů, třídicích souborů a komunikačních oblastí), musí toto jméno změnit explicitně pomocí klauzule REPLACING. d) Je-li v příkazu COPY uvedena jak klauzule ATTRIBUTE, tak i klauzule REPLACING, pak se na jména položek, na podmínková jména a na jména speciálních indexů, k nimž se přidává řetězec z klauzule ATTRIBUTE, již neaplikují změny předepsané klauzulí REPLACING (tzn. ani na původní ani na rozšířené jméno). Z obou klauzulí se tedy uplatní jen klauzule ATTRIBUTE. Použití: Klauzule ATTRIBUTE je výhodná tehdy, když má být do zdrojového programu několikrát zařazen tentýž zdrojový text obsahující popisy položek (např. popisy 01 od několika souborů zpracovávajících logické věty téže struktury). Použije-li uživatel v příkazech COPY (resp. ve všech kromě jednoho) klauzule ATTRIBUTE s různými řetězci, může pak položky ze zařazených zdrojových textů v příkazech používat bez kvalifikace, zatímco bez ATTRIBUTE by byla kvalifikace nezbytná. Znemožní tím ovšem použití příkazů s klauzulí CORRESPONDING. Příklad: V adresáři mějme katalogizován pod jménem RCD1 tento zdrojový text: 01 VETA. 05 CENA PIC 9(5)V99. 05 POCET PIC 9(8). Tento zdrojový text zařadíme do zdrojového programu dvakrát pomocí následujících příkazů COPY s klauzulí ATTRIBUTE: FD STARY. COPY RCD1 ATTRIBUTE A. FD NOVY. COPY RCD1 ATTRIBUTE 'B-'. Překlad proběhne přesně tak, jako kdyby místo těchto čtyř řádků zdrojového programu stály tyto řádky: FD STARY. 01 AVETA. 05 ACENA PIC 9(5)V99. 05 APOCET PIC 9(8). FD NOVY. 01 B-VETA. 05 B-CENA PIC 9(5)V99. 05 B-POCET PIC 9(8). Ve všech příkazech v PROCEDURE DIVISION, v klauzulích v REPORT SECTION (CONTROL, SOURCE, SUM atd.) a dále ve všech případech vyjmenovaných výše v bodě 4c musí uživatel sám přidávat před každé ze jmen VETA, CENA a POCET příslušný řetězec, podle toho, kterou položku má na mysli: 03 POM PIC XXX OCCURS 1000 DEPENDING APOCET. 02 COLUMN 50 PIC Z(5).99 SOURCE B-CENA. WRITE B-VETA FROM AVETA. ADD APOCET TO B-POCET. 5) Zapíše-li se ve FILE SECTION, ve WORKING-STORAGE SECTION nebo v LINKAGE SECTION (nikoliv tedy v REPORT SECTION ani ve SCREEN SECTION) příkaz COPY v konfiguraci {01|77} [jméno-položky-1 | FILLER] COPY atd. přičemž zařazovaný zdrojový text začíná rovněž {01|77} [jméno-položky-2 | FILLER] kde obě čísla úrovní jsou stejná (tj. obě jsou 77 nebo obě jsou 01 resp. 1), bude tento začátek zdrojového textu při zařazování vynechán: bude tedy ponecháno "jméno-položky-1" uvedené ve zdrojovém programu, k němuž se připojí klauzule následující ve zdrojovém textu za "jméno-položky-2" (jsou-li tam nějaké); "jméno-položky-2" se zcela ignoruje. Místo "jména-položky-1" i "jména-položky-2" smí být uvedeno slovo FILLER anebo smí být toto jméno vynecháno. Příklad: Pod jménem zdr2.t máme katalogizován tento zdrojový text: 01 A VALUE ZERO. 05 C PIC X. 05 D PIC 99 OCCURS 100. Uvedeme-li ve zdrojovém programu příkaz COPY 'zdr2.t' REPLACING A BY Z. zařadí se do zdrojového programu text 01 Z VALUE ZERO. 05 C PIC X. 05 D PIC 99 OCCURS 100. Uvedeme-li ve zdrojovém programu zápis 01 VETA COPY 'zdr2.t'. zařadí se do zdrojového programu text 01 VETA VALUE ZERO. 05 C PIC X. 05 D PIC 99 OCCURS 100. Zařadilo se tedy "01 VETA" ze zdrojového programu a text následující za "01 A" ve zdrojovém textu; slova "01 A" ze zdrojového textu se vynechala. Uvedeme-li ve zdrojovém programu příkaz COPY 'zdr2.t' ATTRIBUTE Y REPLACING A BY Z YA BY Q. zařadí se do zdrojového programu text 01 YA VALUE ZERO. 05 YC PIC X. 05 YD PIC 99 OCCURS 100. V tomto případě se neprováděla změna A na Z ani YA na Q, neboť při uplatnění klauzule ATTRIBUTE se ani na původní ani na rozšířené jméno již klauzule REPLACING neaplikuje. Uvedeme-li ve zdrojovém programu zápis 01 VETA COPY 'zdr2.t' ATTRIBUTE Y. zařadí se do zdrojového programu text 01 VETA VALUE ZERO. 05 YC PIC X. 05 YD PIC 99 OCCURS 100. V tomto případě se vynechala část "01 A" ze zdrojového textu. Řetězec Y se ke jménu VETA nepřidává (ani by se na jméno VETA neaplikovala případná klauzule REPLACING), neboť toto jméno nepochází ze zařazovaného zdrojového textu. 6) Zdrojový text zařazovaný pomocí příkazu COPY smí obsahovat další příkaz COPY (nutně ovšem celý až po závěrečnou tečku; není přípustné, aby tento "vnořený" příkaz COPY začínal ve zdrojovém textu a končil až po ukončení tohoto zdrojového textu). Přitom zdrojový text zařazovaný pomocí tohoto "vnořeného" příkazu COPY smí opět obsahovat další příkaz COPY atd. Takto lze do sebe vnořit nejvýše 9 úrovní příkazu COPY. Klauzule SUPPRESS, ATTRIBUTE a REPLACING smí být uvedeny i ve "vnořených" příkazech COPY obsažených ve zdrojových textech, přičemž platí tato pravidla: a) Volba SUPPRESS potlačí tisk protokolu i ode všech zdrojových textů zařazovaných pomocí vnořených příkazů COPY nezávisle na tom, zda tyto vnořené příkazy COPY samy mají nebo nemají uvedenu volbu SUPPRESS. b) Má-li příkaz COPY (na kterékoliv úrovni) uvedenu klauzuli ATTRIBUTE, nesmí už žádný z vnořených příkazů COPY mít též klauzuli ATTRIBUTE (takže v kterémkoliv místě na kterékoliv úrovni vnoření smí být "aktivní" nejvýše jedna klauzule ATTRIBUTE). Klauzule ATTRIBUTE se uplatní i pro všechny zdrojové texty zařazované pomocí vnořených příkazů COPY. c) Klauzule REPLACING se uplatní jak pro zařazovaný zdrojový text, tak i pro zdrojové texty zařazované pomocí vnořených příkazů COPY. Tyto vnořené příkazy COPY (jakož i vnořené příkazy REPLACE) též podléhají změnám způsobeným touto "vnější" klauzulí REPLACING, přičemž mohou mít samy vlastní klauzule REPLACING. Příklad: Hlavní zdrojový program obsahuje příkaz COPY T1 REPLACING B BY A, A BY B, D BY F, E BY G, T2 BY T3. Zdrojový text T1 obsahuje příkaz COPY T3 REPLACING C BY B, A BY H, D BY E. Je třeba si uvědomit, že příkaz COPY v zdrojovém textu T1 bude před zpracováním změněn pomocí klauzule REPLACING z příkazu COPY v hlavním zdrojovém programu, a to do tvaru COPY T3 REPLACING C BY A, B BY H, F BY G. Ve zdrojovém textu T1 se tedy mění B na A, A na B, D na F, E na G a T2 na T3. Ve zdrojovém textu T3 se mění B na A, A na B, D na F, E na G, T2 na T3, C na A a F na G (v T3 se tedy uplatní obě klauzule REPLACING od obou příkazů COPY, přičemž druhá z nich - od vnořeného příkazu COPY - se přijímá modifikovaná pomocí první klauzule REPLACING). Požadavek "B BY H" se neuplatní, protože požadavek "B BY A" od první klauzule REPLACING je uplatňován dříve. Každé D je změněno pouze na F a nikoliv již dále na G, neboť po uplatnění požadavku "D BY F" se další požadavky již netestují a neuplatňují. 8) Je-li v příkazu COPY uvedena volba SUPPRESS, potlačí se tisk zařazovaného zdrojového textu v protokolu o zdrojovém programu. Není-li v příkazu COPY uvedena volba SUPPRESS, zařazovaný zdrojový text se v protokolu o zdrojovém programu vytiskne, přičemž platí tato pravidla: a) Bezprostředně vlevo před každým řádkem pocházejícím ze zdrojového textu se v protokolu vytiskne "Cn", kde "n" je cifra 1,2,3,...,9 vyjadřující úroveň vnoření tohoto příkazu COPY (viz bod 6). b) Slova zdrojového textu změněná účinkem klauzule ATTRIBUTE nebo klauzule REPLACING, v níž příslušná dvojice má tvar "slovo-1 BY slovo-2", se v protokolu tisknou již ve změněném tvaru. Nahrazuje-li se však kratší slovo delším (jak je tomu vždy u klauzule ATTRIBUTE), měl by uživatel vynechat ve zdrojovém textu na příslušných řádcích dostatečný počet mezer (kdekoliv ve zbylé části zdrojového řádku za měněným slovem, např. přímo za měněným slovem nebo mezi následujícími slovy anebo na konci řádku resp. mezi posledním slovem a poznámkou začínající znakem &), aby se změněný text každého řádku opět vešel na jediný řádek. Nevejde-li se tam, bude sice náhrada slova pro účely překladu provedena správně, nebude však provedena v protokolu (a překladač ohlásí upozornění). (Toto se týká jen štítkového formátu zdrojového programu; při terminálovém formátu dokáže překladač sám prodlužovat řádek až do délky nejvýše 255 bytů.) K této situaci dojde vždy při nahrazování alfanumerického literálu s pokračovacími řádky. c) Slova zdrojového programu změněná účinkem klauzule REPLACING, v níž příslušná dvojice má tvar "slovo-1 WITH slovo-2", budou nahrazena pouze pro účely překladu, nebudou však změněna v protokolu o zdrojovém programu, v němž se tedy vytiskne původní slovo-1. (Volba WITH je vhodná např. při zápisu "REPLACING POCET-PRVKU WITH 120", přeje-li si uživatel ponechat v protokolu kvůli názornosti symbolické označení POCET-PRVKU, i když překladač bude ovšem akceptovat literál 120.) 9) Řádky s příkazem COPY se v protokolu o zdrojovém programu vytisknou vždy (nejedná-li se o příkaz COPY uvedený ve zdrojovém textu zařazovaném pomocí "vyššího" příkazu COPY s volbou SUPPRESS).