From: reds@informix.com (Ron Delpiere-Smith) Newsgroups: comp.databases.informix Subject: How to read Flat files from 4gl Date: 18 Apr 1995 02:56:09 GMT Shankar's Emporium Pte Ltd (shanke11@merlion.singnet.com.sg) wrote: : I have a requirment to read the flat file from 4GL. Is there any way to : do it. You would need to use a 'C' routine to read in the file. I have developed a these routines in a nice neat little package over the years. I need to get these places on the archive server at emory.edu. Here is a copy of the c source file, I also have a man page available. The code is pretty well documented. Right now the headers are in a state of transfer from SCCS over to RCS, sorry about that folks. Enjoy, Ron Delpiere-Smith, Informix P.S. Set you tab stops = 4 (:ts=4) in vi for readability. ------------------------------Cut Here---------------------------- /* ############################################################################## # Module : file_io.c # Description : These functions read/write fixed or variable length # records from/to files for 4GL # # Functions : file_init Opens a data files. # file_close Closes a data file. # file_read Reads data from a file. # file_write Writes data to a file. # # Revision : $Revision: 1.2 $ # Author : Ron Delpiere-Smith # Date : %G% %U% # Path : %P% # # Date Author Comments # ======== ====== ===================================================== # 07/10/89 REDS Original Coding. # 09/24/91 REDS Updated standards, revised documentation. # 10/02/91 REDS Defined return codes. # ############################################################################## */ #include #include #include #include #include #define _FIOMAX (8) #define _STAT_OK (0) /* IO status OK. */ #define _STAT_ERR (101) /* Gerneral IO Failure */ #define _STAT_EOF (255) /* Gerneral IO Failure */ #define _INV_PARM (102) /* Invalid number of parameters */ #define _INV_FNAM (103) /* Invalid Filename. */ #define _INV_FMOD (104) /* Invalid File Mode. */ #define _INV_FNUM (105) /* Invalid File Number. */ #define _INV_FTYP (106) /* Invalid File Type. */ #define _INV_BUF (107) /* Invalid Buffer Length. */ #define _NO_FILES (108) /* No files available. */ #define _NO_BUF (109) /* No buffer space available. */ static struct { char fvflag[2]; char rwflag[2]; char *iobuf; short ilen; short inuse; FILE *fp; } _fio[_FIOMAX]; FILE *fopen(); char *clip(); int ident_file_io() { char *g_sccs_var = "%W%"; char *g_rcs_var = "$Header: fgl_fileio.c,v 1.2 95/03/28 13:44:53 rsmith Exp $"; } /* ############################################################################## # # Description : This function will open a unix file in one of 3 modes. # # Usage : CALL file_init ( "foo", 256, "r", "f" ) # RETURNING io_status, file_id # # Logic : Open the file and declare the required bufffer space. # # Passed # Parameters : - Full pathname of data file to open. # - Size of I/O buffer. # - File I/O Mode Indicator (R/W/A). # - Fixed or Variable length record indicator (F/V). # # Returned # Variables : - File I/O Channel Number (smallint). # - File I/O Status (integer). # # Date Author Comments # ======== ====== ===================================================== # 07/10/89 REDS Original Coding. # 09/24/91 REDS Updated standards, revised documentation. # 10/02/91 REDS Added usage of DEFINEd return codes. # ############################################################################## */ int file_init( argcount ) int argcount; { int retcode; short fidx; char flnam[128]; /* * Check argument count */ if ( argcount != 4 ) { retcode = (int) _INV_PARM; } else { retcode = 0; } /* * Set up fio array */ if ( retcode == 0 ) { for ( fidx = 0; fidx < _FIOMAX; ++fidx ) { if ( _fio[fidx].inuse == 0 ) { _fio[fidx].inuse = 1; break; } } if ( fidx >= _FIOMAX ) { retcode = (int) _NO_FILES; } } if ( retcode == 0 ) { /* * Get buffer length & filename */ (void) memset( _fio[fidx].fvflag, (int) '\0', sizeof( _fio[fidx].fvflag ) ); (void) memset( _fio[fidx].rwflag, (int) '\0', sizeof( _fio[fidx].rwflag ) ); (void) memset( flnam, (int) '\0', sizeof( flnam ) ); popquote( _fio[fidx].fvflag, 2 ); /* Fixed/Variable flag */ popquote( _fio[fidx].rwflag, 2 ); /* Read/Write flag */ popshort( &_fio[fidx].ilen ); /* Length of buffer */ popquote( flnam, sizeof( flnam ) -1 ); /* Filename */ } if ( retcode == 0 ) { /* * Validate arguments */ if ( (int) strlen ( clip ( flnam ) ) <= 1 ) { retcode = (int) _INV_FNAM; } } if ( retcode == 0 ) { if ( _fio[fidx].ilen < 1 ) { retcode = (int) _INV_BUF; } } if ( retcode == 0 ) { _fio[fidx].rwflag[0] = (char) tolower( (int) _fio[fidx].rwflag[0] ); if ( _fio[fidx].rwflag[0] != 'r' && _fio[fidx].rwflag[0] != 'w' && _fio[fidx].rwflag[0] != 'a' ) { retcode = (int) _INV_FMOD; } } if ( retcode == 0 ) { _fio[fidx].fvflag[0] = (char) tolower( (int) _fio[fidx].fvflag[0] ); if ( _fio[fidx].fvflag[0] != 'f' && _fio[fidx].fvflag[0] != 'v' ) { retcode = (int) _INV_FTYP; } } if ( retcode == 0 ) { /* * Open the file */ if ( (_fio[fidx].fp = fopen( clip( flnam ), _fio[fidx].rwflag )) == (FILE *) NULL ) { retcode = (int) _STAT_ERR; } else { /* * Allocate space for the I/O buffer */ if ( (_fio[fidx].iobuf = (char *) malloc( (unsigned) (_fio[fidx].ilen+1) )) == (char *) NULL ) { retcode = (int) _NO_BUF; } else { retcode = (int) _STAT_OK; } } } /* * Two values are passed back to 4gl */ retshort( fidx ); retint( retcode ); return( (int) 2 ); } /* ############################################################################## # # Description : This function will allow an Informix-4GL program to # read from a file that was opened for reading using # file_init(). # # Usage : CALL file_read ( file_id ) # RETURNING io_status, string # # Logic : Open the file and declare the required bufffer space. # # Passed # Parameters : - File I/O Channel Number (smallint). # # Returned # Variables : - String of data ( char(buf_siz) ). # - File I/O Status (integer). # # Date Author Comments # ======== ====== ===================================================== # 07/10/89 REDS Original Coding. # 09/24/91 REDS Updated standards, revised documentation. # 10/02/91 REDS Added usage of DEFINEd return codes. # ############################################################################## */ int file_read( argcount ) int argcount; { short idx; int retcode; short fidx; /* * Check argument count */ if ( argcount != 1 ) { retcode = _INV_PARM; } else { retcode = 0; } if ( retcode == 0 ) { /* * Get fio index */ popshort( &fidx ); if ( fidx >= _FIOMAX || fidx < 0 ) { retcode = _INV_FNUM; } } if ( retcode == 0 ) { /* * Initialize the record to Nulls, including null terminator */ (void) memset( _fio[fidx].iobuf, (int) '\0', (_fio[fidx].ilen + 1) ); /* * Check for end-of-file */ if ( feof( _fio[fidx].fp ) ) { retcode = (int) _STAT_EOF; } /* EOF */ else { /* * Read the record as indicated by the flag */ if ( _fio[fidx].fvflag[0] == 'f' ) { /* * Read fixed-length record */ if ( fread( _fio[fidx].iobuf, 1, _fio[fidx].ilen, _fio[fidx].fp ) == 0 ) { retcode = (int) _STAT_ERR; } /* Read fail */ else { retcode = (int) _STAT_OK; } /* Read ok */ } /* Read fix. rec. */ else { /* * Read variable-length record */ if ( fgets( _fio[fidx].iobuf, _fio[fidx].ilen, _fio[fidx].fp ) == (char *) NULL ) { retcode = (int) _STAT_ERR; } else { retcode = (int) _STAT_OK; } } /* Read var. rec. */ } /* Not EOF */ } /* * Two values are passed back to 4gl */ retquote( _fio[fidx].iobuf ); retint( retcode ); return( (int) 2 ); } /* ############################################################################## # # Description : This function will allow an Informix-4GL program to # write to a unix file that was opened in either write # or append modes using file_init() # # Usage : CALL file_write ( buffer, file_id ) # RETURNING io_status # # Logic : Open the file and declare the required bufffer space. # # Passed # Parameters : - Text buffer to write to file (char). # - File I/O Channel Number (smallint). # # Returned # Variables : - File I/O Status (integer). # # Date Author Comments # ======== ====== ===================================================== # 07/10/89 REDS Original Coding. # 09/24/91 REDS Updated standards, revised documentation. # 10/02/91 REDS Added usage of DEFINEd return codes. # ############################################################################## */ int file_write( argcount ) int argcount; { int retcode; short fidx; /* * Check argument count */ if ( argcount != 2 ) { retcode = _INV_PARM; } else { retcode = 0; } if ( retcode == 0 ) { /* * Get fio index */ popshort( &fidx ); if ( fidx >= _FIOMAX || fidx < 0 ) { retcode = _INV_FNUM; } } if ( retcode == 0 ) { /* * Initialize the record to Nulls, including null terminator */ (void) memset( _fio[fidx].iobuf, (int) '\0', (_fio[fidx].ilen + 1) ); /* * Get output text */ popquote( _fio[fidx].iobuf, (_fio[fidx].ilen +1) ); /* * Check for end-of-file */ if ( feof( _fio[fidx].fp ) ) { retcode = (int) _STAT_ERR; } /* EOF */ else { /* * Write the record as indicated by the flag */ if ( _fio[fidx].fvflag[0] == 'f' ) { /* * Write fixed-length record */ if ( fwrite( _fio[fidx].iobuf, 1, _fio[fidx].ilen, _fio[fidx].fp ) != _fio[fidx].ilen ) { retcode = (int) _STAT_ERR; } /* Write fail */ else { (void) fflush( _fio[fidx].fp ); retcode = (int) _STAT_OK; } /* Write ok */ } /* Write fix. rec. */ else { /* * Write variable-length record */ if ( fputs( _fio[fidx].iobuf, _fio[fidx].fp ) == EOF ) { retcode = (int) _STAT_ERR; } /* Write fail */ else { /* * Append a newline */ if ( fputc( '\n', _fio[fidx].fp ) == EOF ) { retcode = (int) _STAT_ERR; } /* Write fail */ else { (void) fflush( _fio[fidx].fp ); retcode = (int) _STAT_OK; } /* Write ok */ } /* Write ok */ } /* Write var. rec. */ } /* Not EOF */ } /* * One value is passed back to 4gl */ retint( retcode ); return( (int) 1 ); } /* ############################################################################## # # Description : This function will close the indicated file. # # Usage : CALL file_close ( file_id ) # RETURNING io_status # # Passed # Parameters : - File I/O Channel Number (smallint). # # Returned # Variables : - File I/O Status (integer). # # Date Author Comments # ======== ====== ===================================================== # 07/10/89 REDS Original Coding. # 09/24/91 REDS Updated standards, revised documentation. # 10/02/91 REDS Added usage of DEFINEd return codes. # ############################################################################## */ int file_close( argcount ) int argcount; { short fidx; int retcode; /* * Check argument count */ if ( argcount != 1 ) { retcode = _INV_PARM; } else { retcode = 0; } if ( retcode == 0 ) { /* * Get fio index */ popshort( &fidx ); if ( fidx >= _FIOMAX || fidx < 0 ) { retcode = _INV_FNUM; } } if ( retcode == 0 ) { /* * Release the memory */ free( _fio[fidx].iobuf ); /* * Flush to output buffer */ if ( _fio[fidx].rwflag[0] == 'w' ) { (void) fflush( _fio[fidx].fp ); } /* * Close the file */ (void) fclose( _fio[fidx].fp ); /* * Release the inuse flag */ _fio[fidx].inuse = 0; } /* * One value is passed back to 4gl */ retint( retcode ); return( (int) 1 ); } /* ############################################################################## # # Function : clip # # Description : This function will "clip" a passed Informix character # array. Informix does not terminate strings with a NULL; # the strings are left justified, space filled. # # Usage : CALL clip ( char_var ) # # Logic : Loop through Informix character array changing spaces # to NULLs. Spaces are defined as x20x20 or x00x20. # # Module # Functions : clip # # Called # Functions : # # Environment # Variables : # # Referenced # Files : stdio.h # ctype.h # # Log File : # # Input Files : # # Output Files: # # Date Author Comments # ======== ====== ===================================================== # 07/10/89 REDS Original Coding. # 09/24/91 REDS Update standards, updated documentation. # ############################################################################## */ #include #include char *clip( pt ) char *pt; { short slen; char *ptmp; slen = strlen( pt ) - 1; if ( slen < 0 ) { return( (char *) NULL ); } ptmp = &pt[slen]; while( ptmp != pt && isspace( (int) *ptmp ) ) { *(ptmp--) = '\0'; } return( pt ); }