IBM Mainframe Forum Index
 
Log In
 
IBM Mainframe Forum Index Mainframe: Search IBM Mainframe Forum: FAQ Register
 

Natural to C acessing the TWA


IBM Mainframe Forums -> Java & MQSeries
Post new topic   Reply to topic
View previous topic :: View next topic  
Author Message
HenriqueS

New User


Joined: 17 Feb 2007
Posts: 30
Location: Brazil

PostPosted: Wed Aug 15, 2007 3:03 am
Reply with quote

Hello folks,

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...

Thanks in advance.
Back to top
View user's profile Send private message
dick scherrer

Moderator Emeritus


Joined: 23 Nov 2006
Posts: 19244
Location: Inside the Matrix

PostPosted: Wed Aug 15, 2007 3:38 am
Reply with quote

Hello and welcome to the forums,

If you post the COBOL sample code, someone here may be able to clarify it for you.
Back to top
View user's profile Send private message
HenriqueS

New User


Joined: 17 Feb 2007
Posts: 30
Location: Brazil

PostPosted: Fri Aug 17, 2007 12:35 am
Reply with quote

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:

Code:

int main(int argc, char *argv  ){                                 
 /* (int argc, char *argv  ) */                                   
 printf("\nTran id: %s", argv 0 );
 char twadata 255 ;                                               
 memset(twadata, 0, 255);                                         
 int *twa;                                                         
 unsigned char *dados;                                             
 EXEC CICS ADDRESS TWA(twa);                                       
 dados = (char *) *((int *) *twa);                                 
 memset(twadata, '\0', sizeof(twadata));                           
 memcpy(twadata, dados, 255);                                     
 printf("\nTWA = %s, %s, %s", &twadata, *twadata, twadata);   
 printf("\nTWA int = %i, %i, %i", &twadata, *twadata, twadata);
 printf("\nTWA hex = %x, %x, %x", &twadata, *twadata, twadata);
}                                                                 


Below the output:
Code:

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.

Any ideas?
Back to top
View user's profile Send private message
HenriqueS

New User


Joined: 17 Feb 2007
Posts: 30
Location: Brazil

PostPosted: Fri Aug 17, 2007 1:44 am
Reply with quote

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....

Code:

struct mystruct {
 unsigned char lda_label[65];
 unsigned char lda_ex_data[4];
 int lda_tam_exp;                                       
 unsigned char lda_return[128];
};                                       
static struct mystruct *twaarea;
static struct mystruct *cwaarea;

int main(int argc, char *argv  ){                                 
 /* (int argc, char *argv  ) */                                   
 printf("\nTran id: %s", argv 0 ); /* nome da transa  o */       
 char twadata 255 ;                                               
 memset(twadata, 0, 255);                                         
 int *twa;                                                       
 unsigned char *dados;                                           
 EXEC CICS ADDRESS TWA(twa);                                     
 dados = (char *) *((int *) *twa);                               
 memset(twadata, '\0', sizeof(twadata));                         
 memcpy(twadata, dados, 255);                                     
 printf("\nTWA = %s, %s, %s", &twadata, *twadata, twadata);       
 printf("\nTWA int = %i, %i, %i", &twadata, *twadata, twadata);   
 printf("\nTWA hex = %x, %x, %x", &twadata, *twadata, twadata);   
                                                                 
 EXEC CICS ADDRESS TWA(twaarea);
 printf("\nNew TWA = %s", twaarea->lda_label);
 printf("\nNew TWA = %s", twaarea->lda_ex_data);
 printf("\nNew TWA = %i", twaarea->lda_tam_exp);
 printf("\nNew TWA = %s", twaarea->lda_return);

 EXEC CICS ADDRESS COMMAREA(cwaarea);
 printf("\nNew CWA = %s", cwaarea->lda_label);
 printf("\nNew CWA = %s", cwaarea->lda_ex_data);
 printf("\nNew CWA = %i", cwaarea->lda_tam_exp);
 printf("\nNew CWA = %s", cwaarea->lda_return);
}


Output...:

Code:

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 =   
Back to top
View user's profile Send private message
HenriqueS

New User


Joined: 17 Feb 2007
Posts: 30
Location: Brazil

PostPosted: Thu Aug 23, 2007 11:15 pm
Reply with quote

For the good of mankind, my working implementation below, I hope someone one day someone using a search engine for help will reach this...

Acessing the TWA using C:

Code:

struct mystruct{                 
 unsigned char lda_label[65];   
 int lda_tam_exp;               
 unsigned char lda_ex_data[128];
 unsigned char lda_md_data[128];
 unsigned char lda_return 10 ;   
};                               
struct mystruct *twaarea;       

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); */                     
                                                                 
  twaarea=(struct mystruct*)data;                               
  printf("\nTWA lda_label = %s", twaarea->lda_label);             
                                                                 
  printf("\nTWA lda_tam_exp = %02X", twaarea->lda_tam_exp);       
                                                                 
  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);                                                           
 }                                                                     
}
Back to top
View user's profile Send private message
dick scherrer

Moderator Emeritus


Joined: 23 Nov 2006
Posts: 19244
Location: Inside the Matrix

PostPosted: Fri Aug 24, 2007 12:50 am
Reply with quote

Hello,

Thank you for posting your solution.

What sort of output did you get when you executed your code?
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Fri Aug 24, 2007 1:48 am
Reply with quote

HenriqueS,

thx. That is what I call a keeper. Print to PDF, save on my pc.
Back to top
View user's profile Send private message
HenriqueS

New User


Joined: 17 Feb 2007
Posts: 30
Location: Brazil

PostPosted: Fri Aug 24, 2007 2:50 am
Reply with quote

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?
Back to top
View user's profile Send private message
dick scherrer

Moderator Emeritus


Joined: 23 Nov 2006
Posts: 19244
Location: Inside the Matrix

PostPosted: Fri Aug 24, 2007 3:08 am
Reply with quote

Cool - thanks icon_smile.gif

d
Back to top
View user's profile Send private message
View previous topic :: :: View next topic  
Post new topic   Reply to topic View Bookmarks
All times are GMT + 6 Hours
Forum Index -> Java & MQSeries

 


Similar Topics
Topic Forum Replies
No new posts IMS DB using Natural Language IMS DB/DC 0
No new posts Negative value - packed field - Natur... Java & MQSeries 0
No new posts Call Natural program with rexx CLIST & REXX 2
No new posts ACESSING THE FILE NAME FROM ANOTEHR E... All Other Mainframe Topics 2
No new posts Reg:Displaying the particular month o... All Other Mainframe Topics 4
Search our Forums:

Back to Top