Figure 1 is a sample preinitialized
C program that shows how to do the following:
- Establish the C environment using an INIT request
- Pass runtime parameters to the C initialization routine
- Set up a parameter to the C program
- Repeatedly call a C program using the CALL request
- Communicate from the C program to the driving program using a
return code
- End the C program using the TERM request
The parameters it expects are the file name in argv[1] and
the return code in argv[2]. The C program printf()s the
value of the return code, writes a record to the file name, and decrements
the value in return code.
The assembler program that drives the C program establishes the
C environment and repeatedly invokes the C program, initially passing
a value of 5 in the return code. When the return code set by the C
program is zero, the assembler program terminates the C environment
and exits.
Program
CCNGCA6 (Figure 1 ) does not include the
logic that would verify the correctness of any of the invocations. Such
logic is imperative for proper operations.
Figure 1. Preinitializing a C program
(CCNGCA6)CCNGCA6 TITLE 'TESTING PREINITIALIZED C PROGRAMS'
***-------------------------------------------------------------
*** this example shows how to preinitialize a C program
*** part 1 of 3 (other files are CCNGCA7 and CCNGCA8)
*** Function: Demonstrate the use of Preinitialized C programs
*** Requests used: INIT, CALL, TERM
*** Parameters to C program: FILE_NAME, RUN_INDEX
*** Return from C Program: RUN_INDEX
***-------------------------------------------------------------
CCNGCA6 CSECT
CCNGCA6 RMODE ANY
CCNGCA6 AMODE ANY
EXTRN CEESTART C Program Entry
STM R14,R12,12(R13) Save registers
BALR R3,0 Set base register
USING *,R3 Establish addressability
ST R13,SVAR+4 Set back chain
LA R13,SVAR Set this module's save area
***-------------------------------------------------------------
*** Initialize
***-------------------------------------------------------------
P_INIT DS 0H
MVC P_RQ,INIT Set INIT as the request
LA R1,PALIPT Load Parameter pointer
L R15,CEP Load C Entry Point
BALR R14,R15 Invoke C Program
***-------------------------------------------------------------
*** The C environment has been established.
*** Parameters include RUN_INDEX which will be counted down
*** by the C program. When the RUN_INDEX is zero, termination
*** will be requested.
*** The following code will set up C program parameters and
*** CALL request, invoke the C program and test for termination.
***-------------------------------------------------------------
LA R1,PGPAPT Pointer to C program parameters
ST R1,EP_PGPA ... to extended parameter list
DO_CALL DS 0H
MVC P_RQ,CALL set up CALL request
LA R1,PALIPT set parameter pointer
L R15,CEP set entry point
BALR R14,R15 invoke C program
L R0,RUN_INDEX Test Return Code
LTR R0,R0
BNZ DO_CALL Repeat CALL
***-------------------------------------------------------------
*** C requested termination.
*** Set up TERM request and terminate the environment
***-------------------------------------------------------------
DO_TERM DS 0H
MVC P_RQ,TERM set up TERM request
SR R1,R1 mark no parameters
ST R1,EP_PGPA
LA R1,PALIPT set parameter pointer
L R15,CEP set entry point
BALR R14,R15 invoke termination
|
***-------------------------------------------------------------
*** Return to system
***-------------------------------------------------------------
XIT DS 0H
L R13,4(13)
LM R14,R12,12(13)
BR R14
***-------------------------------------------------------------
*** Constants and work areas
***-------------------------------------------------------------
VARCON DS 0D
PALIPT DC A(X'80000000'+PALI) Address of Parameter list
CEP DC A(CEESTART) Entry point address
***-------------------------------------------------------------
PALI DS 0F Parameter list
P_LG DC H'16' Length of the list
DC H'0' Must be zero
P_RQ DC CL8' ' Request - INIT,CALL,TERM,EXECUTE
P_EP_PT DC A(EPALI) Address of extended plist
***-------------------------------------------------------------
EPALI DS 0F Extended Parameter list
DC A(EP_LG) Length of this list
EP_TCA DC A(0) First token
EP_PRV DC A(0) Second token
EP_PGPA DC A(PGPAPT) Address of C program plist
EP_XOPT DC A(XOPTPT) Address of runtime options
EP_LG EQU *-EPALI Length of this list
***-------------------------------------------------------------
*** C program plist in argc, argv format
***-------------------------------------------------------------
PGPAPT DC F'3' Number of parameters (argc)
DC A(PGVTPT) parameter vector pter (argv)
PGVTPT DS 0A Parameter Vector
DC A(PGNM) Program name pointer (argv1)
DC A(FILE_NAME) File name pointer (argv2)
DC A(RUN_INDEX) Run index pointer (argv3)
DC XL4'00000000' NULL pointer
***-------------------------------------------------------------
*** Runtime options
***-------------------------------------------------------------
XOPTPT DC A(X'80000000'+XOPTLG) Runtime options pter
XOPTLG DC AL2(XOPTSQ) Runtime option list length
XOPTS DC C'STACK(4K) RPTSTG(ON)' Runtime options list
XOPTSQ EQU *-XOPTS Runtime options length
***-------------------------------------------------------------
PGNM DC C'CCNGCA7',X'00' C program name
FILE_NAME DC C'PREINIT.DATA',X'00' File name for C program
RUN_INDEX DC F'5',X'00' changed by C Program
***-------------------------------------------------------------
*** Request strings for preinitialization
***-------------------------------------------------------------
INIT DC CL8'INIT'
CALL DC CL8'CALL'
TERM DC CL8'TERM'
EXEC DC CL8'EXECUTE'
***-------------------------------------------------------------
*** Assembler program's register save area
***-------------------------------------------------------------
SVAR DC 18F'0'
LTORG
|
***-------------------------------------------------------------
*** Register definitions
***-------------------------------------------------------------
R0 EQU 0
R1 EQU 1
R2 EQU 2
R3 EQU 3
R4 EQU 4
R5 EQU 5
R6 EQU 6
R7 EQU 7
R8 EQU 8
R9 EQU 9
R10 EQU 10
R11 EQU 11
R12 EQU 12
R13 EQU 13
R14 EQU 14
R15 EQU 15
END
|
Program
CCNGCA7 (Figure 2) shows how to use
the preinitializable program.
Figure 2. Using the preinitializable
program (CCNGCA7)/* this example shows how to use a preinitializable program */
/* part 2 of 3 (other files are CCNGCA6 and CCNGCA8) */
#pragma runopts(PLIST(MVS))
#include <stdio.h>
#include <stdlib.h>
#define MAX_MSG 50
#define MAX_FNAME 8
typedef int (*f_ptr)(int, char*);/* pointer to function returning int*/
int main(int argc, char **argv)
{
FILE *fp; /* File to be written to */
int *ptr_run; /* Pointer to the "run index" */
char *ffmsg; /* a pointer to the "fetched function msg"*/
char fname[MAX_FNAME+1]; /* name of the function to be fetched */
int fetch_rc; /* Return value of function invocation */
f_ptr fetch_ptr; /* Function pointer to fetched function */
/* Get the pointer to the "run index" */
ptr_run = (int *)argv[2];
if ((fp = fopen(argv[1],"a")) == NULL)
{
printf("Cannot open file %s\n",argv[1]);
*ptr_run = 0; /* Set to zero so it won't be called again */
return(0); /* Return to Assembler program */
}
|
/* Write the record to the file */
fprintf(fp,"Run index was %d.\n",*ptr_run);
/* Allocate the message returned from the fetched function */
if (( ffmsg=(char *)malloc(MAX_MSG + 1)) == NULL )
printf("ERROR -- malloc returned NULL\n");
/* fetch the function */
fetch_ptr = (f_ptr) fetch("MYFUNC");
if (fetch_ptr == NULL)
printf("ERROR - Fetch returned a null pointer\n");
/* execute the function */
fetch_rc = fetch_ptr(*ptr_run, ffmsg); /* Write the function msg to file */
fprintf(fp,"%s\n",ffmsg);
/* Tell the user the value of the "run index" */
printf("Run index was %d.\n",*ptr_run);
/* Decrement the "run index" */
(*ptr_run)--;
/* Remember to close all opened files */
fclose(fp);
/* Remember to free all allocated storage */
free( fname );
/* Remember to release all fetched modules */
release((void(*)())fetch_ptr);
/* Return to Assembler program */
return(0);
}
|
Finally, Figure 3 shows sample
program CCNGCA8.
Figure 3. Using
the preinitializable program (CCNGCA8)/* this example shows how to use a preinitializable program */
/* part 3 of 3 (other files are CCNGCA6 & CCNGCA7) */
#include <string.h>
#pragma linkage(fetched, fetchable)
int fetched(int run_index, char *ffmsg) {
sprintf(ffmsg,"Welcome to myfunc: Run index was %d.",run_index);
return(0);
}