We have a Natural program that is supposed to call a C program. In the very beginning I struggled because the Natural manuals gave a sample that does not take CICS into consideration.
Then I got to know about the CICS storage areas and how does CICS behaves when switching from one program to another under the same task. It just wipes the command line arguments sent from the caller and puts to the TWA (the choice on which area is based on some Natural setting). Then calls the target program supplying just a transaction id.
Still, I got some Cobol examples of retrieving the calling parameters from the TWA and also returning from it. But I do not grasp Cobol well.
So, I ask if anyone does have any C sample of acessing the TWA area or at least some documentation that shows its structure. The "CICS Programming Reference" nor the "CICS Programming Guide" detail it.
*I got a very simple C sample of getting a pointer to the TWA, but in that sample, the programmer had to parse the whole area and break the data every n bytes to get what he wanted. The Cobol sample seemed more elegant but I did not get the point on it...
Below is the Cobol example of a program that retrieves data from the TWA. These data, according to the docs, is pushed automatically when the caller program invokes (along with the parameters) this one.
Quote:
IDENTIFICATION DIVISION.
PROGRAM-ID. TABSUB.
REMARKS. THIS PROGRAM PERFORMS A TABLE LOOK-UP AND
RETURNS A TEXT MESSAGE.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 MSG-TABLE.
03 FILLER PIC X(15) VALUE 'MESSAGE1 '.
03 FILLER PIC X(15) VALUE 'MESSAGE2 '.
03 FILLER PIC X(15) VALUE 'MESSAGE3 '.
03 FILLER PIC X(15) VALUE 'MESSAGE4 '.
03 FILLER PIC X(15) VALUE 'MESSAGE5 '.
03 FILLER PIC X(15) VALUE 'MESSAGE6 '.
03 FILLER PIC X(15) VALUE 'MESSAGE7 '.
01 TAB REDEFINES MSG-TABLE.
03 MESSAGE OCCURS 7 TIMES PIC X(15).
LINKAGE SECTION.
01 TWA-DATA.
03 PARM-POINTER USAGE IS POINTER.
01 PARM-LIST.
03 DATA-LOC-IN USAGE IS POINTER.
03 DATA-LOC-OUT USAGE IS POINTER.
01 INPUT-DATA.
03 INPUT-NUMBER PIC 99.
01 OUTPUT-DATA.
03 OUTPUT-MESSAGE PIC X(15).
PROCEDURE DIVISION.
100-INIT.
EXEC CICS ADDRESS TWA(ADDRESS OF TWA-DATA) END-EXEC.
SET ADDRESS OF PARM-LIST TO PARM-POINTER.
SET ADDRESS OF INPUT-DATA TO DATA-LOCIN.
SET ADDRESS OF OUTPUT-DATA TO DATA-LOC-OUT.
200-PROCESS.
MOVE MESSAGE (INPUT-NUMBER) TO OUTPUT-MESSAGE.
300-RETURN.
EXEC CICS RETURN END-EXEC.
400-DUMMY.
GO-BACK.
I found a C sample here, tried to run it, but I recovered some unrecognizable data:
TCP2 20070816155903 Tran id: TCP2
TCP2 20070816155903 TWA = & , , &
TCP2 20070816155903 TWA int = 428015264, 80, 28015264
TCP2 20070816155903 TWA hex = 1982fea0, 50, 1982fea0
I really expected to get a bigger sample, since the parameters passes to the called app have more than 128 bytes...
Also, I talked to some people and they said me is very hard to browse the TWA contents during the task, because it is short lived (lasts for the task duration) and is not logged, since it generates too much data in a production environment.
I´ve made a new try, to check if anything was in the commarea. I did this sort of struct-based map according to a sample I found on the net...no success....
TCP2 20070816170850 Tran id: TCP2
TCP2 20070816170850 TWA = & , , &
TCP2 20070816170850 TWA int = 428015264, 80, 428015264
TCP2 20070816170850 TWA hex = 1982fea0, 50, 1982fea0
TCP2 20070816170850 New TWA = t
TCP2 20070816170850 New TWA =
TCP2 20070816170850 New TWA = 0
TCP2 20070816170850 New TWA =
TCP2 20070816170850 New CWA = t
TCP2 20070816170850 New CWA =
TCP2 20070816170850 New CWA = 0
TCP2 20070816170850 New CWA =
int main(int argc, char *argv ){
/* argc and argv are overwritten by CICS, Natural or CICS (not sure) will
store the CALL parameters (made in the Natural program) in an area calles TWA.
Argc under CICS returns '1' and argv[0] returns the transaction id */
printf("\nTransaction id: %s", argv 0 );
int *twa;
unsigned char *data;
EXEC CICS ADDRESS TWA(twa);
data = (unsigned char *) *((int *) *twa); /* weird casting copied from a friend */
/* EIB is a memory area that contains status information about the context in
which the transaction is running. The example below shows getting the current
transaction id. Notice that if the pointer variable to this area was not created
before, the CICS translator solves this, freeing the programmer.
EXEC CICS ADDRESS EIB(dfheiptr);
printf("\nT id %s", dfheiptr->eibtrnid); */
printf("\nTWA lda_ex_data =");
for(int i=0;i<128;i++){
printf("%02X", twaarea->lda_ex_data[i]);
}
printf("\nTWA lda_md_data =");
for(int i=0;i<128;i++){
printf("%02X", twaarea->lda_md_data[i]);
}
/* Shows TWA contents, used for interprocess communication between a caller
Natural module and a called C module. It has the size of 1024 bytes, defined
on CICS for each transaction (custom up to 32kbytes). */
printf("\nFull hex dump =\n");
for(int i=0;i<1024;i++){
if((i+1)%40==0) printf("\n"); /* break line */
printf("%02X", *(data+i));
}
/* Send return back to the Natural module */
strcpy(twaarea->lda_return, "RETURN");
EXEC CICS RETURN;
return(0);
}
}
I got the C field structures filled exactly as the Natural ones sent as parameter with the CALL statement. In the last two fields, since they are plain bytes, I get the hex dump of them.
In Natural: CALL MYCMODULE LOCALSTRT
where LOCALSTRT is called a "local" under natural, it is basically a struct that is defined somewhere...(the previous lines fill them).
There must be an exact data-type relation between the Natural and C types (order, data type and size).
There also may arise some data-alignment issues (when fitting the data into the C struct, the runtime may get lost trying to fit the data and do some shift left or shift left fitting. To deal with this, in the Natural "local" structure you may need to put a padding field between the ones with problem. I did this in my case, since the first field is a char[65] which is not divisible by 4 (4 is the minimum byte displacement in the z/OS C compiler according to the redbook).
The last printf shows the entire TWA as an hex dump just to check if Natural/CICS sent the "local" structure correctly to the TWA.
dick scherrer wrote:
Hello,
Thank you for posting your solution.
What sort of output did you get when you executed your code?