Getting a Hello World program compiled is nice, but you probably want to do something more useful with GCCMVS. In this guide I will show examples of how to compile multiple source code files to produce a single executable, passing parameters to C programs, and basic file I/O. I will assume that GCCMVS is already installed and that you know how to compile simple programs.
Currently being rewritten, coming soon!
This example demonstrates how to pass parameters to a C program. Here is the sample C program that will be used.
#include <stdio.h> int main(int argc, char *argv[]) { if(argc == 3) printf("%d\n", atoi(argv[1]) + atoi(argv[2])); return 0; }
For this example, I will assume you have the source code stored in HERC01.TEST.CNTL(ADDER) and you have compiled the program as HERC01.TEST.LOADLIB(ADDER) using the job shown in "Using GCCMVS".
This program takes in two parameters, adds them, and prints the sum. You may be wondering why the first statement checks for three parameters and the reason is that the program name (ADDER) is considered the first parameter.
Running this program will require a modified version of the RUN job shown in "Using GCCMVS".
//HERC01C JOB CLASS=A,MSGCLASS=X,NOTIFY=HERC01 //EXECGO EXEC PGM=ADDER,REGION=5000K,PARM='3 4' //STEPLIB DD DSN=HERC01.TEST.LOADLIB,DISP=SHR //SYSPRINT DD SYSOUT=*,DCB=(LRECL=132,BLKSIZE=132) //SYSABEND DD SYSOUT=* //SYSIN DD DUMMY
The difference with this job is the addition of the PARM keyword in the EXECGO jobstep. You can think of the PARM keyword as being equivalent to the parameters you would type on Unix system. For example, you would call the program with a command like adder 3 4 on Unix. Parameters are space separated. The first parameter in this case would be 3 and the second is 4. You can now submit the job.
You can view the output of the program with the RPF Output processor (option 3.6). At the end of the output you should see something like this:
IEF375I JOB /HERC01C / START 06245.1903
IEF376I JOB /HERC01C / STOP 06245.1903 CPU 0MIN 00.02SEC SRB 0MIN 00.01SEC
7
The 7 is the output we expected (3 + 4 = 7).
I received an e-mail from another GCCMVS user saying that the maximum length of PARM is 100 characters, so it is something to pay attention to when coding JCL.
Updated on October 31st with valuable information from Paul Edwards.
PDPCLIB features the standard I/O functions for reading and writing to files. You can use these in your C programs to access MVS datasets.
#include <stdio.h> int main(int argc, char *argv[]) { if(argc == 2) { FILE *fp; fp = fopen("dd:output", "w"); fprintf(fp, "Writing to a file with GCCMVS.\n"); fclose(fp); } return 0; }
The above program will open the dataset specified by the OUTPUT DD statement in your JCL and replace its contents with "Writing to a file with GCCMVS." so you probably do not want to point it at any of your important datasets. :) It can be compiled the same was as the example program from "Using GCCMVS" and I will assume it's located at HERC01.TEST.LOADLIB(FILEIO).
If you already looked at the "Passing Parameters to a C Program" section, you might be wondering how the program knows the difference between a simple parameter and an MVS dataset. The magic is in the JCL.
//HERC01C JOB CLASS=A,MSGCLASS=X,NOTIFY=HERC01 //EXECGO EXEC PGM=FILEIO,REGION=5000K //STEPLIB DD DSN=HERC01.TEST.LOADLIB,DISP=SHR //SYSPRINT DD SYSOUT=*,DCB=(LRECL=132,BLKSIZE=132) //SYSABEND DD SYSOUT=* //SYSIN DD DUMMY //OUTPUT DD DSN=HERC01.FILEIO.TEST,DISP=(NEW,CATLG), // SPACE=(CYL,(1,1)),DCB=(RECFM=FB,LRECL=80,BLKSIZE=3120), // UNIT=SYSDA
It is important to add DD statements for all datasets that your program reads and writes to. This program will write to the dataset referred to by the OUTPUT DD statement. In this case, the OUTPUT DD statement says to allocate and catalog a new sequential dataset named HERC01.FILEIO.TEST.
After you run the job, HERC01.FILEIO.TEST should now contain:
Writing to a file with GCCMVS.