11. PŘÍKAZY PRO SPOJOVÁNÍ PROGRAMU Jazyk MX COBOL poskytuje prostředky pro předání řízení z jednoho programu do druhého a pro případný návrat zpět. Při předání řízení je možno současně předat druhému programu i argumenty. Oba tyto programy musí být spojeny v jednom běhu spojovacího programu a v okamžiku předávání řízení musí být oba dva v paměti. Předání řízení a argumentů je možné: a) Z jednoho cobolského programu do jiného cobolského programu. b) Z cobolského programu do programu v jiném jazyce (většinou v jazyku C nebo ve Fortranu apod.). c) Z programu v jiném jazyce (většinou v jazyku C nebo ve Fortranu apod.) do cobolského programu. 11.5. Předávání řízení v COBOLu V předešlých odstavcích byly popisovány především ty situace, kdy jeden z obou programů (volající nebo vyvolaný) byl cobolský a druhý byl napsán v jiném jazyce, většinou v jazyku C. Zde se zřejmě program v jazyku C musí při přebírání resp. předávání řízení a argumentů přizpůsobit konvencím, které jsou u cobolského programu pevně dané (tzn. že cobolský příkaz CALL neočekává a cobolský příkaz ENTRY neposkytuje funkční hodnotu, a že cobolský příkaz ENTRY očekává jako skutečné argumenty výhradně ukazatele; všechny ostatní konvence jsou v COBOLu stejné jako v jazyku C). Jsou-li oba programy cobolské, programátor nemusí konvence jazyka C znát ani se o ně zajímat, neboť tyto konvence jsou automaticky oboustranně splněny. Programátor může tedy předávat řízení a argumenty příkazem CALL na příkaz ENTRY v jiném programu a vracet se zpět příkazem GOBACK nebo EXIT PROGRAM, přičemž musí dodržovat pouze tyto zásady: 1) Externí jméno uvedené za slovem CALL musí být stejné jako externí jméno uvedené za slovem ENTRY. (Např. CALL 'TYGR' a ENTRY 'TYGR'.) 2) Odpovídající si příkazy CALL a ENTRY by měly být buďto oba bez klauzule USING (nepředávají-li se argumenty) anebo by oba měly mít klauzuli USING a v ní týž počet argumentů. (Ve speciálních případech lze ovšem tuto podmínku porušit.) Argumenty za USING v příkazu CALL by měly být pouze položky, speciální indexy a literály, snad též externí jména a ve speciálních případech i soubory, třídicí soubory nebo "/položka", aby byly příkazu ENTRY předávány adresy a nikoliv hodnoty 3) Argumenty na odpovídajících si místech v příkazu CALL a v příkazu ENTRY by si měly odpovídat co do typu, popisu a významu. Tomu je třeba rozumět takto: Každá položka z LINKAGE SECTION má zde svůj vyčerpávající popis a při použití v kterémkoliv příkazu je zpracovávána podle tohoto popisu. Její číslo úrovně, PICTURE, USAGE, OCCURS, nadřízené a podřízené položky, REDEFINES atd. jsou pevně určeny a nelze je měnit. Jediné, co chybí, je adresa v paměti, a tato se získá např. při předání řízení na příkaz ENTRY. Vyvolaný program předpokládá, že na adresa argumentu uvedeného v příkazu CALL začíná úsek paměti přesně téže délky a struktury, jak to odpovídá popisu položky uvedené v příkazu ENTRY, a podle toho také s tímto úsekem pracuje. Pokud uživatel nezajistil, aby tento úsek paměti měl očekávanou délku a strukturu, může to vést k nesprávnému výpočtu nebo dokonce k chybě a k ukončení výpočtu (viz 4.9.). Z toho plynou následující doporučení: a) V běžných případech je vhodné používat jako argumenty v příkazu CALL pouze položky, které mají stejné popisy jako odpovídající položky v příkazu ENTRY (s výjimkou čísla úrovně, jména položky a klauzulí REDEFINES, OCCURS, VALUE, ENTRY a EXTRN). Pak při zpracování skutečného argumentu nemůže dojít k nesrovnalosti. (Např. je-li v příkazu ENTRY za USING uvedena položka z LINKAGE SECTION s PIC S99V9 COMP-3, je nejvhodnější, aby odpovídající argument uvedený v příkazu CALL za USING byla též položka s PIC S99V9 COMP-3.) b) Pokud položka u ENTRY má USAGE DISPLAY, lze bez nebezpečí použít jako argument u CALL alfanumerický literál o stejné délce, jakou má položka u ENTRY. Přitom je-li položka u ENTRY rozpakovaná, je nutné zapsat levostranné i pravostranné bezvýznamné nuly, vynechat desetinnou tečku a v případě záporné hodnoty změnit poslední cifru na vhodné písmeno. (Např. má-li položka u ENTRY PIC S999V99 USAGE DISPLAY, je nutno při požadované hodnotě 7.8 zapsat v příkazu CALL literál '00780', při požadované hodnotě -7.8 zapsat v příkazu CALL literál '0078@' neboli #3030373840# a při požadované hodnotě -12.56 zapsat v příkazu CALL literál '0125F' neboli #3031323546#.) c) Pokud položka u ENTRY má USAGE COMP-3, lze použít jako argument u CALL numerický literál. Je nutné zapsat levostranné i pravostranné bezvýznamné nuly, znaménko lze zapsat obvyklým způsobem, desetinná tečka je bezvýznamná a uživatel ji může uvést pouze pro přehlednost (viz způsob uložení numerického literálu popsaný v 11.1.). (Např. má-li položka u ENTRY PIC S999V99 COMP-3, je nutno při požadované hodnotě -7.4 zapsat v příkazu CALL literál -00740 nebo -007.40.) d) Při jakémkoliv popisu položky u ENTRY (včetně USAGE COMP, COMP-1, COMP-2 nebo INDEX) lze použít jako argument u CALL hexadecimální zápis alfanumerického literálu (viz 1.3.2.). (Např. má-li položka u ENTRY PIC S9(5) COMP, je nutno při požadované hodnotě 165 zapsat v příkazu CALL literál #A5000000# nebo #000000A5# v závislosti na způsobu uložení binárních hodnot v paměti počítače. (Podobně u exponenciálních položek. Tento způsob zadávání hodnoty je náročný, nekompatibilní a počítačově závislý; doporučujeme jej nepoužívat a raději předávat položku s vhodným VALUE.) e) Je-li v příkazu CALL použit jako argument speciální index, je nejvhodnější, aby mu v příkazu ENTRY odpovídala položka s USAGE INDEX (anebo binární numerická položka o délce 4 bytů). f) Je-li v příkazu CALL uvedeno jako argument jméno souboru, jméno třídicího souboru, jméno komunikační oblasti, externí jméno nebo "/ položka", je pak vlastně ve vyvolaném programu položka z LINKAGE SECTION ztotožněna s tabulkou souboru, komunikační oblastí (24 bytů), externím argumentem nebo s ukazatelem přiděleným položce uvedené za / pro úschovu adresy přiděleného úseku paměti. Pracovat pak rozumně pomocí cobolských příkazů je u tabulky souboru nebo komunikační oblasti značně obtížné (některé drobné opravy nebo testy lze však provést celkem jednoduše, např. změnit jméno tabulky souboru "dtfname") a u externího argumentu závislé na struktuře tohoto argumentu. U argumentu "/ položka" lze běžnými cobolskými příkazy adresu zvětšit nebo zmenšit (např. ADD 4 TO položka), pro dosazení adresy je však nejvhodnější příkaz UFO. Vyvolaný program může ovšem též argumenty těchto nezpracovatelných typů (jakož i argumenty všech ostatních typů, které vyjadřují hodnotu a nikoliv adresu) nezpracovávat sám, nýbrž je předat pomocí příkazu CALL dalšímu podprogramu, který již bude zapsán v jazyce C. Poznámka: Přeložený cobolský program bývá většinou o několik desítek až set bytů delší než přeložený program v jazyce C s touž funkcí. Proto je vhodné psát jednoduché podprogramy nikoliv v COBOLu, nýbrž v jazyce C. 11.6. Vzájemné vyvolávání podprogramů Mezi příkazy prováděnými ve vyvolaném programu mezi ENTRY a GOBACK smí být další příkaz CALL, jenž předává řízení do dalšího podprogramu. Takto lze předávat řízení i argumenty neomezeně. Je zajištěno, že všechny příkazy GOBACK se při návratech provedou správně. Může tedy být takové schéma: program A program B program C program D ------------------------------------------------------------ 1 CALL 'U'-------->ENTRY 'U' |<---------- | | | 2| | | | | | | 3 | | CALL 'V'-------->ENTRY 'V' | | |<---------- | 12| 11| 10| | 4| | | | | | 5 | --- GOBACK | CALL 'W'-------->ENTRY 'W' | | |<---------- | | 9| 8| 7| 6| | | | | | --- GOBACK --- GOBACK Kterýkoliv z těchto programů smí být napsán i v jiném jazyce, dodrží-li ovšem cobolské konvence. Kterékoliv dva nebo více z těchto programů se smí shodovat (tzn. smí být předáno řízení na týž příkaz ENTRY, který již dříve dostal řízení a dosud je nevrátil příkazem GOBACK, nebo na jiný příkaz ENTRY téhož zdrojového programu); jediné teoretické omezení nastává, dostane-li se řízení znovu do programu, který předal příkazem CALL některou z položek definovaných překladačem, jejíž hodnota byla vytvořena v pracovním poli tohoto programu. Podprogramy v COBOLu tedy smí být rekursivní; kvůli kompatibilitě však před tím varujeme. Všechny položky z WORKING-STORAGE SECTION i ukazatele odpovídající položkám z FILE SECTION a z LINKAGE SECTION (jakož i všechny pracovní položky přeloženého programu) jsou ovšem ve statické paměti a nikoliv na zásobníku, takže jsou společné pro všechna rekursivní volání téhož cobolského programu; automatickou paměť (na zásobníku) lze v COBOLu vyhradit pouze příkazem UFO. Příklad: Ve výše uvedeném schématu smí být program A totožný s jedním z programů B, C nebo D. Uvedeme schéma pro program A totožný s programem C: program B program A = C program D ------------------------------------------------------------ 1 ENTRY 'U'<------------------- CALL 'U' | ------------------>| 2| | -------->12 | | 3 CALL 'V'----|---------------->ENTRY 'V' |<--------|------------ | 10| 11| 9| 4| | | | | 5 GOBACK------- | CALL 'W'------------>ENTRY 'W' | |<--------------- | | 8| 7| 6| | | | | ----- GOBACK --- GOBACK Poznámka: Je přípustné předávat pomocí příkazu CALL řízení i argumenty na příkaz ENTRY umístěný v témže cobolském programu (dokonce i na začátek programu, a to i rekurzívně): CALL 'KOZA' USING A B C. : : ENTRY 'KOZA' USING X Y Z. : : GOBACK. Pomocí této taktiky lze ztotožnit položku z LINKAGE SECTION s kterýmkoliv argumentem (např. s indexovanou položkou nebo s externím polem apod.). Oproti příkazům UFO a CALL 'ICIDENT', které tuto možnost poskytují také, je však použití příkazů CALL a ENTRY značně pomalejší a proto méně vhodné: CALL 'BERAN' USING A (I J K). . . . ENTRY 'BERAN' USING B. GOBACK. Poznámka: Předá-li volající program podprogramu nějaký argument pomocí vazby CALL-ENTRY, smí tento podprogram předat obdržený argument dalšímu podprogramu (opět pomocí vazby CALL-ENTRY). V tomto speciálním případě bude tedy argumentem příkazu CALL (v podprogramu) položka z LINKAGE SECTION: program A program B program C ------------------------------------------------------------ WORKING-STORAGE. LINKAGE. LINKAGE. 77 A PIC 99. 77 X PIC 99. 77 Y PIC 99. . . . . . . CALL 'Q' USING A. ENTRY 'Q' USING X. . . . . . . . . CALL 'R' USING X. ENTRY 'R' USING Y. . . . . GOBACK. GOBACK.