This chapter covers the low-level I/O functions as well as three utility functions that can be used with the I/O functions. Note that these functions are not portable.
The CMS low-level I/O functions are:
cmsstate
cmsopen
cmsread
cmswrite
cmspoint
cmsclose
cmserase
cmsxflst
cmsxflrd
cmsxflwr
cmsxflpt
cmspid
cmsdfind
cmsdnext
#include <cmsio.h> int cmsstate(struct CMSFSCB *fscbp, struct CMSFST *fstp); int cmsopen(struct CMSFSCB *fscbp); int cmsread(struct CMSFSCB *fscbp); int cmswrite(struct CMSFSCB *fscbp); int cmspoint(struct CMSFSCB *fscbp); int cmsclose(struct CMSFSCB *fscbp); int cmserase(struct CMSFSCB *fscbp);
cmsstate
function states or verifies the existence of a CMS
disk file. The first argument to cmsstate
is a pointer to a
CMS File System Control Block (CMSFSCB
) structure, and the second is a
pointer to a CMS File Status Table (CMSFST
) structure.
The remaining functions are as follows:
cmsopen
cmsread
cmswrite
cmspoint
cmsclose
cmserase
<cmsio.h>
defines two structures for the CMS and
XEDIT low-level I/O functions. The first structure maps a CMS FSCB
and is defined as follows. (Note that extended FSCBs (FORM=E) are
included.)
struct CMSFSCB { /* CMSFSCB definition */ char comm[8]; /* file system command */ char fn[8]; /* filename */ char ft[8]; /* filetype */ char fm[2]; /* filemode */ short itno; /* relative record number */ char *buff; /* address of r/w buffer */ int size; /* length of buffer */ char fv; /* recfm - C'F' or C'V' */ char flg; /* flag byte */ short noit; /* number of records */ int nord; /* number of bytes actually read */ int aitn; /* extended record number */ int anit; /* extended number of records */ int wptr; /* extended write pointer */ int rptr; /* extended read pointer */ };The second structure maps a CMS FST and is defined as follows. (Again, note that the FORM=E fields are included.)
struct CMSFST { char fname[8]; /* filename */ char ftype[8]; /* filetype */ short datew; /* date last written - MMDD */ short timew; /* time last written - HHMM */ short wrpnt; /* write pointer - item number */ short rdpnt; /* read pointer - item number */ char fmode[2]; /* filemode - letter and number */ short recct; /* number of logical records */ short fclpt; /* first chain link pointer */ char recfm; /* record format - F or V */ char flags; /* fST flag byte (read/write) */ int lrecl; /* logical record length */ short blkcnt; /* number of 800 byte blocks */ short yearw; /* year last written */ int fop; /* alternate file origin pointer */ int adbc; /* alt number of data blocks */ int aic; /* alternate item count */ char nlvl; /* number of ptr block levels */ char ptrsz; /* length of a pointer element */ char adati[6]; /* alt date/time (YYMMDDHHMMSS) */ int _; };
cmsstate
copies the
information from the CMS FST to the CMSFST
structure pointed to by
fstp
.
Function CMS Macro ------------------- cmsstate FSSTATE cmsopen FSOPEN cmsread FSREAD cmswrite FSWRITE cmsclose FSCLOSE cmspoint FSPOINT cmserase FSERASERefer to the appropriate IBM documentation for information about the data associated with the FSCB and FST and for information about these CMS macros.
stdout
.
#include <cmsio.h> #include <stdlib.h> #include <stdio.h> #include <string.h> main(int argc, char **argv) { struct CMSFSCB fscb; struct CMSFST fst; register int rc; register char *buffer; /* Perform error checking as necessary. */ if (argc < 2) { puts("Missing fileid"); exit(4); } if (argc > 2) { puts("Extraneous parameters"); exit(4); } /* Call cmspid to tokenize the fileid. */ memset((void *) &fscb,'\0',sizeof(fscb)); rc = cmspid(argv[1],&fscb); if (rc != 0) { printf("Fileid \"%s\" is invalid",argv[1]); exit(4); } /* Call cmsstate to get the file characteristics. */ rc = cmsstate(&fscb,&fst); if (rc != 0) { if (rc == 28) printf("File \"%s\" not found.\n",argv[1]); else printf("Error occurred while issuing FSSTATE. RC=%d\n",rc); exit(rc); } buffer = malloc(fst.lrecl + 1); if (!buffer) exit(8); /* Fill in the required FSCB fields. */ fscb.buff = buffer; fscb.size = fst.lrecl; fscb.fv = fst.recfm; fscb.anit = 1; /* Set current record number to number of records in file. */ fscb.aitn = fst.aic;/* Read the file backward; type records to the terminal. */ while ((rc = cmsread(&fscb)) == 0 && fscb.aitn > 0) { buffer[fscb.nord]= '\0'; puts(buffer); --fscb.aitn; /* Decrement the current record number. */ } /* Check for error while reading. */ if (rc > 0) { printf("Error occurred while reading \"%s\". RC=%d\n", argv[1],rc); exit(rc); } exit(0); }
#include <cmsio.h> int cmsxflst(struct CMSFSCB *fscbp, struct CMSFST *fstp); int cmsxflrd(struct CMSFSCB *fscbp); int cmsxflwr(struct CMSFSCB *fscbp); int cmsxflpt(struct CMSFSCB *fscbp);
cmsxflst
function states or verifies the existence of an XEDIT
file. The first argument to cmsxflst
is a pointer to a CMSFSCB
structure, and the second argument is a pointer to a CMSFST
structure.
The remaining functions are as follows:
cmsxflrd
cmsxflwr
cmsxflpt
CMSFSCB
structure is the only argument for these
functions.
Refer to the "CMS Low-Level I/O Functions" for a description of these structures.
cmsstate
copies the information from the CMS FST to the CMSFST
structure
pointed to by fstp
.
Function XEDIT Subcommand -------------------------- cmsxflst DMSXFLST cmsxflrd DMSXFLRD cmsxflwr DMSXFLWR cmsxflpt DMSXFLPTRefer to the appropriate IBM documentation for information about the data associated with the FSCB and FST and for information about these XEDIT subcommands.
<cmsio.h>
and are listed as
follows:
#define xedstate(fscb,fst) cmsxflst(fscb,fst) #define xedread(fscb) cmsxflrd(fscb) #define xedwrite(fscb) cmsxflwr(fscb) #define xedpoint(fscb) cmsxflpt(fscb)
cmsxflwr
to write
a date and time string at the current line of a file in XEDIT. The
example shows how a program can communicate with XEDIT via the
system
function (using the "XEDIT prefix) and the
cmsxflst
function.
Note that XEDIT and either EXEC2 or REXX must be active when this function is executed. This sort of interaction between XEDIT and a program via an EXEC processor is most appropriate in a program using the SUBCOM interface or a program that is a REXX function package.
The example invokes the EXTRACT subcommand to place the filename,
filetype, and filemode of the file into EXEC2 or REXX variables.
Then, it calls execfetch
to fetch the values of these variables
and put them into a CMSFSCB structure. Next, it uses the time
and ctime
functions to create a date and time string. Finally,
cmsxflwr
writes the string into the file at the current line.
The example assumes that the file has fixed format records and a
logical record length of 80. In practice, this information can be
obtained with a call to cmsstat
, cmsxflst
, or via the
EXTRACT subcommand.
For clarity, all error checking after the initial call to system
has been omitted.
For more information on the time
, ctime
, or system
functions, refer to Chapter 6, "Function Descriptions," in SAS/C Library Reference, Third Edition, Volume 1,& Release 6.00 .
For more information on the cmsshv
function, refer to
The CMS REXX SAS/C® Interface in this book.
#include <cmsio.h> #include <lclib.h> #include <cmsexec.h> #include <lcstring.h> #include <time.h> main() { time_t now; struct CMSFSCB fscb; char timestring[80]; int s, rc; rc = system("xedit: extract /fname/ftype/fmode"); if (rc != 0) { printf("Unable to determine current fileid. "); switch (rc) { case SYS_TNAC: puts("XEDIT is not active."); break; case SYS_CUNK: puts("Not called from EXEC2 or REXX exec."); break; default: if (rc > 0) printf("EXTRACT subcommand returned %d\n", rc); else printf("System function returned %d\n", rc); break; } } exit(rc); } /* Set all fields in CMSFSCB structure to zeros. */ /* Fetch fileid components. */ memset((void *) &fscb,'\0',sizeof(fscb)); cmsshv(SHV_FETCH_DIRECT,"FNAME.1",7,fscb.fn,8,&s); cmsshv(SHV_FETCH_DIRECT,"FTYPE.1",7,fscb.ft,8,&s); cmsshv(SHV_FETCH_DIRECT,"FMODE.1",7,fscb.fm,2,&s); fscb.fv = 'F'; /* RECFM F */ fscb.size = 80; /* LRECL 80 */ fscb.buff = timestring; /* record buffer address */ fscb.aitn = 0; /* A zero indicates the current line. */ /* Initialize record buffer. Get the date and time */ /* and copy to the record. Call cmsxflwr to write */ /* the record. */ memset(timestring,' ',80); now = time(NULL); memcpy(timestring,ctime(&now),24); cmsxflwr(&fscb); exit(0); }
cmspid
, cmsdfind
, and cmsdnext
functions are often used in connection with CMS
low-level I/O tasks. cmspid
separates a CMS or XEDIT style
filename string into filename, filetype, and filemode. cmsdfind
and cmsdnext
can be used to search for a specific CMS file.
A description of cmspid
follows.
(See SAS/C Library Reference, Third Edition, Volume 1
for descriptions of cmsdfind
and comsdnext
.)
#include <cmsio.h> int cmspid(const char *name, struct CMSFSCB *fscbp);
cmspid
tokenizes the string pointed to by name
and fills
in
the filename, filetype, and filemode in the CMSFSCB structure pointed
to by fscbp
. The string pointed to by name
may be any
filename in the cms
or xed
style.
cmspid
returns 0 if tokenizing is successful and fills in the
appropriate fields in the CMSFSCB structure. If name
cannot
be tokenized or does not refer to a CMS or XEDIT file, -1 is
returned.
cmspid
does not imply that the file
exists.
#include <cmsio.h> struct CMSFSCB fscb; rc = cmspid("cms:profile.exec.a",&fscb); . . .