Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
wf90.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/wf90.c     92.4    06/18/99 10:01:44"
00039 
00040 #include <stdio.h>
00041 #include <cray/format.h>
00042 #include <cray/nassert.h>
00043 #include "fio.h"
00044 #include "f90io.h"
00045 
00046 /*
00047  *      _FWF    Called by compiled Fortran programs to process a formatted
00048  *              write statement.  Each statement is processed by one or 
00049  *              more calls to _FWF.
00050  *
00051  *      Synopsis
00052  *
00053  *              int _FWF(       ControlList     *cilist,
00054  *                              iolist_header   *iolist,
00055  *                              void            *stck);
00056  *              
00057  *              Where
00058  *
00059  *                      cilist  Pointer to the control information list 
00060  *                              information.  This describes the specifiers 
00061  *                              for the current I/O statement.  This cilist
00062  *                              is guaranteed by the compiler to reflect
00063  *                              the original values of control information
00064  *                              list variables for the duration of the I/O
00065  *                              statement (ie through multiple calls).
00066  *                      iolist  Pointer to the I/O list information. 
00067  *                      stck    Pointer to stack space which is passed
00068  *                              to each call to _FWF for a particular
00069  *                              statement.  This space is used by the
00070  *                              library.
00071  *
00072  *      Return value
00073  *
00074  *              IO_OKAY or IO_ERR
00075  */
00076 
00077 int
00078 _FWF(ControlListType *cilist, iolist_header *iolist, void *stck)
00079 {
00080         register int    errf;           /* ERR processing flag  */
00081         register int    errn;           /* Error number         */
00082         register int    iost;           /* I/O statement type   */
00083         register int    retval;         /* _FWF return value    */
00084         register recn_t errarg;         /* Extra _ferr argument */
00085         register unum_t unum;           /* Unit number          */
00086         xfer_func       *xfunc;         /* Data transfer func.  */
00087         unit            *cup;           /* Unit table pointer   */
00088         FIOSPTR         css;            /* I/O statement state  */
00089 
00090 /*
00091  *      Assertions 
00092  */
00093         /* Validate that the size of *stck is large enough */
00094 
00095         assert ( cilist->stksize >= sizeof(struct fiostate)/sizeof(long) );
00096 
00097         /* The compiler disallows EOR= on WRITE */
00098 
00099         assert ( cilist->eorflag == 0 );
00100 
00101         /* The compiler disallows SIZE= on WRITE */
00102 
00103         assert ( cilist->size_spec == NULL );
00104 
00105         /* The compiler disallows ADVANCE= w/ internal files */
00106 
00107         assert( ! (cilist->advcode != CI_ADVYES && cilist->internal != 0));
00108 
00109         /* The compiler disallows ADVANCE= w/ list-directed */
00110 
00111         assert( ! (cilist->advcode != CI_ADVYES && cilist->fmt == CI_LISTDIR));
00112 
00113         css     = stck;
00114         errn    = 0;
00115         errarg  = 0;
00116         retval  = IO_OKAY;
00117         xfunc   = (cilist->fmt == CI_LISTDIR) ? _ld_write : _wrfmt;
00118 
00119         if (iolist->iolfirst == 0) {
00120                 cup     = css->f_cu;
00121                 /*
00122                  * Copy the user's error processing options into the unit table 
00123                  */
00124                 cup->uflag      = (cilist->errflag              ?  _UERRF : 0) |
00125                                   (cilist->iostat_spec != NULL  ? _UIOSTF : 0);
00126                 goto data_transfer;
00127         }
00128 
00129 /*******************************************************************************
00130  *
00131  *      Statement Initialization Section
00132  *
00133  ******************************************************************************/
00134 
00135         errf    = (cilist->errflag || cilist->iostatflg);
00136 
00137         if (cilist->fmt == CI_LISTDIR) 
00138                 iost    = T_WLIST;
00139         else if (cilist->dflag)
00140                 iost    = T_WDF;
00141         else
00142                 iost    = T_WSF;
00143 
00144         css->u.fmt.freefmtbuf   = 0;
00145         css->u.fmt.freepfmt     = 0;
00146         css->u.fmt.tempicp      = NULL;
00147 
00148         /* Check if we're doing internal I/O or external I/O */
00149 
00150         if (cilist->internal) {         /* If internal I/O */
00151                 STMT_BEGIN(-1, 1, iost, NULL, css, cup);
00152                 cup->uft90      = 1;    /* set F90 mode for internal file */
00153 #if     !defined(__mips)
00154                 cup->ufcompat   = 2;    /* set cf90 on internal file */
00155                 cup->ufunilist  = 0;
00156                 cup->ufcomsep   = 0;
00157                 cup->ufcomplen  = 0;
00158                 cup->ufrptcnt   = 0;
00159                 cup->ufnegzero  = 1;    /* set default write of -0.0 */
00160 #elif   defined(_LITTLE_ENDIAN)
00161                 cup->ufcompat   = 0;    /* set no f90 on internal file */
00162                 cup->ufunilist  = 0;
00163                 cup->ufcomsep   = 0;
00164                 cup->ufcomplen  = 0;
00165                 cup->ufrptcnt   = 0;
00166                 cup->ufnegzero  = 1;    /* set default write of -0.0 */
00167 #else
00168                 cup->ufcompat   = 4;    /* set irixf90 on internal file */
00169                 cup->ufunilist  = 0;
00170                 cup->ufcomsep   = 0;
00171                 cup->ufcomplen  = 0;
00172                 cup->ufrptcnt   = 0;
00173                 cup->ufnegzero  = 1;    /* set default write of -0.0 */
00174 #endif
00175         }
00176         else {                          /* Else external I/O */
00177                 if (cilist->uflag == CI_UNITASTERK)
00178                         unum    = STDOUT_U;
00179                 else
00180                         unum    = *cilist->unit.wa;
00181 
00182                 STMT_BEGIN(unum, 0, iost, NULL, css, cup);
00183 
00184                 if (cup == NULL) {      /* If not connected */
00185                         int     stat;
00186 
00187                         cup     = _imp_open(    css,
00188                                                 (cilist->dflag ? DIR : SEQ),
00189                                                 FMT,
00190                                                 unum,
00191                                                 errf,
00192                                                 &stat);
00193 
00194                         /*
00195                          * If the open failed, cup is NULL and stat contains 
00196                          * the error number.
00197                          */
00198                         if (cup == NULL) {
00199                                 errn    = stat;
00200                                 goto handle_exception;
00201                         }
00202                 }
00203         }
00204 
00205         /* All paths which lead here have set cup to a non-null value */
00206 
00207         assert (cup != NULL);
00208 
00209 /*
00210  *      Copy the user's error processing options into the unit table 
00211  */
00212         cup->uflag      = (cilist->errflag              ?  _UERRF : 0) |
00213                           (cilist->iostat_spec != NULL  ? _UIOSTF : 0);
00214 
00215         /* Initialize fields in the Fortran statement state structure */
00216 
00217         css->u.fmt.icp          = NULL;
00218         css->u.fmt.nonl         = 0;
00219 
00220         /* Process the format and related specifiers */
00221 
00222         if (cilist->fmt != CI_LISTDIR) {        /* If formatted output */
00223                 register int    stat;
00224 
00225                 css->u.fmt.u.fe.fmtbuf  = NULL;
00226                 css->u.fmt.u.fe.fmtnum  = 0;
00227                 css->u.fmt.u.fe.fmtcol  = 0;
00228                 css->u.fmt.u.fe.scale   = 0;
00229                 css->u.fmt.cplus        = 0;
00230 
00231                 errn    = setup_format(css, cup, cilist);
00232 
00233                 if (errn == 0) { /* If no error, handle ADVANCE specifier */
00234 
00235                         stat    = _is_nonadv(cilist);
00236 
00237                         if (stat < 0) /* If invalid ADVANCE specifier */
00238                                 errn    = FEADVSPC; /* Invalid ADVANCE */
00239                 }
00240 
00241                 if (errn != 0)
00242                         goto handle_exception;
00243 
00244                 css->u.fmt.nonadv       = stat;
00245         }
00246         else {                                  /* Else list-directed output */
00247                 css->u.fmt.u.le.ldwinit = 1;
00248                 css->u.fmt.nonadv       = 0;
00249         }
00250 
00251         /* Set processing functions */
00252 
00253         if (cilist->dflag) {
00254 
00255                 if (!cup->ok_wr_dir_fmt)
00256                         errn    = _get_mismatch_error(errf, iost, cup, css);
00257                 else {
00258                         recn_t  recn;   /* Record number */
00259 
00260                         recn    = (recn_t) *cilist->rec_spec;
00261                         errarg  = recn;
00262                         errn    = _unit_seek(cup, recn, iost);
00263                 }
00264 
00265                 cup->uend       = BEFORE_ENDFILE;
00266                 cup->ulinecnt   = 0;            /* Number of characters written */
00267                 cup->ulinemax   = 0;            /* Highwater mark */
00268                 cup->ulineptr   = cup->ulinebuf;/* Current character position */
00269                 css->u.fmt.endrec       = _dw_endrec;
00270         }
00271         else {
00272 
00273                 if (!cup->ok_wr_seq_fmt) {
00274                         errn    = _get_mismatch_error(errf, iost, cup, css);
00275                         goto handle_exception;
00276                 }
00277 
00278                 if (cilist->internal) {
00279 
00280                         cup->ulinecnt   = 0;    /* Number characters written */
00281                         cup->ulinemax   = 0;    /* Highwater mark */
00282 
00283                         css->u.fmt.endrec       = _iw_endrec;
00284 
00285                         if (cilist->uflag == CI_UNITCHAR) {
00286                                 css->u.fmt.iiae = 1;
00287                                 css->u.fmt.icp  = _fcdtocp(cilist->unit.fcd);
00288                                 css->u.fmt.icl  = _fcdlen (cilist->unit.fcd);
00289                         }
00290                         else {
00291                                 DopeVectorType  *dv = cilist->unit.dv;
00292                                 void            *newar;
00293                                 int             nocontig = 0;
00294                                 long            extent = 0;
00295                                 long            nbytes = 0;
00296 
00297                                 css->u.fmt.icp  = _fcdtocp(dv->base_addr.charptr);
00298                                 css->u.fmt.icl  = _fcdlen (dv->base_addr.charptr);
00299 
00300                                 /*
00301                                  * check for contiguous array
00302                                  */
00303                                 newar   = (void *) NULL;
00304 
00305                                 if (dv->p_or_a && (dv->assoc == 0))
00306                                         errn    = FEUNOTAL; /* Not allocated/associated */
00307                                 else
00308                                         errn    = _cntig_chk(dv, &newar, &nocontig,
00309                                                                 &extent, &nbytes);
00310                                 if (errn > 0)
00311                                         goto handle_exception;
00312 
00313                                 css->u.fmt.iiae         = extent;
00314 
00315                                 if (nocontig) {
00316                                         css->u.fmt.icp          = newar;
00317                                         css->u.fmt.tempicp      = newar;
00318                                 }
00319                         }
00320 
00321                         cup->uldwsize   = css->u.fmt.icl;
00322 
00323                         /*
00324                          * If the size of the internal record is greater
00325                          * than the existing line buffer, then realloc()
00326                          * another one; else just decrease urecsize.
00327                          */
00328  
00329                         if (css->u.fmt.icl > cup->urecsize) {
00330  
00331                                 cup->ulinebuf   = (long *)realloc(cup->ulinebuf,
00332                                                 sizeof(long) * (css->u.fmt.icl +
00333                                                 1));
00334 
00335                                 if (cup->ulinebuf == NULL)
00336                                         errn    = FENOMEMY;     /* No memory */
00337                         }
00338 
00339                         cup->urecsize   = css->u.fmt.icl;
00340                         cup->ulineptr   = cup->ulinebuf;
00341                 }
00342                 else {                  /* external sequential formatted I/O */
00343 
00344                         if (cup->uend != BEFORE_ENDFILE) {
00345                                 /*
00346                                  * If positioned after an endfile, and the file
00347                                  * does not support multiple endfiles, a write
00348                                  * is invalid.
00349                                  */
00350                                 if (!cup->umultfil && !cup->uspcproc) {
00351                                         errn    = FEWRAFEN;
00352                                         goto handle_exception;
00353                                 }
00354 
00355                                 /*
00356                                  * If a logical endfile record had just been 
00357                                  * read, replace it with a physical endfile 
00358                                  * record before starting the current data 
00359                                  * record.
00360                                  */
00361                                 if ((cup->uend == LOGICAL_ENDFILE) &&
00362                                     !(cup->uspcproc)) {
00363                                         struct ffsw     fst;    /* FFIO status block */
00364 
00365                                         if (XRCALL(cup->ufp.fdc, weofrtn)
00366                                             cup->ufp.fdc, &fst) < 0) {
00367                                                 errn    = fst.sw_error;
00368                                                 goto handle_exception;
00369                                         }
00370                                 }
00371 
00372                                 cup->uend       = BEFORE_ENDFILE;
00373                         }
00374 
00375                         if (cup->pnonadv && cup->uwrt == 0) {
00376                                 register int    offset;
00377                                 /*
00378                                  * A formatted or list-directed write statement
00379                                  * follows a nonadvancing read.  Switch the 
00380                                  * current line (record) from read to write 
00381                                  * mode.  Then backspace the file so the 
00382                                  * current record gets written back in place.
00383                                  */
00384 
00385                                 offset          = cup->ulineptr - cup->ulinebuf;
00386                                 cup->ulinemax   = offset + cup->ulinecnt;
00387                                 cup->ulinecnt   = offset;
00388                                 cup->uflshptr   = cup->ulinebuf;
00389                                 errn            = _unit_bksp(cup);
00390 
00391                                 if (errn != 0)
00392                                         goto handle_exception;
00393                         }
00394                         else if (cup->pnonadv == 0) {
00395                                 /* 
00396                                  * There is no current record (due to a prior
00397                                  * nonadvancing read or write).  Initialize
00398                                  * the empty line buffer.
00399                                  */ 
00400                                 cup->ulinecnt   = 0;    /* Num chars written */
00401                                 cup->ulinemax   = 0;    /* Highwater mark */
00402                                 cup->ulineptr   = cup->ulinebuf;
00403                                 cup->uflshptr   = cup->ulinebuf;
00404                         }
00405 
00406                         /*
00407                          * If list-directed write and there is a current 
00408                          * record, then truncate the current record at the
00409                          * current position and flush it if the current record 
00410                          * is already beyond uldwsize.
00411                          */
00412 
00413                         if (cup->pnonadv && cilist->fmt == CI_LISTDIR)
00414                                 errn    = _lw_after_nonadv(css, cup,
00415                                                         cup->uldwsize, 0);
00416 
00417                         css->u.fmt.endrec       = _sw_endrec;
00418                         cup->pnonadv            = css->u.fmt.nonadv;
00419                 }
00420         }
00421 
00422         if (errn != 0)
00423                 goto handle_exception;
00424 
00425         css->u.fmt.leftablim    = cup->ulineptr;        /* Set left tab limit */
00426         cup->uwrt               = 1;                    /* Set write mode */
00427 
00428 /*******************************************************************************
00429  *
00430  *      Data Transfer Section
00431  *
00432  ******************************************************************************/
00433 data_transfer:
00434 
00435         assert (cup != NULL);                   /* cup assumed non-NULL */
00436 
00437         errn    = _xfer_iolist(css, cup, iolist, xfunc);
00438 
00439         if (errn != 0)
00440                 goto handle_exception;
00441 
00442         if (! iolist->iollast)
00443                 return (IO_OKAY);
00444 
00445 /******************************************************************************
00446  *
00447  *      Statement Finalization Section
00448  *
00449  ******************************************************************************/
00450 finalization:
00451 
00452         /* Assertion */
00453         assert ( cup != NULL );
00454 
00455         /* If formatted I/O and no error complete processing */
00456 
00457 /*
00458  *      Complete formatted or list-directed output processing.
00459  */
00460 
00461         if (errn == 0) {
00462                 errn    = xfunc(css, cup, (void *) NULL, &__tip_null, 0L);
00463 
00464                 if (errn != 0)
00465                         goto handle_exception;
00466 
00467                 if (css->u.fmt.nonadv)
00468                         errn    = _nonadv_partrec(css, cup);
00469                 else
00470                         errn    = (*css->u.fmt.endrec)(css, cup, 1);
00471 
00472                 if (errn != 0)
00473                         goto handle_exception;
00474         }
00475 
00476         if (cilist->fmt != CI_LISTDIR)  /* If formatted */
00477                 if (css->u.fmt.freepfmt || css->u.fmt.freefmtbuf) {
00478 
00479                         /* If we allocated memory for a variable format, free it */
00480 
00481                         if (css->u.fmt.freepfmt && css->u.fmt.u.fe.pfmt != NULL)
00482                                 free(css->u.fmt.u.fe.pfmt);
00483                         /*
00484                          * If we allocated memory for a noncontiguous format,
00485                          * free it.
00486                          */
00487 
00488                         if (css->u.fmt.freefmtbuf &&
00489                             css->u.fmt.u.fe.fmtbuf != NULL)
00490                                 free(css->u.fmt.u.fe.fmtbuf);
00491                 }
00492 
00493         /*
00494          * If we allocated memory for an internal file, move
00495          * the output file from the temporary array to the
00496          * noncontiguous array and free the temporary array.
00497          */
00498 
00499         if (cilist->internal && css->u.fmt.tempicp != NULL) {
00500                 (void) _unpack_arry (css->u.fmt.tempicp, cilist->unit.dv);
00501                 free(css->u.fmt.tempicp);
00502         }
00503 
00504 out_a_here:
00505 
00506         /* Set IOSTAT variable to 0 if no error, >0 error code otherwise */
00507 
00508         if (cilist->iostat_spec != NULL)
00509                 *(cilist->iostat_spec)  = errn;
00510 
00511         STMT_END(cup, TF_WRITE, NULL, css);     /* Unlock unit */
00512 
00513         /* Return proper status */
00514 
00515         return (retval);
00516 
00517 /*
00518  *      We put the error handling stuff here to reduce its impact when
00519  *      no errors are generated.  If we jump here, errn is set to a nonzero
00520  *      error, eor, or endfile status code.
00521  */
00522 handle_exception:
00523         retval  = IO_ERR;
00524  
00525         if (! cilist->errflag && ! cilist->iostatflg)
00526                 _ferr(css, errn, errarg);
00527  
00528         if (cup == NULL)
00529                 goto out_a_here;
00530  
00531         goto finalization;
00532 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines