17.15. ICMVC Funkce: Podprogram ICMVC provádí alfanumerický přesun zadaného počtu bytů z jednoho místa na druhé. Způsob volání: CALL 'ICMVC' USING { vysílající incrementv příjmový incrementp počet } ... Pravidla: Prvním argumentem "vysílající" a třetím argumentem "příjmový" smí být libovolný argument přípustný v příkazu CALL, který vyjadřuje adresu nějakého úseku paměti, tzn. položka, speciální index, jméno souboru, jméno třídicího souboru, externí jméno v závorkách (případně i s *), jméno komunikační oblasti nebo /položka, v případě prvního argumentu "vysílající" též literál. Druhým, čtvrtým a pátým argumentem musí být buďto celočíselný numerický literál (tj. celé číslo s případným znaménkem) nebo celočíselná numerická položka libovolného typu. Hodnota druhého a čtvrtého argumentu smí být i záporná, hodnota pátého argumentu "počet" musí být nezáporná a nejvýše rovna 65535 při celém čísle resp. 32767 při celočíselné položce. Adresa vysílajícího pole (tj. prvního bytu, jenž bude přesunován) je rovna součtu adresy prvního argumentu "vysílající" a hodnoty druhého argumentu "incrementv". Adresa příjmového pole (tj. bytu, do něhož bude přesunut první byte vysílajícího pole) je rovna součtu adresy třetího argumentu "příjmový" (jenž nesmí být literálem!) a hodnoty čtvrtého argumentu "incrementp". Podprogram ICMVC přesune z vysílajícího pole do příjmového pole tolik bytů, kolik činí hodnota pátého argumentu. Je-li tato hodnota rovna nule, nepřesunuje se nic, chyba to však není. Implicitní délky prvního a třetího argumentu se ignorují; vysílající resp. příjmové pole může ležet částečně nebo i celé mimo první resp. třetí argument. Přesun se provádí vždy alfanumericky, žádné kontroly ani úpravy přesunovaných bytů se neprovádějí. Předcházející i následující byty příjmového pole zůstávají beze změny. Pokud se vysílající a příjmové pole překrývají, platí stejná pravidla jako u funkce memcpy jazyka C, pomocí níž se přesun provádí. Příklady: CALL 'ICMVC' USING A 0 B 0 5000 CALL 'ICMVC' USING (ODKUD) 50 (KAM) 32 48 CALL 'ICMVC' USING A I B J K CALL 'ICMVC' USING 'ABCD' 0 D(I) 16 4 Použití: Příkaz CALL 'ICMVC' je překládán velmi efektivně, a to při pevném pátém argumentu přesunem struktur (tedy stejně jako příkaz MOVE nebo STRING) a při proměnném pátém argumentu voláním funkce memcpy jazyka C. Žádný podprogram ICMVC neexistuje a není dodáván. Je-li první argument položka nebo literál, třetí argument položka a druhý, čtvrtý a pátý argument celá nezáporná čísla, je příkaz CALL 'ICMVC' přeložen přesně stejně jako obyčejný příkaz MOVE (jenž ovšem vyžaduje pojmenování vysílajícího i příjmového pole a tedy jejich vyčlenění pomocí popisů) nebo příkaz STRING (jenž žádné vyčleňování obou polí nepotřebuje); všechny tyto příkazy se překládají jako přesun struktur. Při jiných typech prvního resp. třetího argumentu (třeba při externím jméně) nebo při proměnném druhém, čtvrtém nebo pátém argumentu je však použití příkazu CALL 'ICMVC' výhodnější, obzvláště proti příkazu STRING, jenž by byl realizován voláním dlouhého a pomalého podprogramu icbstrin. Příklad: 03 ALFA PIC X(60). : 05 BETA PIC X(80). Příkaz CALL 'ICMVC' USING ALFA 5 BETA 12 8 přesune 6.-13.byte položky ALFA na 13.-20.byte položky BETA, a to pomocí přesunu struktur, tzn. přesně stejně jako příkaz STRING ALFA POINTER 6 8 INTO BETA POINTER 13 8 Stejným způsobem by byl přeložen i příkaz MOVE, ovšem vyžadoval by zařadit dodatečné popisy přidělující jméno vysílajícímu i příjmovému poli: 03 ALFA. 04 PIC X(5). 04 ALFA1 PIC X(8). 04 PIC X(47). : 05 BETA PIC X(80). 05 REDEFINES. 06 PIC X(12). 06 BETA1 PIC X(8). 06 PIC X(60). : MOVE ALFA1 TO BETA1. (Pro vyčlenění ALFA1 a BETA1 byly úmyslně použity různé způsoby.) Pokud by bylo třeba provádět takovýchto dílčích přesunů větší množství s různými inkrementy a délkami, tyto dodatečné popisy by výrazně prodloužily a znepřehlednily zdrojový program; na druhé straně je ovšem ze všech uvedených způsobů příkaz MOVE jediný, jenž je realizován ve všech existujících implementacích jazyka COBOL. Pokud by některý z inkrementů nebo délka byly proměnné, je použití příkazu CALL 'ICMVC', např. CALL 'ICMVC' USING ALFA IA BETA IB DEL překládané voláním funkce memcpy (při celém čísle na místě DEL přesunem struktur) daleko výhodnější než příkaz STRING ALFA POINTER KA LENGTH DEL & KA = IA+1 INTO BETA POINTER KB LENGTH DEL & KB = IB+1 překládaný voláním dlouhého a pomalého podprogramu icbstrin. Pro účely příkazu MOVE by bylo nutno provádět redefinici na úrovni 01 typu (uvedeme jen pro ALFA) 01 REDEFINES. & redefinujeme 01 nadřízenou k ALFA 02 PIC X(400). & odpovídá položkám před začátkem ALFA 02 PIC X OCCURS 60 DEPENDING IA. 02 ALFA1. 03 PIC X OCCURS 60 DEPENDING DEL. Příkaz MOVE bude při pevné délce provádět přesun struktur stejně jako příkaz CALL 'ICMVC', zatímco při proměnné délce bude volat podpůrný podprogram, bude tedy méně efektivní než příkaz CALL 'ICMVC'. Příkazy MOVE a STRING jsou použitelné jen při položkách, zatímco příkaz CALL 'ICMVC' připouští obecný první a třetí argument, např. externí jméno: CALL 'ICMVC' USING (EXTPOLE) INCR (EXTFELD) 24 DEL. Poznámka: První až pátý argument se mohou za slovem USING několikrát opakovat. Každá pětice argumentů pak vyjadřuje jeden přesun, jenž bude proveden dle výše popsaných pravidel.