Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
frwd.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/frwd.c     92.3    09/29/99 19:50:24"
00039 
00040 #include <errno.h>
00041 #include <fortran.h>
00042 #include <liberrno.h>
00043 #ifdef  _ABSOFT
00044 #include <stdlib.h>
00045 #endif
00046 #include <cray/nassert.h>
00047 #include "fio.h"
00048 
00049 #include <stdlib.h>
00050 
00051 #define TBFSZ   (4096 * sizeof(long))   /* Size of temporary buffer (bytes) */
00052 
00053 static const _f_int     bitoff = 0;
00054 static const _f_int     stride = 1;
00055 
00056 /*
00057  *      _frwd 
00058  *              Read binary data from one record of a Fortran file.
00059  *
00060  *      Side effects
00061  *
00062  *              Increments cup->urecpos by the change in bit position within
00063  *              the record, including pad bits.
00064  *
00065  *              Sets *status as follows:
00066  *
00067  *                      CNT - if the requested number of items were read, and
00068  *                            more data remains in the current record (if
00069  *                            the file has records).  
00070  *                      EOR - if all remaining data in the current record was 
00071  *                            read by this request. 
00072  *                      EOF - if a physical EOF mark was read and no data 
00073  *                            preceded the EOF mark.
00074  *                      EOD - if the end-of-data mark was reached and no data 
00075  *                            was read.
00076  *
00077  *      Return value
00078  *              The number of items read.  -1 on error with errno set to
00079  *              the error code.
00080  *
00081  *      Note
00082  *              If a nonzero amount of data was read and an EOF mark or the 
00083  *              end of file was encountered before reading the full amount
00084  *              of data requested and before encountering EOR, CNT status is 
00085  *              returned.  This is not well supported because we never detect 
00086  *              that we processed the EOF.  However, no FFIO layers currently 
00087  *              support embedded EOF marks inside a record.
00088  */
00089 
00090 long
00091 _frwd(
00092 unit            *cup,           /* Unit pointer */
00093 void            *uda,           /* User data address */
00094 type_packet     *tip,           /* Type information packet */
00095 int             mode,           /* FULL or PARTIAL record mode */
00096 int             *ubcret,        /* If non-NULL, pointer to unused bit count in 
00097                                  * the last item.  This is both an input and 
00098                                  * output parameter.  On input it enables the 
00099                                  * caller to request an arbitrary number of 
00100                                  * bits.  On output it reflects the actual data
00101                                  * transfer.
00102                                  *  NOTE:  Normal item alignment (normally 
00103                                  *         forced to word boundaries) is 
00104                                  *         disabled when this parameter is 
00105                                  *         passed.      */
00106 long            *wr,            /* If non-NULL, pointer to number of items read.
00107                                  * This is an output parameter.  It is useful 
00108                                  * because it is possible to have an error 
00109                                  * return, but still return data.  This 
00110                                  * parameter is set only if an error is 
00111                                  * encountered with data being delivered.  It 
00112                                  * is currently only set for FFIO files where 
00113                                  * foreign data conversion is not active. */
00114 int             *status)        /* assigned on return to CNT, EOR, EOF, or EOD*/
00115 {
00116         register int    fdsize;         /* Item size (bits) in file */
00117         register int    padbyts;
00118         register long   elsize;
00119         register long   items;
00120         register ftype_t type;          /* Fortran data type */
00121         register size_t breq;
00122         register ssize_t ret;
00123         register int64  totbits;
00124         int             padubc;
00125         int             ubc;
00126         _f_int          icount;
00127 
00128         /* Assertions */
00129 
00130 #ifdef  _UNICOS
00131         assert ( _numargs() == 7 );
00132 #endif
00133         assert ( mode == FULL || mode == PARTIAL );
00134         assert ( tip != NULL );
00135         assert ( status != NULL );
00136 
00137         type    = tip->type90;
00138         elsize  = tip->elsize;
00139         items   = tip->count;
00140         breq    = elsize * items;       /* bytes requested */
00141         padbyts = 0;
00142         padubc  = 0;
00143         ubc     = 0;
00144 /*
00145  *      If a ubc word is passed, this call is asking for typeless data; no 
00146  *      data conversion will be done.  The ubcret and wr arguments are used
00147  *      by CALL READ/READP.
00148  */
00149         if (ubcret != NULL) {
00150                 if ((*ubcret & 7) != 0 && cup->ufs != FS_FDC) {
00151                         errno   = FEUBCINV;
00152                         return(IOERR);
00153                 }
00154                 if (type != DVTYPE_TYPELESS) {
00155                         errno   = FEINTUNK;
00156                         return(IOERR);
00157                 }
00158 /*
00159  *              Adjust breq for ubc input, which can be 0-63
00160  */
00161                 breq    -= *ubcret >> 3;
00162                 ubc     = *ubcret & 7;
00163         }
00164 #if     NUMERIC_DATA_CONVERSION_ENABLED
00165         else {
00166 /*
00167  *              Pad word-aligned numeric data on word boundaries within
00168  *              the record for CRI and some foreign data formats.  Note
00169  *              that the elsize expression needs to be cleaned up to be
00170  *              something like:  external_size > granularity.
00171  */
00172                 if ((cup->urecpos & cup->ualignmask) != 0 &&
00173                     type != DVTYPE_ASCII &&
00174                     items > 0 &&
00175 #if     defined(__mips) || defined(_LITTLE_ENDIAN)
00176                     elsize > 2 ) {
00177 #else
00178                     elsize > 4 ) {
00179 #endif
00180 
00181                         long    blanks;
00182                         COMPADD(cup, padbyts, padubc, blanks);
00183                 }
00184         }
00185 #endif  /* NUMERIC_DATA_CONVERSION_ENABLED */
00186 
00187         cup->ulastyp    = type;
00188 
00189         *status = CNT;          /* default return status */
00190 /*
00191  *      According to the file structure make the appropriate
00192  *      low level read request.
00193  */
00194         switch ( cup->ufs ) {
00195 
00196         case  STD:
00197 /*
00198  *              If the number of items to read is zero return to caller. 
00199  *              Unicos binary files have no record structure.  Except for
00200  *              an end of file, a read request always returns CNT status.
00201  */
00202                 if (items == 0)
00203                         return(0);
00204 
00205                 ret     = 1;
00206 
00207                 if (padbyts > 0) {      /* Flush a few bytes */
00208                         int     dummy;
00209 
00210                         ret     = fread(&dummy, 1, padbyts, cup->ufp.std);
00211 
00212                         if (ret > 0)
00213                                 cup->urecpos    += (uint64)ret << 3;
00214 
00215                 }
00216                 if (ret > 0)    /* don't continue if last read failed. */
00217                         ret     = fread(uda, 1, breq, cup->ufp.std );
00218  
00219                 if (ret == 0) {
00220                         if ( ferror(cup->ufp.std) ) {
00221                                 if (errno == 0)
00222                                         errno   = FESTIOER;
00223                                 return(IOERR);
00224                         }
00225                         *status = EOD;
00226                         return(0);
00227                 }
00228 /*
00229  *              If the read produced an integral number of items, return.
00230  *              else allow partial items only for typeless.
00231  */
00232                 icount          = ret / elsize;
00233                 cup->urecpos    = cup->urecpos + (uint64) (ret << 3);
00234 
00235                 if ((ret % elsize) != 0)
00236                         if (type == DVTYPE_TYPELESS) {
00237 
00238                                 icount  = icount + 1;
00239 
00240                                 if (ubcret != NULL)
00241                                         *ubcret = (elsize - (ret % elsize)) << 3;
00242                         }
00243                         else
00244                                 if (icount == 0) {
00245                                         errno   = FERDPEOR;
00246                                         return(IOERR);
00247                                 }
00248 
00249                 break;
00250 
00251         case FS_FDC:
00252 /*
00253  *              Align the FD to a word boundary if required.
00254  */
00255 
00256                 if (padbyts > 0) {
00257                         long    paddval;
00258 
00259                         ret     = XRCALL(cup->ufp.fdc, readrtn) cup->ufp.fdc,
00260                                 CPTR2BP(&paddval), padbyts, &cup->uffsw,
00261                                 PARTIAL, &padubc);
00262 
00263                         if (ret != padbyts || FFSTAT(cup->uffsw) != FFCNT) {
00264 
00265                                 if (ret < 0) {
00266                                         errno   = cup->uffsw.sw_error;
00267                                         return(IOERR);
00268                                 }
00269 
00270                                 *status = FF2FTNST(FFSTAT(cup->uffsw));
00271 
00272                                 return(0);
00273                         }
00274 
00275                         cup->urecpos    += ((uint64)ret << 3) - padubc;
00276                 }
00277 /*
00278  *              If no conversion to be done, just read in the data
00279  */
00280                 if (tip->cnvindx == 0) {
00281                         register short  erret;
00282 /*
00283  *                      read in the data
00284  */
00285                         ret     = XRCALL(cup->ufp.fdc, readrtn) cup->ufp.fdc,
00286                                         CPTR2BP(uda), breq,
00287                                         &cup->uffsw, mode, &ubc);
00288 
00289                         *status = FF2FTNST(FFSTAT(cup->uffsw));
00290                         erret   = 0;
00291 
00292                         if (*status == EOR)
00293                                 cup->ulastyp    = DVTYPE_TYPELESS;
00294 
00295                         if (ret < 0) {          /* if an error */
00296 
00297                                 errno   = cup->uffsw.sw_error;
00298 
00299                                 if (errno == FETAPUTE) {
00300                                         ret     = cup->uffsw.sw_count;
00301                                         erret   = 1;
00302                                 }
00303                                 else
00304                                         return(IOERR);
00305                         }
00306                         else
00307                                 if (ret == 0)
00308                                         return(0);
00309 /*
00310  *                      Data was returned (ret > 0), process it
00311  *
00312  *                      If the read produced an integral number of items,
00313  *                      then return.  Else allow partial items only for
00314  *                      typeless.
00315  */
00316                         totbits         = ((uint64)ret << 3) - ubc;
00317                         cup->urecpos    = cup->urecpos + totbits;
00318                         icount          = totbits / (elsize << 3);
00319 
00320                         if (type == DVTYPE_TYPELESS) {
00321 
00322                                 if ((((uint64)icount*elsize) << 3) != totbits) {
00323 
00324                                         icount  = icount + 1;
00325 
00326                                         if (ubcret != NULL)
00327                                                 *ubcret = (elsize << 3) -
00328                                                    (totbits % (elsize << 3));
00329                                 }
00330 
00331                                 if (wr != NULL)
00332                                         *wr     = icount;
00333                         }
00334                         else
00335                                 if (icount == 0) {
00336                                         errno   = FERDPEOR;
00337                                         erret   = 1;
00338                                 }
00339 
00340                         if (erret == 1)
00341                                 return(IOERR);
00342 
00343                         goto done;      /* Return number of items read */
00344                 }
00345 
00346 #if     NUMERIC_DATA_CONVERSION_ENABLED
00347 /*
00348  *              Process numeric or character conversion.
00349  */
00350                 {
00351                 int             (* cvt_fun)();  /* Conversion function  */
00352                 _f_int          dctype;
00353                 char            tbuf[TBFSZ];    /* Temporary buffer     */
00354                 char            *bptr;          /* Buffer pointer       */
00355 
00356                 cvt_fun = __fndc_ncfunc[tip->cnvindx].to_native;
00357 
00358 #if     !defined(__mips) && !defined(_LITTLE_ENDIAN)
00359                 if (!_loaded(cvt_fun)) {
00360                         errno   = FELDDCNV;
00361                         return(IOERR);
00362                 }
00363 #endif
00364 
00365                 fdsize  = tip->extlen;
00366                 dctype  = tip->cnvtype;
00367 
00368 /*
00369  *              Point the pointer to the tail end of the buffer by
00370  *              calculating the total bit count, and then rounding down
00371  *              to a word boundary.  Note that fdsize is the size of
00372  *              each byte for type==DVTYPE_ASCII, so we must multiply by
00373  *              elsize to get the real total bit count.
00374  */
00375                 if (fdsize == 0) {
00376                         errno   = FDC_ERR_NCVRT;
00377                         return(IOERR);
00378                 }
00379 
00380                 totbits = items * fdsize;       /* Bit size of foreign data to 
00381                                                  * be read from the file. */
00382 
00383                 if (type == DVTYPE_ASCII)
00384                         totbits = totbits * tip->elsize;
00385 
00386                 if (ubcret != NULL)
00387                         totbits = totbits - *ubcret;
00388 
00389                 /*
00390                  * Round pointer down to the next byte if numeric conversion
00391                  * is requested.
00392                  */
00393 
00394                 bptr    = tbuf; /* Assume data will fit in temporary buffer */
00395                 breq    = (totbits + 7) >> 3;
00396                 ubc     = ((uint64)breq << 3) - totbits;
00397 
00398                 if (breq > TBFSZ) {
00399                         bptr    = (char *) malloc(breq);
00400 
00401                         if (bptr == NULL) {     /* malloc() failed! */
00402                                 errno   = FENOMEMY;
00403                                 return(IOERR);
00404                         }
00405                 }
00406 /*
00407  *              read in the data
00408  */
00409                 ret     = XRCALL(cup->ufp.fdc, readrtn) cup->ufp.fdc,
00410                                 CPTR2BP(bptr), breq,
00411                                 &cup->uffsw, mode, &ubc);
00412 
00413                 *status = FF2FTNST(FFSTAT(cup->uffsw));
00414 
00415                 if (*status == EOR)
00416                         cup->ulastyp    = DVTYPE_TYPELESS;
00417 
00418                 if (ret <= 0) {         /* If an error or no data */
00419                         register long   stat = EOR;
00420 
00421                         if (bptr != tbuf)       /* Free allocated space */
00422                                 free(bptr);
00423 
00424                         if (ret < 0) {
00425                                 errno   = cup->uffsw.sw_error;
00426                                 stat    = IOERR;
00427                         }
00428 
00429                         return(stat);
00430                 }
00431 
00432 /*
00433  *              If the read produced an integral number of items, return.
00434  *              else diagnose partial items.
00435  */
00436                 totbits = ((uint64)ret << 3) - ubc;
00437                 icount  = totbits / fdsize;
00438 
00439                 if (((int64)icount * fdsize) != totbits) {
00440                         if (bptr != tbuf)       /* Free allocated space */
00441                                 free(bptr);
00442                         /* partial items with conversion on is weird */
00443                         errno   = FDC_ERR_PITM;
00444                         return(IOERR);
00445                 }
00446 /*
00447  *              Do the numeric conversion
00448  */
00449                 {
00450                 register _f_int numerr;         /* Error code */
00451 #ifdef  _CRAY
00452                 _fcd            craychr;        /* Only used for char. conversion */
00453 
00454                 craychr = _cptofcd((char *)uda, items);
00455 #endif
00456 
00457                 if (tip->newfunc) {
00458                         _f_int  flen;           /* Foreign length, in bits */
00459                         _f_int  nlen;           /* Native length, in bits */
00460 
00461                         flen    = fdsize;
00462                         nlen    = tip->intlen;
00463 
00464                         numerr  = cvt_fun(&dctype, &icount, (void *) bptr,
00465                                         &bitoff, (void *)uda, &stride, &nlen,
00466                                         &flen,
00467 #ifdef  _CRAY
00468                                         craychr);
00469 #else
00470                                         (char *)uda, items);
00471 #endif
00472                 }
00473                 else {
00474 
00475                         numerr  = cvt_fun(&dctype, &icount, (void *)bptr,
00476                                         &bitoff, (void *)uda, &stride,
00477 #ifdef  _CRAY
00478                                         craychr);
00479 #else
00480                                         (char *)uda, items);
00481 #endif
00482                 }
00483 
00484                 if (bptr != tbuf)       /* Free allocated space */
00485                         free(bptr);
00486 
00487                 if (numerr != 0) {
00488                         errno   = (numerr < 0) ? FEINTUNK : FDC_ERR_NCVRT;
00489                         return(IOERR);
00490                 }
00491                 }
00492                 }
00493 
00494                 cup->urecpos    += totbits;
00495 #endif  /* NUMERIC_DATA_CONVERSION_ENABLED */
00496 
00497                 break;
00498 
00499         case FS_AUX:
00500                 errno   = FEMIXAUX;
00501                 icount  = IOERR;
00502                 break;
00503 
00504         default:
00505                 errno   = FEINTFST;
00506                 icount  = IOERR;
00507                 break;
00508         } /* switch */
00509 
00510 done:
00511         return(icount);         /* Return number of items read or status */
00512 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines