Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
rf90.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/rf90.c     92.4    06/18/99 15:49:57"
00039 
00040 #include <ctype.h>
00041 #include <errno.h>
00042 #include <liberrno.h>
00043 #include <fortran.h>
00044 #include <stdlib.h>
00045 #include <string.h>
00046 #include <unistd.h>
00047 #include <cray/fmtconv.h>
00048 #include <cray/format.h>
00049 #include <cray/nassert.h>
00050 #ifndef _ABSOFT
00051 #include <sys/unistd.h>
00052 #endif
00053 #include "fio.h"
00054 #include "fmt.h"
00055 #include "fstats.h"
00056 #include "f90io.h"
00057 
00058 /*
00059  *      _FRF    Called by compiled Fortran programs to process a formatted
00060  *              or list-directed read statement.  Each statement is
00061  *              processed by one or more calls to _FRF.
00062  *
00063  *      Synopsis
00064  *
00065  *              int _FRF(       ControlList     *cilist,
00066  *                              iolist_header   *iolist,
00067  *                              void            *stck);
00068  *              
00069  *              Where
00070  *
00071  *                      cilist  Pointer to the control information list 
00072  *                              information.  This describes the specifiers 
00073  *                              for the current I/O statement.  This cilist
00074  *                              is guaranteed by the compiler to reflect
00075  *                              the original values of control information
00076  *                              list variables for the duration of the I/O
00077  *                              statement (ie through multiple calls).
00078  *                      iolist  Pointer to the I/O list information. 
00079  *                      stck    Pointer to stack space which is passed
00080  *                              to each call to _FRF for a particular 
00081  *                              statement.  This space is used by the
00082  *                              library.
00083  *
00084  *      Return value
00085  *
00086  *              IO_OKAY, IO_ERR, IO_END, or IO_EOR 
00087  */
00088 int
00089 _FRF(ControlListType *cilist, iolist_header *iolist, void *stck)
00090 {
00091         register int    errf;           /* ERR processing flag  */
00092         register int    errn;           /* Error number         */
00093         register int    iost;           /* I/O statement type   */
00094         register int    retval;         /* _FRF return value    */
00095         register recn_t errarg;         /* Extra _ferr argument */
00096         register unum_t unum;           /* Unit number          */
00097         unit            *cup;           /* Unit table pointer   */
00098         FIOSPTR         css;            /* I/O statement state  */
00099 
00100 /*
00101  *      Assertions 
00102  */
00103         /* Validate that the size of *stck is large enough */
00104         assert ( cilist->stksize >= sizeof(struct fiostate)/sizeof(long) );
00105 
00106         /* The compiler disallows ADVANCE='YES' w/ SIZE= */
00107         assert ( ! (cilist->advcode == CI_ADVYES && cilist->size_spec != NULL));
00108 
00109         /* The compiler disallows ADVANCE='YES' w/ EOR= */
00110         assert ( ! (cilist->advcode == CI_ADVYES && cilist->eorflag));
00111 
00112         /* The compiler disallows ADVANCE= w/ internal files */
00113         assert( ! (cilist->advcode != CI_ADVYES && cilist->internal != 0));
00114 
00115         /* The compiler disallows ADVANCE= w/ list-directed */
00116         assert( ! (cilist->advcode != CI_ADVYES && cilist->fmt == CI_LISTDIR));
00117 
00118         css     = stck;
00119         errn    = 0;
00120         errarg  = 0;
00121         retval  = IO_OKAY;
00122 
00123         if (iolist->iolfirst == 0) {
00124                 cup     = css->f_cu;
00125                 goto data_transfer;
00126         }
00127 
00128 /*******************************************************************************
00129  *
00130  *      Statement Initialization Section
00131  *
00132  ******************************************************************************/
00133 
00134         /* Establish error processing options */
00135 
00136         errf    = (cilist->errflag || cilist->iostatflg);
00137 
00138         if (cilist->fmt == CI_LISTDIR) 
00139                 iost    = T_RLIST;
00140         else if (cilist->dflag)
00141                 iost    = T_RDF;
00142         else
00143                 iost    = T_RSF;
00144 
00145         /* Zero the SIZE= value before any errors are encountered */
00146 
00147         if (iost & TF_FMT)
00148                 css->u.fmt.u.fe.charcnt = 0;
00149 
00150         css->u.fmt.freefmtbuf   = 0;
00151         css->u.fmt.freepfmt     = 0;
00152         css->u.fmt.tempicp      = NULL;
00153 
00154         /* Check if we're doing internal I/O or external I/O */
00155 
00156         if (cilist->internal) {         /* If internal I/O */
00157                 STMT_BEGIN(-1, 1, iost, NULL, css, cup);
00158                 cup->uft90      = 1;    /* set F90 mode for internal file */
00159 #ifndef __mips
00160                 cup->ufcompat   = 2;    /* set CF90 on internal file */
00161                 cup->ufunilist  = 0;
00162                 cup->ufcomsep   = 0;
00163                 cup->ufcomplen  = 0;
00164                 cup->ufrptcnt   = 0;
00165 #elif   defined(_LITTLE_ENDIAN)
00166                 cup->ufcompat   = 0;    /* set no f90 on internal file */
00167                 cup->ufunilist  = 0;
00168                 cup->ufcomsep   = 0;
00169                 cup->ufcomplen  = 0;
00170                 cup->ufrptcnt   = 0;
00171 #else
00172                 cup->ufcompat   = 4;    /* set IRIXF90 on internal file */
00173                 cup->ufunilist  = 0;
00174                 cup->ufcomsep   = 0;
00175                 cup->ufcomplen  = 0;
00176                 cup->ufrptcnt   = 0;
00177 #endif
00178         }
00179         else {                          /* Else external I/O */
00180                 if (cilist->uflag == CI_UNITASTERK)
00181                         unum    = STDIN_U;
00182                 else
00183                         unum    = *cilist->unit.wa;
00184 
00185                 STMT_BEGIN(unum, 0, iost, NULL, css, cup);
00186 
00187                 if (cup == NULL) {      /* If not connected */
00188                         int     stat;
00189 
00190                         cup     = _imp_open(    css,
00191                                                 (cilist->dflag ? DIR : SEQ),
00192                                                 FMT,
00193                                                 unum,
00194                                                 errf,
00195                                                 &stat);
00196 
00197                         /*
00198                          * If the open failed, cup is NULL and stat contains 
00199                          * the error number.
00200                          */
00201                         if (cup == NULL) {
00202                                 errn    = stat;
00203                                 goto handle_exception;
00204                         }
00205                 }
00206         }
00207 
00208         /* All paths which lead here have set cup to a non-null value */
00209 
00210         assert (cup != NULL);
00211 
00212         /* Copy the user's error processing options into the unit table */
00213 
00214         cup->uflag      = (cilist->errflag              ?  _UERRF : 0) |
00215                           (cilist->endflag              ?  _UENDF : 0) |
00216                           (cilist->eorflag              ?  _UEORF : 0) |
00217                           (cilist->iostat_spec != NULL  ? _UIOSTF : 0);
00218 
00219         /* Initialize fields in the Fortran statement state structure */
00220 
00221         css->u.fmt.icp          = NULL;
00222         css->u.fmt.blank0       = cup->ublnk;
00223         css->u.fmt.lcomma       = 0;
00224         css->u.fmt.slash        = 0;
00225 #ifdef  _CRAYMPP
00226         css->f_shrdput          = 0;
00227 #endif
00228 
00229         /* Process the format and related specifiers */
00230 
00231         if (cilist->fmt != CI_LISTDIR) {        /* If formatted input */
00232                 register int    stat;
00233 
00234                 css->u.fmt.u.fe.fmtbuf  = NULL;
00235                 css->u.fmt.u.fe.fmtnum  = 0;
00236                 css->u.fmt.u.fe.fmtcol  = 0;
00237                 css->u.fmt.u.fe.scale   = 0;
00238 
00239                 errn    = setup_format(css, cup, cilist);
00240 
00241                 if (errn > 0)
00242                         goto handle_exception;
00243 
00244                 /* Handle ADVANCE specifier */
00245 
00246                 stat    = _is_nonadv(cilist);
00247 
00248                 if (stat < 0)
00249                         errn    = FEADVSPC;     /* Invalid ADVANCE specifier */
00250 
00251                 if (cilist->advcode == CI_ADVVAR && stat == 0) {
00252                         if (cilist->size_spec != NULL)
00253                                 errn    = FEADVSIZ; /* ADVANCE='YES' w/SIZE= */
00254 
00255                         if (cilist->eorflag)
00256                                 errn    = FEADVEOR; /* ADVANCE='YES' w/EOR= */
00257                 }
00258 
00259                 if (errn != 0)
00260                         goto handle_exception;
00261 
00262                 css->u.fmt.nonadv       = stat;
00263         }
00264         else                                    /* Else list-directed input */
00265                 css->u.fmt.nonadv       = 0;
00266 
00267         /* Set processing functions */
00268 
00269         if (cilist->dflag) {
00270 
00271                 if (!cup->ok_rd_dir_fmt)
00272                         errn    = _get_mismatch_error(errf, iost, cup, css);
00273                 else {
00274                         register recn_t recn;   /* Record number */
00275 
00276                         recn    = (recn_t) *cilist->rec_spec;
00277                         errarg  = recn;
00278                         errn    = _unit_seek(cup, recn, iost);
00279                 }
00280 
00281                 css->u.fmt.endrec       = _dr_endrec;
00282         }
00283         else {
00284 
00285                 if (!cup->ok_rd_seq_fmt) {
00286                         errn    = _get_mismatch_error(errf, iost, cup, css);
00287                         goto handle_exception;
00288                 }
00289 
00290                 if (cilist->internal) {
00291 
00292                         css->u.fmt.endrec       = _ir_endrec;
00293 
00294                         if (cilist->uflag == CI_UNITCHAR) {
00295                                 css->u.fmt.iiae = 1;
00296                                 css->u.fmt.icp  = _fcdtocp(cilist->unit.fcd);
00297                                 css->u.fmt.icl  = _fcdlen (cilist->unit.fcd);
00298                         }
00299                         else {
00300                                 DopeVectorType *dv = cilist->unit.dv;
00301                                 void    *newar;
00302                                 int     nocontig = 0;
00303                                 long    extent = 0;
00304                                 long    nbytes = 0;
00305 
00306                                 css->u.fmt.icp  = _fcdtocp(dv->base_addr.charptr);
00307                                 css->u.fmt.icl  = _fcdlen (dv->base_addr.charptr);
00308 
00309                                 newar   = (void *) NULL;
00310 
00311                                 if (dv->p_or_a && (dv->assoc == 0))
00312                                         errn    = FEUNOTAL; /* Not allocated/associated */
00313                                 else    /* Check for contiguous array */
00314                                         errn    = _cntig_chk(dv, &newar, &nocontig,
00315                                                         &extent, &nbytes);
00316 
00317                                 if (errn != 0)
00318                                         goto handle_exception;
00319 
00320                                 /* Number of elements in array */
00321 
00322                                 css->u.fmt.iiae = extent;
00323 
00324                                 if (nocontig) {
00325                                         css->u.fmt.icp          = newar;
00326                                         css->u.fmt.tempicp      = newar;
00327                                 }
00328                         }
00329 
00330                         /*
00331                          * If the size of the internal record is greater
00332                          * than the existing line buffer, then realloc()
00333                          * another one; else just decrease urecsize.
00334                          */
00335  
00336                         if (css->u.fmt.icl > cup->urecsize) {
00337  
00338                                 cup->ulinebuf   = (long *) realloc(cup->ulinebuf,
00339                                                         sizeof(long) *
00340                                                         (css->u.fmt.icl + 1));
00341 
00342                                 if (cup->ulinebuf == NULL)
00343                                         errn    = FENOMEMY;     /* No memory */
00344                         }
00345 
00346                         cup->urecsize   = css->u.fmt.icl;
00347                 }
00348                 else {                  /* external sequential formatted I/O */
00349 
00350                         if (cup->uend != BEFORE_ENDFILE && !cup->umultfil) /* If after endfile */
00351                                 errn    = FERDENDR;     /* Read after endfile */
00352         
00353                         if (cup->uwrt)  /* If writing */
00354                                 errn    = FERDAFWR;     /* Read after write */
00355 
00356                         css->u.fmt.endrec       = _sr_endrec;
00357 
00358                 }
00359         }
00360 
00361         if (errn != 0)
00362                 goto handle_exception;
00363 
00364         if (cup->pnonadv == 0) {        /* If previous ADVANCE='YES' */
00365                 errn    = (*css->u.fmt.endrec)(css, cup, 1); /* Read a record */
00366 
00367                 if (errn != 0)
00368                         goto handle_exception;
00369         }
00370         else                    /* else previous ADVANCE='NO' */
00371                 css->u.fmt.leftablim    = cup->ulineptr; /* Set left tab limit */
00372 
00373         cup->pnonadv    = css->u.fmt.nonadv;    /* Remember previous ADVANCE */
00374         cup->uwrt       = 0;                    /* Set read status */
00375 
00376 /*******************************************************************************
00377  *
00378  *      Data Transfer Section
00379  *
00380  ******************************************************************************/
00381 data_transfer:
00382 
00383         errn    = _xfer_iolist(css, cup, iolist, (cilist->fmt == CI_LISTDIR) ?
00384                                 _ld_read : _rdfmt);
00385 
00386         if (errn != 0)
00387                 goto handle_exception;
00388 
00389         if (! iolist->iollast )
00390                 return (IO_OKAY);
00391 
00392 /******************************************************************************
00393  *
00394  *      Statement Finalization Section
00395  *
00396  ******************************************************************************/
00397 finalization:
00398 
00399 #ifdef  _CRAYMPP
00400         if (css->f_shrdput) {
00401                 css->f_shrdput  = 0;
00402                 _remote_write_barrier();
00403         }
00404 #endif
00405         /* If formatted I/O and no error/EOF/EOR, complete processing */
00406 
00407         if (cilist->fmt != CI_LISTDIR) {        /* If formatted */
00408 
00409                 if (errn == 0)  /* Complete format */
00410                         errn    = _rdfmt(css, cup, (void *) NULL, &__tip_null,
00411                                         0);
00412 
00413                 /* If we allocated memory for a variable format, free it */
00414 
00415                 if (css->u.fmt.freepfmt && css->u.fmt.u.fe.pfmt != NULL)
00416                         free(css->u.fmt.u.fe.pfmt);
00417 
00418                 /* If we allocated memory for a noncontiguous format,
00419                  * free it.
00420                  */
00421 
00422                 if (css->u.fmt.freefmtbuf && css->u.fmt.u.fe.fmtbuf != NULL)
00423                         free(css->u.fmt.u.fe.fmtbuf);
00424         }
00425 
00426         /*
00427          * If we allocated memory for an internal file, move the output
00428          * file from the temporary array to the noncontiguous array and
00429          * free the temporary array.
00430          */
00431 
00432         if (cilist->internal && css->u.fmt.tempicp != NULL) {
00433                 (void) _unpack_arry (css->u.fmt.tempicp,
00434                                         cilist->unit.dv);
00435                 free(css->u.fmt.tempicp);
00436         }
00437 
00438 out_a_here:
00439 
00440         /* Set IOSTAT variable to 0 if no error, >0 error code otherwise */
00441 
00442         if (cilist->iostat_spec != NULL)
00443                 *cilist->iostat_spec    = errn;
00444 
00445         /* Store character count in the SIZE= variable */
00446 
00447         if (cilist->size_spec != NULL)
00448                 *cilist->size_spec      = css->u.fmt.u.fe.charcnt;
00449 
00450         STMT_END(cup, TF_READ, NULL, css);      /* Unlock unit */
00451 
00452         /* Return proper status */
00453 
00454         return (retval);
00455 
00456 /*
00457  *      We put the error handling stuff here to reduce its impact when
00458  *      no errors are generated.  If we jump here, errn is set to a nonzero
00459  *      error, eor, or endfile status code.
00460  */
00461 handle_exception:
00462         if (errn < 0) { /* If EOF/EOR type error */
00463 
00464                 /* No current record if EOF or EOR */
00465 
00466                 if (cup != NULL) 
00467                         cup->pnonadv    = 0;
00468 
00469                 if (errn == FEEORCND)
00470                         retval  = IO_EOR;
00471                 else
00472                         retval  = IO_END;
00473         }
00474         else 
00475                 retval  = IO_ERR;
00476 
00477         if (retval == IO_ERR && ! cilist->errflag && ! cilist->iostatflg)
00478                 _ferr(css, errn, errarg);
00479 
00480         if (retval == IO_EOR && ! cilist->eorflag && ! cilist->iostatflg)
00481                 _ferr(css, errn, errarg);
00482 
00483         if (retval == IO_END && ! cilist->endflag && ! cilist->iostatflg)
00484                 _ferr(css, errn, errarg);
00485 
00486         if (cup == NULL)
00487                 goto out_a_here;
00488 
00489         goto finalization;
00490 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines