Czy koniecznie muszę wywołać program w języku CL ?
CzÄ™sto by zrealizować pewnÄ… funkcjÄ™ lub zadanie systemu operacyjnego najÅ‚atwiej jest posÅ‚użyć siÄ™ komendÄ… jÄ™zyka skryptowego CL. W koÅ„cu do tego powstaÅ‚ i sÅ‚uży. Jednak w przypadku gdy wspomniane zadanie chcemy zrealizować wewnÄ…trz programu w jÄ™zyku RPG czy ILE-RPG zmuszeni jesteÅ›my do stworzenia dodatkowego programu CL i wywoÅ‚ywania go wewnÄ…trz kodu RPG. Do tego dochodzi czÄ™sto przekazanie parametrów, zwrócenie wyników wywoÅ‚ania i przetwarzania. I tak z prostego wydawać by siÄ™ mogÅ‚o zadania robi siÄ™ prawdziwe wyzwanie …
Receptą na to by wykorzystać komendę języka CL bez wywoływania zewnętrznego programu jest użycie systemowego API realizującego takie wywołanie. Właściwie istnieje kilka takich API które umożliwiają uruchomienie komendy CL z programu RPG (lub innego dowolnego). Należy do nich API Execute Command QCMDEXC (udokumentowane tutaj). Pozostałe, rzadziej wykorzystywane to Process Commands API (QCAPCMD) oraz Execute Command (QCAEXEC).
A co potrzebne jest by zaimplementować wykorzystanie tych API we własnym programie ? By zademonstrować użycie jednego z nich posłużymy się bardzo prostym przykładem. Załóżmy że przygotowanie do przetwarzania pewnego pliku wymaga jego wyczyszczenia. Najprościej zrealizować to za pomocą komendy CL: CLRPFM FILE(NAZWA_PLIKU). Wykorzystując API QCMDEXC, wywołanie takiej komendy mogłoby wyglądać następująco:
DPsDs           SDS * D PsErrorMsgId                  7   Overlay(Psds:40) D* Prototyp QCMDEXC D QCMDEXC        PR                 Extpgm('QCMDEXC') D Command                  65535A  const options(*varsize) D CommandLength               15P 5 const D CommandOpt                   3   const options(*nopass) D Cmd            S          1024A D Message        C                  const('Nie znaleziono pliku' C                  Eval     Cmd = 'DLTF FILE(Biblioteka/PlikBD)' C                  CallP(e) QCMDEXC(%trim(Cmd) : %Len(%Trim(Cmd))) C                  If       %Error And PsErrorMsgId = 'CPF2105' C    Message      DSPLY C                  EndIf C                  Seton                                       LR C                  Return
Źródło programu rozpoczyna się deklaracją struktury danych reprezentującej status programu wraz ze zmienną która wskazuje na miejsce przechowywania informacji o kodzie błędu (znaki od 40 do 46 w strukturze). W kolejnych liniach znajduje się definicja prototypu funkcji API QCMDEXC oraz deklaracja zmiennej Cmd która będzie przechowywać treść komendy w języku CL.
Działanie programu wygląda następująco: po podstawieniu do zmiennej Cmd treści komendy CL, wywoływane jest API QCMDEXC (zdefiniowane jako prototyp o takiej samej nazwie jak API), a jako drugi parametry wywołania mamy funkcja określającą wielkość zmiennej tekstowej zawierającej komendę bez spacji. Jeśli komenda zostanie wykonana bezbłędnie (komenda języka CL zawarta w zmiennej Cmd) program przejdzie do dalszego przetwarzania (w naszym przypadku zakończy działanie), natomiast jeśli wystąpi błąd wykonania, w zmiennej PsErrorMsgId program zwróci kod błędu który może zostać obsłużony (w naszym przykładzie wyświetla się informacja o nieznalezieniu pliku).
Należy pamiętać że nie wszystkie komendy języka CL można wywołać wykorzystując wymienione funkcje API. Część z nich, takich jak MONMSG czy DCL jest oczywista ale na liście znajdują się również mniej oczywiste przypadki, takie jak RTVJOBA. Dokumentacja komend języka CL przy każdej z nich określa czy możliwe jest wywołanie tylko za pomocą programu w języku CL i jeśli takiego obostrzenia nie ma, możemy śmiało korzystać z prezentowanych API.