Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
frch.c
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001, Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2.1 of the GNU Lesser General Public License 
00007   as published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU Lesser General Public 
00021   License along with this program; if not, write the Free Software 
00022   Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, 
00023   USA.
00024 
00025   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00026   Mountain View, CA 94043, or:
00027 
00028   http://www.sgi.com
00029 
00030   For further information regarding this notice, see:
00031 
00032   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00033 
00034 */
00035 
00036 
00037 
00038 #pragma ident "@(#) libf/fio/frch.c     92.2    06/22/99 11:11:33"
00039 
00040 #include <errno.h>
00041 #include <liberrno.h>
00042 #if     defined(_SOLARIS) || (defined(_LITTLE_ENDIAN) && !defined(__sv2))
00043 #include <stdio.h>
00044 #endif
00045 #include <stdlib.h>
00046 #include <string.h>
00047 #include "fio.h"
00048 #ifdef  _ABSOFT
00049 #include "ac_sysdep.h"
00050 #else           /* NOT _ABSOFT */
00051 
00052 #if     defined(_LITTLE_ENDIAN) && !defined(__sv2)
00053 #ifndef FILE_CNT
00054 #define FILE_CNT(__f)   (__f)->_IO_write_end - (__f)->_IO_write_ptr
00055 #endif
00056 
00057 #ifndef FILE_PTR
00058 #define FILE_PTR(__f)   (__f)->_IO_write_ptr
00059 #endif
00060 
00061 #ifndef FILE_FLAG
00062 #define FILE_FLAG(__f)  (__f)->_flags
00063 #endif
00064 
00065 #ifndef IOWRT
00066 #define IOWRT = _IO_CURRENTLY_PUTTING
00067 #endif
00068 #ifndef IOREAD
00069 #define IOREAD = _IO_CURRENTLY_APPENDING
00070 #endif
00071 #ifndef IORW
00072 #define IORW = _IO_TIED_PUTGET
00073 #endif
00074 
00075 #else           /* LITTLE_ENDIAN and not sv2 */
00076 #ifndef FILE_CNT
00077 #define FILE_CNT(__f)   (__f)->_cnt
00078 #endif
00079 
00080 #ifndef FILE_PTR
00081 #define FILE_PTR(__f)   (__f)->_ptr
00082 #endif
00083 
00084 #ifndef FILE_FLAG
00085 #define FILE_FLAG(__f)  (__f)->_flag
00086 #endif
00087 
00088 #endif          /* LITTLE_ENDIAN and not sv2 */
00089 
00090 #endif          /* _ABSOFT */
00091 
00092 #ifdef  _SOLARIS
00093 #undef getc
00094 #ifndef MIN
00095 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
00096 #endif
00097 #endif          /* end _SOLARIS */
00098 #ifdef  _CRAY
00099 extern int G@INTIO;
00100 #define _GINTIO G@INTIO
00101 #else
00102 extern int _intio;
00103 #define _GINTIO _intio
00104 #endif
00105 /*
00106  *      _frch
00107  *              Read and unpack characters from the current record of a file.
00108  *
00109  *      Arguments
00110  *              cup:    unit pointer
00111  *              uda:    character pointer to user's data area
00112  *              chars:  Number of characters to read
00113  *              mode:   Full or partial mode flag
00114  *              status: Address of caller's status word.
00115  *
00116  *      Side effects
00117  *
00118  *              Sets *status as follows:
00119  *
00120  *                      CNT - if the requested number of items were read, and
00121  *                              more data remains in the current record (if
00122  *                              the file has records).
00123  *                      EOR - if all remaining data in the current record was 
00124  *                              read by this request. 
00125  *                      EOF - if a physical endfile record was read and no data 
00126  *                              preceded the endfile record.
00127  *                      EOD - if the end-of-data mark was reached and no data 
00128  *                              preceded the the end-of-data.
00129  *
00130  *      Return value
00131  *              The number of characters read from the current record.  The
00132  *              record delimitting character (for example a newline) is not 
00133  *              counted.  An error results in a -1 return value with errno set 
00134  *              to the error code.
00135  *
00136  *      Note
00137  *
00138  *              If a nonzero amount of data was read and an EOF mark or the 
00139  *              end of file (EOD) was encountered before reading the full amount
00140  *              of data requested and before encountering EOR, beware that
00141  *              CNT status is returned.
00142  */
00143 
00144 long
00145 _frch(
00146         unit    *cup,
00147         long    *uda,
00148         long    chars,
00149         int     mode,
00150         long    *status)
00151 {
00152         register int    bytsiz;
00153         register int    chr;
00154         register long   nchr;
00155         register long   ncnt;
00156         unsigned char   tbuf[TBUFSZB], *tp;     /* Line buffer */
00157         FILE            *fptr;
00158         struct ffsw     stat;
00159         struct fdinfo   *fio;
00160 #if     defined(_SOLARIS) || (defined(_LITTLE_ENDIAN) && !defined(__sv2))
00161         register long   count;
00162         char            *tpinterim;
00163 #endif
00164  
00165         switch (cup->ufs) {
00166 
00167         case FS_TEXT:
00168         case STD:
00169                 fptr    = cup->ufp.std;
00170 /*
00171  *              Switch the FILE structure into read mode
00172  */
00173 #if     !defined(_LITTLE_ENDIAN) || (defined(_LITTLE_ENDIAN) && defined(__sv2))
00174                 if ((FILE_FLAG(fptr) & (_IOREAD | _IORW)) == _IORW) {
00175 
00176                         if (FILE_FLAG(fptr) & _IOWRT)
00177                                 (void) fseek(fptr, 0, SEEK_CUR);
00178 
00179                         FILE_FLAG(fptr) |= _IOREAD;
00180                 }
00181 #endif
00182 /*
00183  *              Loop on getc until the character count has been 
00184  *              exhausted, an end of file is encountered, or end
00185  *              of record.
00186  */
00187                 nchr    = 0;
00188 #if     defined(_SOLARIS) || (defined(_LITTLE_ENDIAN) && !defined(__sv2))
00189                 while (nchr < chars) {
00190 fill:
00191                         errno   = 0;
00192                         count   = chars - nchr;
00193                         tp      = tbuf;
00194                         count   = MIN(TBUFSZB, (count + 1));
00195                         tpinterim       = fgets((char *)tp, count, fptr);
00196                         if (tpinterim == NULL) {
00197                         /*
00198                          * Search for the newline char in the buffer, but
00199                          * search only the number of characters left in
00200                          * the request, plus one in case it is the
00201                          * newline (if it is in the buffer).  If we find
00202                          * newline, we're done.
00203                          */
00204                         /* EOF here means incomplete record. */
00205                                 if (ferror(fptr)) {
00206                                         if ( errno == EINTR  && _GINTIO == 0) {
00207                                                 clearerr(fptr);
00208                                                 goto fill;
00209                                         }
00210                                         if (errno == 0)
00211                                                 errno   = FESTIOER;
00212                                         return(IOERR);
00213                                 }
00214                                 /*
00215                                  * If nchr > zero, file has no newline.
00216                                  * Make sure we handle it properly.
00217                                  */
00218                                 if (feof(fptr)) {
00219                                         if (nchr == 0) {
00220                                                 *status = EOD;
00221                                                 return(0);
00222                                         }
00223                                         *status = CNT;
00224                                         return(nchr);
00225                                 }
00226                         } else {
00227                                 unsigned char   *tmpptr;
00228                                 ncnt    = count - 1;
00229                                 tmpptr  = memchr(tp, '\n', ncnt);
00230                                 if (tmpptr != NULL) {   /* eor */
00231                                         *status = EOR;
00232                                         ncnt    = tmpptr - tp;
00233                                         nchr    += ncnt;
00234                                         _unpack(tp, uda, ncnt, -1);
00235                                         /* Return number of chars read */
00236                                         return(nchr);
00237                                 }
00238                                 _unpack(tp, uda, ncnt, -1);
00239                                 nchr            += ncnt;
00240                                 uda             += ncnt;
00241 
00242                                 /* go refill the buffer */
00243                         }
00244                 }
00245 #else
00246                 while (nchr < chars) {
00247                         if (FILE_CNT(fptr) <= 0) {
00248 fill:
00249                                 errno   = 0;
00250                                 chr     = _filbuf(fptr);
00251 
00252                                 /* EOF here means incomplete record. */
00253 
00254                                 if (chr == EOF) {
00255 
00256                                         if (ferror(fptr)) {
00257 
00258                                                 if ( errno == EINTR &&
00259                                                  _GINTIO == 0 ) {
00260                                                         clearerr(fptr);
00261                                                         goto fill;
00262                                                 }
00263 
00264                                                 if (errno == 0)
00265                                                         errno   = FESTIOER;
00266 
00267                                                 return(IOERR);
00268                                         }
00269 /*
00270  *                                      If nchr > zero, file has no newline.
00271  *                                      Make sure we handle it properly.
00272  */
00273                                         if (nchr == 0) {
00274                                                 *status = EOD;
00275                                                 return(0);
00276                                         }
00277 
00278                                         *status = CNT;
00279                                         return(nchr);
00280                                 }
00281 /*
00282  *                              Put character returned by filbuf() back
00283  */
00284                                 FILE_CNT(fptr)++;
00285                                 FILE_PTR(fptr)--;
00286                         }
00287 /*
00288  *                      Search for a newline char in the buffer, but search
00289  *                      only the number of characters left in the request,
00290  *                      plus one in case it is the newline (if it is in
00291  *                      the buffer).  If we find the newline, we're done.
00292  */
00293                         if ((chars - nchr) < FILE_CNT(fptr)) {
00294                                 ncnt    = chars - nchr;
00295                                 tp      = memchr(FILE_PTR(fptr), '\n', ncnt + 1);
00296                         }
00297                         else {
00298                                 ncnt    = FILE_CNT(fptr);       /* assume no EOR yet */
00299                                 tp      = memchr(FILE_PTR(fptr), '\n', ncnt);
00300                         }
00301 
00302                         if (tp != NULL) {       /* Found end of record */
00303 
00304                                 *status = EOR;
00305                                 ncnt    = tp - FILE_PTR(fptr);
00306                                 nchr    += ncnt;
00307 
00308                                 _unpack((char *)FILE_PTR(fptr), uda, ncnt, -1);
00309 
00310                                 FILE_CNT(fptr)  -= ncnt + 1;
00311                                 FILE_PTR(fptr)  += ncnt + 1;
00312 
00313                                 return(nchr);   /* Return number of characters read */
00314                         }
00315 
00316                         _unpack((char *)FILE_PTR(fptr), uda, ncnt, -1);
00317 
00318                         FILE_CNT(fptr)  -= ncnt;
00319                         FILE_PTR(fptr)  += ncnt;
00320                         nchr            += ncnt;
00321                         uda             += ncnt;
00322 
00323                         /* go refill the buffer */
00324                 }
00325 #endif
00326 /*
00327  *              Get the next character to see if at end of record.
00328  *              Set the user's status word accordingly.
00329  */
00330                 chr     = getc(fptr);
00331 
00332                 *status = CNT;
00333 
00334                 if (chr == '\n' ) {
00335                         *status = EOR;
00336                         return(nchr);   /* Return number of characters read */
00337                 }
00338 /*
00339  *              We are not at end of record.  Thus if reading in full
00340  *              record mode skip until EOR is found.  If reading in 
00341  *              partial record mode, unget the last character read.
00342  */
00343                 if (mode == FULL)
00344 #if     defined(_SOLARIS) || (defined(_LITTLE_ENDIAN) && !defined(__sv2))
00345                 {
00346 fill2:
00347                         count   = TBUFSZB;
00348                         tp      = tbuf;
00349                         tpinterim = fgets((char *)tp, count, fptr);
00350                         if (tpinterim == NULL) {
00351                                 /* EOF means incomplete record. */
00352                                 if (ferror(fptr)) {
00353                                         if ( errno == EINTR && _GINTIO == 0 ) {
00354                                                 clearerr(fptr);
00355                                                 goto fill2;
00356                                         }
00357                                 }
00358                                 /* Return number of chars read. */
00359                                 return(nchr);
00360                         } else {
00361                                 unsigned char   *tmpptr;
00362                                 ncnt    = count - 1;
00363                                 tmpptr  = memchr(tp, '\n', ncnt);
00364                                 if (tmpptr != NULL) {   /* Found eor */
00365                                         /* Return number of chars read */
00366                                         return(nchr);
00367                                 } else
00368                                         goto fill2;
00369                         }
00370                 }
00371 #else
00372                         while (1) {
00373                                 if (FILE_CNT(fptr) <= 0) {
00374 fill2:
00375                                         chr     = _filbuf(fptr);
00376 
00377                                         /* EOF here means incomplete record. */
00378 
00379                                         if (chr == EOF) {
00380 
00381                                                 if (ferror(fptr)) {
00382 
00383                                                         if ( errno == EINTR &&
00384                                                          _GINTIO == 0 ) {
00385                                                                 clearerr(fptr);
00386                                                                 goto fill2;
00387                                                         }
00388 
00389                                                 }
00390 
00391                                                 /* Return number of characters read */
00392 
00393                                                 return(nchr);
00394                                         }
00395 
00396                                         FILE_CNT(fptr)++;
00397                                         FILE_PTR(fptr)--;
00398                                 }
00399 
00400                                 tp      = memchr(FILE_PTR(fptr), '\n', FILE_CNT(fptr));
00401 
00402                                 if (tp != NULL) {
00403 
00404                                         tp++;
00405                                         FILE_CNT(fptr)  -= tp - FILE_PTR(fptr);
00406                                         FILE_PTR(fptr)  = tp;
00407 
00408                                         return(nchr);
00409                                 }
00410                                 else
00411                                         FILE_CNT(fptr)  = 0;
00412                         }
00413 #endif
00414                 else {
00415                         ungetc ((char) chr, fptr);
00416                 }
00417 
00418                 return(nchr);   /* return number of character read */
00419 
00420         case FS_FDC:
00421                 nchr    = 0;
00422                 fio     = cup->ufp.fdc;
00423 /*
00424  *              If no conversion is to be done, or no characters requested
00425  *              (usually for null request, FULL mode), make it simple and direct.
00426  */
00427                 if (cup->ucharset == 0 || chars == 0) {
00428                         register long   breq;
00429                         register int    ffstat;
00430                         register int    ret;
00431 /*
00432  *                      If file is direct access, we know that all reads are
00433  *                      going to be whole records in FULL mode.  We also
00434  *                      know that the open code would not let us get this far
00435  *                      if we were not dealing with a stream layer.
00436  */
00437 
00438                         breq    = chars;
00439 
00440                         ret     = XRCALL(fio, readcrtn) fio, CPTR2BP(uda),
00441                                         breq, &stat, mode);
00442 
00443                         if (ret < 0) {
00444                                 errno   = stat.sw_error;
00445                                 return(IOERR);
00446                         }
00447 
00448                         ffstat  = FFSTAT(stat);
00449 
00450                         if (!cup->useq && !cup->ublkd && ffstat == FFCNT)
00451                                 ffstat  = FFEOR;
00452 
00453                         *status = FF2FTNST(ffstat);
00454                         nchr    = ret;
00455 
00456                         return(nchr);   /* Return number of characters read */
00457                 }
00458 /*
00459  *              Get proper byte size (might not be 8-bits if doing conversion).
00460  */
00461 
00462 #if     NUMERIC_DATA_CONVERSION_ENABLED
00463                 bytsiz  = __fndc_charsz[cup->ucharset];
00464 #else
00465                 bytsiz  = 8;
00466 #endif
00467                 FFSTAT(cup->uffsw)      = FFCNT;
00468                 *status = CNT;
00469 
00470                 while (nchr < chars && FFSTAT(cup->uffsw) != FFEOR) {
00471                         register long   bgot;
00472                         register long   breq;
00473                         register long   padc;
00474                         register int    ret;
00475                         register long   totbits;
00476                         int             ubc;
00477 /*
00478  *                      Calculate the number of bits that need to be taken
00479  *                      from the foreign data stream.
00480  *
00481  *                      ncnt    = number of resultant bytes
00482  */
00483                         ncnt    = chars - nchr;
00484 
00485                         if (ncnt > TBUFSZB)
00486                                 ncnt    = TBUFSZB;
00487 
00488                         totbits = bytsiz * ncnt;        /* bit count */
00489                         breq    = (totbits + 7) >> 3;   /* full 8-bit bytes */
00490                         ubc     = (breq << 3) - totbits;/* unused bits */
00491 
00492                         ret     = XRCALL(fio, readrtn) fio, CPTR2BP(tbuf),
00493                                         breq, &cup->uffsw, PARTIAL, &ubc);
00494 
00495                         if (ret < 0) {  /* if an error */
00496                                 errno   = cup->uffsw.sw_error;
00497                                 return(IOERR);
00498                         }
00499 
00500                         /* if end of file */
00501 
00502                         if (ret == 0) {
00503                                 if (nchr == 0)
00504                                         *status = FF2FTNST(FFSTAT(stat));
00505                                 return(nchr);   /* Return number of characters read */
00506                         }
00507 
00508 /*
00509  *                      how many bits did we get?  Convert back to foreign
00510  *                      character count.
00511  */
00512                         totbits = (ret << 3) - ubc;
00513                         bgot    = totbits / bytsiz;     /* foreign bytes */
00514                         ubc     = totbits - (bgot * bytsiz);
00515 
00516                         if (ubc != 0) {
00517                                 errno   = FEINTUNK;
00518                                 return(IOERR);
00519                         }
00520 
00521                         padc    = 0;
00522 
00523                         if (FFSTAT(cup->uffsw) == FFEOR) {
00524                                 padc    = chars - (bgot + nchr);
00525                                 *status = EOR;
00526                         }
00527 
00528                         if (_fdc_unpackc(tbuf, &uda[nchr], bgot, padc,
00529                                 cup->ucharset) < 0) {
00530                                 return(IOERR);
00531                         }
00532 
00533                         nchr    += bgot;
00534                 }
00535 
00536                 /* check for null request, non-EOR */
00537 
00538                 if (FFSTAT(cup->uffsw) == FFCNT && mode == FULL) {
00539                         register int    ret;
00540                         int             ubc;
00541 
00542                         ret     = XRCALL(fio, readrtn) fio, CPTR2BP(tbuf), 0,
00543                                         &cup->uffsw, FULL, &ubc);
00544 
00545                         if (ret < 0) {  /* if an error */
00546                                 errno   = cup->uffsw.sw_error;
00547                                 return(IOERR);
00548                         }
00549                 }
00550                 return(nchr);
00551 
00552         case FS_AUX:
00553                 errno   = FEMIXAUX;
00554                 return(IOERR);
00555 
00556         default:
00557                 errno   = FEINTFST;
00558                 return(IOERR);
00559         }
00560 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines