4.5.9.2. Klauzule ASCENDING/DESCENDING Formát: {{ASCENDING|DESCENDING} KEY IS jméno-položky...}... Pravidla: 1) Pro účely tohoto odstavce říkejme té položce, která má v popisu klauzuli OCCURS s jednou nebo více podklauzulemi ASCENDING nebo DESCENDING, hlavní položka. 2) V klauzuli OCCURS lze uvést jednu podklauzuli ASCENDING/ DESCENDING anebo několik těchto podklauzulí za sebou. V každé z nich je nutno uvést jedno nebo několik jmen položek; těmto položkám budeme říkat klíče. 3) Klíčem může být buďto sama hlavní položka nebo taková její podřízená položka, které přísluší právě tolik indexů jako hlavní položce (tzn. nesmí mít sama klauzuli OCCURS ani nesmí být podřízena takové položce s klauzulí OCCURS, která by byla podřízena hlavní položce). 4) V klauzulích ASCENDING/DESCENDING se uvádějí pouze jména klíčů bez kvalifikace a bez indexů. Musí být proto splněn požadavek, aby se každé zde uvedené jméno vyskytovalo mezi jmény položek podřízených k hlavní položce (včetně této hlavní položky samé) právě jednou. 5) Klíčem může být položka jakéhokoliv typu. 6) Celkový počet klíčů uvedených ve všech podklauzulích ASCENDING/DESCENDING jedné klauzule OCCURS smí být nejvýše 31. 7) Položka s klauzulí OCCURS ASCENDING/DESCENDING smí mít mezi svými podřízenými další položku s klauzulí OCCURS ASCENDING/DESCENDING. Význam: Klauzule ASCENDING/DESCENDING se uplatní výhradně při prohledávání tabulky příkazem SEARCH ALL (viz 12.2.) a při setřiďování tabulky v paměti některým z příkazů CALL 'ICSORT', CALL 'ICSORTM' a CALL 'ICSORTP'. Klauzule ASCENDING/DESCENDING uvedené u položky, která by nebyla použita v žádném z těchto příkazů, by byly zcela neúčinné a ignorovaly by se. V příkazu SEARCH ALL se za slovem ALL uvádí jméno položky, která musí mít v popisu klauzuli OCCURS s alespoň jednou podklauzulí ASCENDING/DESCENDING, v naší terminologii tedy jméno hlavní položky. Příkaz SEARCH ALL bude pracovat správně jedině tehdy, bude-li pole složené z opakovaných hlavních položek na začátku provádění tohoto příkazu SEARCH ALL setříděno vzhledem k uvedeným klíčům. Požadovaný způsob setřídění tohoto pole závisí jednak na tvaru klauzulí ASCENDING/DESCENDING, a jednak na tvaru klauzule WHEN v příkazu SEARCH ALL, kterážto klauzule WHEN obsahuje některé (ne nutně všechny) z klíčů uvedených též v klauzulích ASCENDING/DESCENDING. Platí tato pravidla: 1) Je-li v příkazu SEARCH ALL uvedeno v klauzuli WHEN méně klíčů než v klauzulích ASCENDING/DESCENDING, vyžaduje se při tomto příkazu SEARCH ALL setřídění pouze vzhledem ke klíčům uvedeným v této klauzuli WHEN. Ostatní klíče uvedené v klauzulích ASCENDING/DESCENDING a přitom neuvedené v klauzuli WHEN se přitom zcela ignorují a setřídění vzhledem k nim se nevyžaduje. (Připomeňme, že v klauzuli WHEN lze uvést libovolný výběr klíčů definovaných klauzulemi ASCENDING/DESCENDING; například je možno první klíče z klauzulí ASCENDING/DESCENDING vynechat a pozdější uvést.) 2) Priorita klíčů závisí na jejich pořadí v klauzulích ASCENDING/DESCENDING (je zcela nezávislá na pořadí v klauzuli WHEN) a klesá od prvního k poslednímu uvedenému klíči přes všechny podklauzule ASCENDING/DESCENDING v příslušné klauzuli OCCURS. Tím je míněno, že hlavní položky musí být setříděny dle toho klíče, který je (pouze ovšem z klíčů uvedených ve WHEN) uveden v ASCENDING/DESCENDING jako první. Ty skupiny hlavních položek, které mají stejný tento první klíč, musí být setříděny dle toho klíče, který je (opět pouze z klíčů uvedených ve WHEN) uveden v ASCENDING/DESCENDING jako druhý. Ty skupiny hlavních položek, které mají stejný jak první tak i druhý klíč, musí být setříděny dle třetího klíče atd. Ty hlavní položky, které mají všechny klíče (uvedené ve WHEN) stejné, smí mít libovolné vzájemné pořadí; není však potom definováno, která z těchto hlavních položek bude při provádění příkazu SEARCH ALL nalezena. 3) Je-li klíč uveden za slovem ASCENDING, musí být hlavní položky setříděny vzhledem k němu vzestupně. Je-li klíč uveden za slovem DESCENDING, musí být hlavní položky setříděny vzhledem k němu sestupně. 4) Je-li určitý klíč srovnáván v klauzuli WHEN v příkazu SEARCH ALL alfanumericky, musí být hlavní položky setříděny vzhledem k tomuto klíči též dle svých alfanumerických hodnot. (Srovnávat ve WHEN numerické klíče alfanumericky je ovšem zcela zavrženíhodné.) Je-li klíč srovnáván v klauzuli WHEN numericky, musí být hlavní položky setříděny vzhledem k tomuto klíči dle svých numerických hodnot. 5) Správné setřídění hlavních položek musí zajistit před začátkem provádění příkazu SEARCH ALL uživatel. (Není-li toto setřídění zajištěno jiným způsobem, může uživatel provést setřídění sám s využitím příkazu SORT nebo pomocí příkazu CALL 'ICSORT' resp. CALL 'ICSORTM'.) Při chybném setřídění nebude příkaz SEARCH ALL schopen nalézt některé z hlavních položek porušujících setřídění. 6) Je-li hlavní položka podřízena další položce s klauzulí OCCURS, existuje vlastně v paměti několik polí obsahujících opakované hlavní položky. Ze všech těchto polí se při jednom provádění příkazu SEARCH ALL bude skutečně prohledávat pouze jediné (uživatel je určí prvním až předposledním indexem u klíčů v klauzuli WHEN) a pouze pro toto jediné pole se pro účely tohoto příkazu SEARCH ALL požaduje setříděnost. Pokud ovšem uživatel neví předem (a tak tomu většinou bývá), které z polí to bude, nelze jinak, než aby zajistil setříděnost všech těchto polí (tj. každého samostatně). 7) V praxi mívá většinou klauzule OCCURS uvedená u hlavní položky též podklauzuli DEPENDING. Pak se příkazem SEARCH ALL prohledává pole obsahující pouze tolik hlavních položek, kolik činí okamžitá hodnota celočíselné položky uvedené za slovem DEPENDING, a pouze pro tento počet hlavních položek se požaduje setříděnost. V příkazech CALL 'ICSORT', CALL 'ICSORTM' a CALL 'ICSORTP' se rovněž uvádí jméno položky mající v popisu klauzuli OCCURS s alespoň jednou podklauzulí ASCENDING/ DESCENDING. V příkazech CALL 'ICSORT' a CALL 'ICSORTM' se nevyžaduje žádné předběžné setřídění, zatímco v příkazu CALL 'ICSORTP' se vyžaduje setřídění první až předposlední hlavní položky dle všech klíčů uvedených v ASCENDING/DESCENDING. Všechny tyto tři příkazy CALL provádějí setřídění celého pole hlavních položek (a připravují je tím např. pro využití v příkazu SEARCH ALL). Vzniklé setřídění se ovšem může teoreticky lišit od setřídění požadovaného pro příkaz SEARCH ALL, a to v těchto bodech: - Zmíněné příkazy CALL setřídí pole vždy podle všech klíčů uvedených v klauzulích ASCENDING/DESCENDING; nelze v nich zadat, aby třídily jen podle některých klíčů a ostatní ignorovaly. (Pokud by příkaz SEARCH ALL vyžadoval jiné - výběrové - setřídění, bylo by nutné celou tabulku redefinovat a v redefinujícím popisu uvést v klauzulích ASCENDING/DESCENDING menší počet klíčů.) - Je-li v klauzuli WHEN v příkazu SEARCH ALL některý numerický klíč srovnáván s nenumerickým argumentem (tedy alfanumericky), vyžaduje příkaz SEARCH ALL setřídění hlavních položek vzhledem k tomuto klíči dle jejich alfanumerických (a nikoliv numerických!) hodnot. Příkazy CALL ovšem setřídí hlavní položky podle numerických hodnot tohoto klíče (s výjimkou osmibytových binárních, exponenciálních znakových a numerických editovaných klíčů). (Alfanumerické srovnávání numerických klíčů v klauzuli WHEN je zcela nevhodné a nemělo by být nikdy používáno.) - Je-li klíčem binární osmibytová, exponenciální znaková nebo numerická editovaná položka, třídí příkazy CALL dle tohoto klíče alfanumericky, což může být nevhodné pro příkaz SEARCH ALL. Doporučujeme takové klíče nepoužívat. - V případě vícerozměrného pole (viz bod 6 výše) setřídí příkaz CALL při jednom svém provedení pouze jediný "řádek" pole (potřebný první až předposlední index se uvádí v příkazu CALL přímo u hlavní položky), Je-li třeba setřídit všechny "řádky" tohoto vícerozměrného pole, je nutno provést pro každý z nich příkaz CALL samostatně. Příklad: 01 A. 02 B OCCURS 100 DEPENDING T ASCENDING C F DESCENDING H INDEXED I. 03 C PIC 999. 03 D PIC X(8). 03 E. 04 F PIC X(5). 04 G PIC 99 OCCURS 60 ASCENDING G INDEXED J. 03 H PIC S9(5)V99 COMP. : SEARCH ALL B WHEN F(I)=F1 AND H(I)=H1 AND C(I)=C1 ... Na začátku provádění příkazu SEARCH musí být pole obsahující položky B(1), B(2), ..., B(T) setříděno vzestupně dle klíče C. Skupiny položek B s týmž klíčem C musí být setříděny vzestupně dle klíče F. Skupiny položek B s týmiž klíči C a F musí být setříděny sestupně dle klíče H. Takovéto setřídění by bylo možno zajistit jediným provedením příkazu "CALL 'ICSORT' USING B". Kdyby měl příkaz SEARCH tvar pouze "SEARCH ALL B WHEN C(I)=C1", požadovalo by se pouze vzestupné setřídění dle klíče C; setřídění dle klíčů nižší priority F a H by se nevyžadovalo, avšak nevadilo by, takže i pro toto setřídění by bylo možno použít příkaz "CALL 'ICSORT' USING B" (ovšem vzhledem k nutnosti třídit i dle klíčů F a H by mohl být zbytečně pomalý). Kdyby však příkaz SEARCH měl tvar "SEARCH ALL B WHEN H(I)=H1", požadovalo by se pouze sestupné setřídění dle klíče H, což ovšem vylučuje současné setřídění dle klíčů vyšší priority. Proto bychom si celou tabulku redefinovali tak, aby v klauzulích ASCENDING/DESCENDING byla jedině položka redefinující klíč H (zde: HX): 01 REDEFINES A. 02 BX OCCURS 100 DEPENDING T DESCENDING HX. 03 PIC X(136). 03 HX PIC S9(5)V99 COMP. Pak bychom naši tabulku setřídili výhradně dle klíče H příkazem "CALL 'ICSORT' USING BX". V programu se asi vyskytuje příkaz "SEARCH ALL G ... WHEN G(K J)=G1 ..." (v praxi bude téměř jistě na místě indexu K uveden speciální index I, není to však nezbytné), kde hodnota indexu K je určena předešlým výpočtem (možná předcházejícím příkazem SEARCH). Pak pole obsahující položky G(K 1), G(K 2), ..., G(K 60) musí být setříděno vzestupně (dle klíče G). Neznáme-li předem hodnotu indexu K, musíme zajistit vzestupné setřídění každého z těchto polí pro K = 1,...,T například tak, že pro každé z nich provedeme zvláštní příkaz CALL 'ICSORT' např. pomocí cyklu PERFORM VARYING I UNTIL I > T CALL 'ICSORT' USING G(I). 4.5.9.3. Klauzule INDEXED Formát: INDEXED BY jméno-speciálního-indexu ... Funkce: Klauzule INDEXED se používá pro definování speciálních indexů. V klauzuli INDEXED je třeba uvést jedno nebo několik jmen, vytvořených zcela libovolně dle pravidel pro tvorbu jména-položky (viz 1.4.). Tato jména pak budou sloužit jako jména speciálních indexů spojených s touto klauzulí OCCURS. (Upozorňujeme, že veškerá definice speciálního indexu spočívá výhradně v uvedení jeho jména v některé klauzuli INDEXED; nikde jinde ve zdrojovém programu se žádná jiná definice nebo popis speciálního indexu neuvádí.) Speciální indexy se nepočítají mezi položky a nezabírají žádné byty paměti v rámci té struktury, v jejímž popisu jsou definovány. Každému speciálnímu indexu je přidělen jeden "long" (4 byty), nikoliv však v oblasti paměti přidělené položkám z DATA DIVISION, nýbrž v oblasti tabulek přeloženého programu. Hodnotu tohoto "longu" (chápanou jako u binární numerické položky s PIC S9(9) USAGE COMP) nazýváme hodnotou speciálního indexu. Tato hodnota speciálního indexu se přiděluje a využívá při provádění příkazů SET, PERFORM a SEARCH (a případně ještě CALL a UFO), může být testována relačním testem a může být vytisknuta pomocí příkazu DISPLAY nebo EXHIBIT; především se ovšem využívá při indexování (viz 4.3.). Poznámka: Klauzule INDEXED definující speciální indexy se kromě popisu položky vyskytuje ještě v klauzuli CD s volbou OUTPUT. Pravidla: 1) V klauzuli INDEXED se uvádí pouze jméno speciálního indexu bez kvalifikace; při použití je však možné toto jméno kvalifikovat pomocí jména té položky, v jejímž popisu je speciální index definován, a pomocí jmen položek k této položce nadřízených. 2) Počet jmen speciálních indexů v jedné klauzuli INDEXED ani v celém zdrojovém programu není omezen. 3) Na začátku výpočtu je hodnota všech speciálních indexů nulová (takže odpovídá pořadí 1). Použití: Speciální indexy se používají při indexování (viz 4.3.) za účelem zrychlení výpočtu adresy indexované položky. Zatímco při indexování celočíselnou numerickou položkou je třeba její hodnotu zmenšit o 1 a vynásobit délkou opakovaného úseku paměti (u rozpakovaných a pakovaných položek předtím ještě převést jejich hodnotu do binárního tvaru, což činí tyto položky naprosto nevhodnými pro indexování), při indexování speciálním indexem se žádné takové operace neprovádějí, neboť hodnota speciálního indexu přímo udává relativní vzdálenost indexované položky od začátku pole (takže to odečítání 1 a násobení již zahrnuje). Naproti tomu trvá déle přesun položky do speciálního indexu (jenž se ovšem provádí pouze jednou za celý cyklus anebo vůbec ne), srovnání speciálního indexu s numerickou položkou (jemuž by se měl programátor zásadně vyhnout a nahradit je srovnáním s jiným speciálním indexem) apod. Vždy je nutno uvážit, jakým způsobem je nejvýhodnější speciální indexy použít, aby se výpočet skutečně zrychlil (srovnej též kapitolu "Doporučení k optimalizaci"). Poznámka: Pokud se speciálním indexem pracujeme normálním způsobem pomocí příkazů SET, PERFORM a SEARCH (a neprovádíme nějaké mimořádné akce jako např. CALL, UFO nebo získání hodnoty speciálního indexu příkazem SET z UI-položky s nevhodnou hodnotou), bude hodnota speciálního indexu vždy celočíselným násobkem délky položky, v jejímž popisu je tento speciální index definován v klauzuli INDEXED (tj. délky opakujícího se úseku paměti; označme tuto délku písmenem d). I když to není povinné, bývá zvykem indexovat pomocí speciálního indexu pouze tu položku, v jejímž popisu je tento speciální index definován, a dále její podřízené položky; tedy pouze pro tu klauzuli OCCURS, v níž je tento speciální index definován. V takovém případě speciální index určuje při indexování n-tý prvek pole, právě když je jeho hodnota rovna (n-1)*d. (Speciální index lze bez nebezpečí používat i pro jinou klauzuli OCCURS pouze v tom případě, že tato jiná klauzule OCCURS má stejnou délku d opakujícího se úseku paměti - např. pracujeme-li současně se dvěma tabulkami a v nich s prvky s týmž indexem.) Je-li hodnota speciálního indexu celočíselným násobkem délky d (jak tomu v praxi bývá téměř vždy), definujeme pořadí odpovídající hodnotě speciálního indexu vzorcem pořadí = (hodnota / d) + 1 což můžeme vyjádřit též ve tvaru hodnota = (pořadí - 1) * d. Umístí-li uživatel do speciálního indexu uměle hodnotu, která není celočíselným násobkem délky d, anebo použije-li speciální index při indexování pro takovou jinou klauzuli OCCURS, která má délku opakujícího se úseku paměti jinou než d (což obojí by se mělo stávat jen ve zcela mimořádných případech), nelze definovat žádné "pořadí" odpovídající hodnotě speciálního indexu a při indexování je nutno používat složitější ("přesné") vzorce uvedené v 4.3. Příklad: 01 A. 02 B OCCURS 20 INDEXED I J. 03 C PIC X(5). 03 D PIC S9(4) OCCURS 15 INDEXED K. Při indexování píšeme např. B(I), B(J), B(J+3), C(I), D(I K), D(J OF B, K OF D IN A), D (I - 5 K + 4) apod. Má-li např. B(I) být 12. prvek pole, musí speciálnímu indexu I odpovídat pořadí 12, takže jeho hodnotu (tzn. binární hodnota "longu" přiděleného tomuto speciálnímu indexu) musí být (12-1)*65 = 715, neboť 65 = 5+15*4 je délka položky B. Tato hodnota 715 a tím i pořadí 12 se speciálnímu indexu I přidělí např. příkazem "SET I TO 12". Pomocí speciálních indexů I a J by bylo možno bez potíží indexovat i v libovolném jiném poli s délkou prvku 65 bytů, přičemž by bylo možné normálním způsobem provádět i příkazy SET, PERFORM a SEARCH. Poznámka: Při práci se speciálními indexy zná přeložený program pouze hodnotu speciálního indexu jakožto obsah přiděleného "longu", zatímco odpovídající pořadí se v něm nikde neobjeví. Naproti tomu programátor se normálně zajímá pouze o pořadí (12), zatímco hodnota odpovídající speciálnímu indexu (715) ani délka d opakujícího se úseku paměti (65) se ve zdrojovém programu prakticky nikdy neobjeví. Programátor by měl znát pojem "hodnota speciálního indexu" nikoliv kvůli vlastnímu programování, nýbrž kvůli hlubšímu porozumění situaci např. za účelem optimalizace nebo pro pochopení kontrolních výpisů při ladění apod. 4.5.10. Klauzule SIGN Formát: [SIGN IS] {LEADING | TRAILING} [SEPARATE CHARACTER] Pravidla: Klauzule SIGN smí být uvedena pouze v popisu skupinové položky anebo v popisu elementární položky, která splňuje tyto podmínky: a) Má uvedenu klauzuli PICTURE, přičemž vzor obsahuje povinně znak S a dále pouze znaky 9,V,P v kombinaci vyhovující pravidlům pro numerické položky s pevnou řádovou tečkou (viz 4.5.3.C1). b) Klauzule USAGE u ní není uvedena vůbec nebo je uvedena s volbou DISPLAY. Je-li klauzule SIGN uvedena u elementární položky, platí pouze pro ni. Je-li uvedena u skupinové položky, platí pak pro každou její podřízenou elementární položku, která nemá vlastní klauzuli SIGN, splňuje výše uvedené podmínky a,b a přitom není podřízena skupinové položce s klauzulí USAGE COMP nebo USAGE COMP-3. Pravidlo: Slovo SIGN resp. slova SIGN IS jsou nepovinná a bezvýznamná; klauzule tedy může znít pouze LEADING nebo TRAILING nebo LEADING SEPARATE nebo TRAILING SEPARATE. Význam jednotlivých formátů: Formát 1: [SIGN IS] LEADING (bez SEPARATE) Hodnota položky je zobrazena v paměti stejně jako u numerické rozpakované položky, pouze znaménkový půlbyte je umístěn v levém (!) půlbytu prvního bytu položky. Levý půlbyte posledního bytu položky musí obsahovat vždy hexadecimální číslici 3. Formát 2: [SIGN IS] TRAILING (bez SEPARATE Tento formát klauzule SIGN je pouze poznámkový; jedná se o obyčejnou rozpakovanou numerickou položku se znaménkem. Formát 3: [SIGN IS] {LEADING | TRAILING} SEPARATE CHARACTER Hodnota položky je zobrazena v paměti stejně jako u numerické rozpakované položky, avšak znaménko hodnoty neovlivní levý půlbyte u poslední číslice (zde musí být vždy hexadecimální 3), nýbrž bude mít reservováno samostatný byte, který bude připojen na začátek (při LEADING) resp. na konec (při TRAILING) položky. Na tomto bytu musí být při nezáporné hodnotě znak + a při záporné hodnotě znak -. (Popis položky je tedy přesně ekvivalentní témuž popisu bez klauzule SIGN, odstraníme-li ze vzoru znak S a přidáme-li ke vzoru znak + vlevo (při LEADING) resp. vpravo (při TRAILING); tato úprava však změní způsob interpretace klauzule VALUE, která se při klauzuli SIGN interpretuje numericky, zatímco při PIC +999 resp. 999+ alfanumericky.) Příklad: 02 A PIC S9V9 LEADING. 02 B PIC S9V9 TRAILING. 02 C PIC S9V9 LEADING SEPARATE. 02 D PIC S9V9 TRAILING SEPARATE. || A | B | C | D hodnota || zn. hex. | zn. hex. | zn. hex. | zn. hex. ---------||----------|----------|-------------|------------- 6.8 || 68 3638 | 68 3638 | +68 2B3638 | 68+ 36382B -6.8 || F8 4638 | 6H 3648 | -68 2D3638 | 68- 36382D -0.1 || @1 4031 | 0A 3140 | -01 2D3031 | 01- 30312D 0 || 00 3030 | 00 3030 | +00 2B3030 | 00+ 30302B Položka B je obyčejná rozpakovaná numerická položka, klauzule "[SIGN IS] TRAILING" se u ní ignoruje. Až na rozdílnou interpretaci případné klauzule VALUE jsou popisy položek C a D přesně ekvivalentní popisům 02 C PIC +9V9. 02 D PIC 9V9+. Poznámka: Položky s klauzulí SIGN formátu 1 nebo 3 se v tomto COBOLu považují za numerické editované položky; ode všech ostatních numerických editovaných položek se však liší tím, že klauzule VALUE (viz 4.5.8.) se u nich interpretuje numericky a nikoliv alfanumericky. Tyto položky mohou být (tak jako všechny ostatní numerické editované položky) uvedeny všude tam, kde formát povoluje neceločíselné numerické položky, nikoliv však tam, kde formát povoluje pouze celočíselné numerické položky. Poznámka: Klauzule SIGN je v tomto COBOLu implementována kvůli kompatibilitě s těmi COBOLy, v nichž jedině klauzule SIGN umožňuje vstup numerických údajů se samostatně děrovanými znaménky (Formát 3). V našem COBOLu může být jakákoliv numerická editovaná položka použita jako vysílající položka v numerickém přesunu nebo jako operand v aritmetickém výrazu nebo v některém aritmetickém příkazu, a proto je Formát 3 klauzule SIGN již nadbytečný; místo něj lze popsat obyčejnou numerickou editovanou položku s "+ levým" nebo s "+ pravým" (viz výše C a D). Formát 1 klauzule SIGN nemůže být ničím nahrazen a používá se při čtení numerických údajů děrovaných na děrovači, jenž nadděrovává záporné znaménko nikoliv u poslední, nýbrž u první cifry. 4.5.11. Klauzule ENTRY Formát: ENTRY Pravidla: Klauzule ENTRY smí být uvedena pouze u položky z WORKING-STORAGE SECTION nebo z COMMUNICATION SECTION, která nemá klauzuli OCCURS ani není podřízena položce s klauzulí OCCURS, a která neleží ve struktuře za položkou s klauzulí OCCURS DEPENDING (tzn. pouze u položky s pevnou adresou). Jméno této položky musí vyhovovat požadavkům pro jméno v jazyku C (musí tedy začínat písmenem a nesmí obsahovat pomlčky) a nesmí to být FILLER. Funkce: Překladač prohlásí jméno položky (v němž však nejprve změní všechna malá písmena na velká!) za "externí" (jako tzv. "nabídku" pro spojovací program), přičemž mu jako adresu přidělí adresu prvního bytu položky. Toto jméno tedy bude přístupné všem programům, které budou s naším programem zpracovávány v jednom běhu spojovacího programu. Tyto programy mohou být napsány též v COBOLu (pak je třeba uvést totéž jméno jako jméno položky z LINKAGE SECTION, která má v popisu klauzuli EXTRN, anebo jako argument příkazu CALL uzavřený v závorkách) nebo v jazyku C (pak je třeba totéž jméno uvést jako jméno proměnné se specifikací "extern") anebo v kterémkoliv jiném programovacím jazyku, který umí předat jméno spojovacímu programu jako "poptávku", aniž by na toto jméno předával řízení. Tyto programy pak mohou s naší položkou (tj. s jejím úsekem paměti) pracovat, aniž by do nich bylo předem předáno řízení z našeho programu příkazem CALL, jenž by měl naši položku uvedenu jako argument za USING. Poznámka: Klauzule ENTRY žádným způsobem neovlivní práci s položkou v rámci toho programu, v němž je tato položka popsána; pouze ji zpřístupní jiným programům. Příklad: hlavní program (v jazyku C) vedlejší program (cobolský) ----------------------------------------------------------- extern long ALFA; WORKING-STORAGE SECTION. extern double BETA; : extern char GAMA; 03 ALFA PIC S9(9) COMP ENTRY. : 03 BETA COMP-2 ENTRY. ALFA=5L; 03 GAMA PIC X VALUE 'A' ENTRY. BETA=ALFA+1.5; if (GAMA=='A') GAMA='B'; Příklad: hlavní program (cobolský) vedlejší program (cobolský) ---------------------------------------------------------- CALL 'TRETI' USING (DELTA) WORKING-STORAGE SECTION. CALL 'CTVRTY' USING A B : (DELTA) C (EPSILON) 03 DELTA PIC 9(5) ENTRY. : 02 EPSILON ENTRY. 03 T PIC X(20) OCCURS 60. Poznámka: Vzhledem k implementačním obtížím není klauzule ENTRY zatím realizována - při uvedení se ignoruje. 4.5.12. Klauzule EXTRN Formát: EXTRN Pravidla: Klauzule EXTRN smí být uvedena pouze u položky z LINKAGE SECTION s číslem úrovně 01 nebo 77. Jméno této položky musí vyhovovat požadavkům pro jméno v jazyku C (musí tedy začínat písmenem a nesmí obsahovat pomlčky) a nesmí to být FILLER. Je-li několik položek spojeno pomocí klauzule REDEFINES, smí být klauzule EXTRN uvedena nejvýše u jedné z nich. Pravidla: Překladač předá jméno položky (v němž však předtím změní všechna malá písmena na velká!) spojovacímu programu jako "poptávku". Spojovací program pak při spojování našeho programu najde v některém jiném programu spojovaném současně s naším (případně zařazeném pomocí tzv. autolinku) stejně znějící jméno a uloží adresu příslušející tomuto jménu do ukazatele přiděleného naší položce (viz 4.9.). Toto stejně znějící jméno musí být ve zmíněném jiném programu předáno spojovacímu programu jako "nabídka". Tento jiný program může být napsán též v COBOLu (pak totéž jméno musí být použito jako jméno položky z WORKING-STORAGE SECTION nebo z COMMUNICATION SECTION, která má v popisu klauzuli ENTRY; teoreticky by to mohlo být i jméno programu z PROGRAM-ID nebo externí jméno z příkazu ENTRY) nebo v jazyku C (pak totéž jméno musí být jménem proměnné definované mimo funkce bez specifikací "static" i "extern" anebo takovýmto jménem funkce) anebo v kterémkoliv jiném programovacím jazyku, jenž umí předat spojovacímu programu jméno jako "nabídku". Nalezne-li spojovací program skutečně takové stejně znějící jméno, bude mít naše položka přidělenu adresu skutečného úseku paměti již na začátku výpočtu a bude možno s ní (a též se všemi položkami jí podřízenými a dále se všemi položkami spojenými s ní pomocí klauzule REDEFINES a se všemi položkami jim podřízenými) okamžitě pracovat, aniž by bylo nutno předem předat řízení do našeho programu na záhlaví PROCEDURE DIVISION USING nebo na příkaz ENTRY. Poznámka (pro programátory znalé jazyka C): Při popisu např. "01 petr extrn." bude do přeloženého programu v jazyku C zařazena deklarace "extern unsigned char PETR[];" (malá písmena jsou vždy změněna na velká a programátor tomu nemůže zabránit), načež je ukazatel odpovídající položce s klauzulí EXTRN inicializován výrazem PETR. Programátor tedy nesmí pomocí příkazu UFD zařadit do přeloženého C-programu jinou deklaraci téhož jména PETR. Příklad: hlavní program (cobolský) vedlejší program (cobolský) ----------------------------------------------------------- LINKAGE SECTION. WORKING-STORAGE SECTION. 01 BETA EXTRN. 03 BETA VALUE ALL #000013# ENTRY. 02 GAMA PIC S9(5) 05 DELTA PIC S9(5) COMP-3 OCCURS 100. COMP-3 OCCURS 100. : : ADD 1 TO GAMA(I) MOVE DELTA(K) TO NEKAM Již na začátku výpočtu je položka BETA z hlavního programu ztotožněna s položkou BETA s vedlejšího programu (tzn. má přidělen její úsek paměti). Dokud nebude v hlavním programu přidělena položce BETA jiná adresa, zůstanou obě položky BETA totožné a v důsledku toho bude též GAMA(1) totožné s DELTA(1), GAMA(2) totožné s DELTA(2) atd. Příklad: hlavní program (cobolský) vedlejší program (v jazyku C) ----------------------------------------------------------- LINKAGE SECTION. short SIGMA; 77 SIGMA PIC S999 COMP EXTRN. struct {char x[100];} TAU; 01 TAU EXTRN. : 02 T PIC 9 OCCURS 100. : : : ADD 1 TO TAU(SIGMA) TAU.x[SIGMA-1]++;