Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
wu90.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/wu90.c     92.3    08/02/99 10:38:48"
00039 
00040 #include <stdio.h>
00041 #include "fio.h"
00042 #include "f90io.h"
00043 
00044 /*
00045  *      _FWU    Called by compiled Fortran programs to process an unformatted
00046  *              write statement.  Each statement is processed by one or more
00047  *              calls to _FWU.  If any of the calls to _FWU for a particular
00048  *              write statement result in an error return code, the compiler
00049  *              ensures that subsequent calls to _FWU are suppressed.
00050  *
00051  *      Synopsis
00052  *
00053  *              int _FWU(       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 _FWU 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 _FWU(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;         /* _FWU return value    */
00084         register recn_t errarg;         /* Extra _ferr argument */
00085         register unum_t unum;           /* Unit number          */
00086         unit            *cup;           /* Unit table pointer   */
00087         FIOSPTR         css;            /* I/O statement state  */
00088 
00089 /*
00090  *      Assertions 
00091  */
00092         /* Validate that the size of *stck is large enough */
00093 
00094         assert ( cilist->stksize >= sizeof(struct fiostate)/sizeof(long) );
00095 
00096         /* Validate correct unformatted I/O info from compiler */
00097 
00098         assert ( cilist->uflag == CI_UNITNUM );
00099         assert ( cilist->eorflag == 0 );
00100         assert ( cilist->endflag == 0 );
00101 
00102 
00103         css     = stck;
00104         errn    = 0;
00105         errarg  = 0;
00106         retval  = IO_OKAY;
00107 
00108         if (iolist->iolfirst == 0) {
00109                 cup     = css->f_cu;
00110                 goto data_transfer;
00111         }
00112 
00113 /*******************************************************************************
00114  *
00115  *      Statement Initialization Section
00116  *
00117  ******************************************************************************/
00118 
00119         errf    = (cilist->errflag || cilist->iostatflg);
00120         unum    = *cilist->unit.wa;
00121         iost    = cilist->dflag ? T_WDU : T_WSU;
00122 
00123         STMT_BEGIN(unum, 0, iost, NULL, css, cup);
00124 
00125         if (cup == NULL) {              /* If not connected */
00126                 int     stat;   /* Status */
00127 
00128                 cup     = _imp_open(css, (cilist->dflag ? DIR : SEQ), UNF,
00129                                 unum, errf, &stat);
00130                 /*
00131                  * If the open failed, cup is NULL and stat contains
00132                  * the error number.
00133                  */
00134 
00135                 if (cup == NULL) {
00136                         errn    = stat;
00137                         goto handle_exception;
00138                 }
00139         }
00140 
00141         cup->f_lastiolist = NULL;       /* Indicates whether we are on the last item */
00142 
00143         /*
00144          * Record error processing options in the unit.  The _wrunf() etc.
00145          * routines will still use cup->uflag.
00146          */
00147         cup->uflag      = (cilist->errflag              ? _UIOSTF : 0) |
00148                           (cilist->iostat_spec != NULL  ?  _UERRF : 0);
00149 
00150         cup->uwrt       = 1;
00151         cup->ulastyp    = DVTYPE_TYPELESS;
00152 
00153         if (cilist->dflag) {    /* If direct access */
00154 
00155                 if (!cup->ok_wr_dir_unf)
00156                         errn    = _get_mismatch_error(errf, iost, cup, css);
00157                 else {
00158                         recn_t  recn;   /* Record number */
00159 
00160                         recn    = (recn_t) *cilist->rec_spec;
00161                         errarg  = recn;
00162                         errn    = _unit_seek(cup, recn, iost);
00163                 }
00164 
00165                 if (cup->udalast > cup->udamax) /* If new highwater mark */
00166                         cup->udamax     = cup->udalast;
00167 
00168                 cup->uend       = BEFORE_ENDFILE;
00169         }
00170         else {          /* Else sequential access */
00171 
00172                 if (!cup->ok_wr_seq_unf) {
00173                         errn    = _get_mismatch_error(errf, iost, cup, css);
00174                         goto handle_exception;
00175                 }
00176 
00177                 if (cup->uend != BEFORE_ENDFILE) {
00178                         struct ffsw     fst;    /* FFIO status block */
00179                         /*
00180                          * If positioned after an endfile, and the file does not
00181                          * support multiple endfiles, a write is invalid.
00182                          */
00183                         if (!cup->umultfil && !cup->uspcproc) {
00184                                 errn    = FEWRAFEN;     /* Write after endfile */
00185                                 goto handle_exception;
00186                         }
00187                         /*
00188                          * If a logical endfile record had just been read,
00189                          * replace it with a physical endfile record before
00190                          * starting the current data record.
00191                          */
00192                         if ((cup->uend == LOGICAL_ENDFILE) && !(cup->uspcproc)) {
00193                                 if (XRCALL(cup->ufp.fdc, weofrtn)cup->ufp.fdc, &fst) < 0)
00194                                         errn    = fst.sw_error;
00195                         }
00196 
00197                         cup->uend       = BEFORE_ENDFILE;
00198                 }
00199         }
00200 
00201         if (errn != 0)
00202                 goto handle_exception;
00203 
00204 /*******************************************************************************
00205  *
00206  *      Data Transfer Section 
00207  *
00208  ******************************************************************************/
00209 data_transfer:
00210 
00211         cup->f_lastwritten = 0;
00212         if (iolist->iollast && !cilist->dflag && cup->ublkd) {
00213                 cup->f_lastiolist = (long *)iolist + iolist->ioetsize;
00214         }
00215         errn    = _xfer_iolist(css, cup, iolist, _wrunf);
00216 
00217         if (errn != 0)
00218                 goto handle_exception;
00219 
00220         if (! iolist->iollast)
00221                 return(IO_OKAY);
00222 
00223 
00224 /*******************************************************************************
00225  *
00226  *      Finalization
00227  *
00228  ******************************************************************************/
00229 finalization:
00230 
00231         if (cup != NULL) {
00232                 cup->ulrecl     = cup->urecpos;
00233                 cup->urecpos    = 0;
00234                 cup->f_lastiolist = NULL;       /* reset */
00235         }
00236 
00237         if (errn != 0)
00238                 goto out_a_here;
00239 
00240         if (!cilist->dflag) {           /* Sequential Access */
00241                 if (cup->ublkd && cup->f_lastwritten == 0) {
00242                         register int    ret;    /* Return value */
00243                         int             dummy;  /* Unused word */
00244 
00245                         /* Terminate the record */
00246 
00247                         ret     = _fwwd(cup, &dummy, &__tip_null, FULL,
00248                                         (int *) NULL, (long *) NULL, &dummy);
00249 
00250                         if (ret == IOERR)
00251                                 errn    = errno;
00252                 }
00253         }
00254         else {                          /* Direct Access */
00255                 register long   bleft;  /* bytes unwritten in record */
00256 
00257                 bleft   = cup->urecl - (cup->ulrecl >> 3);
00258 
00259                 if (bleft > 0 && cup->udalast == cup->udamax) {
00260                         ssize_t         ret;    /* Return value */
00261                         long            zero = 0; /* Zero word */
00262                         long            *zbuf;  /* Buffer pointer */
00263                         struct ffsw     fst;    /* FFIO status block */
00264 
00265                         /*
00266                          * If this is the last direct access record in
00267                          * the file and a short record was written, be
00268                          * sure it is padded out to its full width as
00269                          * required by the Fortran standard.
00270                          */
00271 
00272                         zbuf    = &zero;        /* Assume short pad */
00273 
00274                         if (bleft > sizeof(long)) {
00275 
00276                                 zbuf    = (long *) malloc(bleft);
00277 
00278                                 if (zbuf == NULL) {
00279                                         errn    = FENOMEMY; /* No memory */
00280                                         goto handle_exception;
00281                                 }
00282                                 else    /* Clear record */
00283                                         (void) memset((void *) zbuf, 0, (size_t)bleft);
00284                         }
00285 
00286                         switch (cup->ufs) {     /* File structure */
00287 
00288                         case FS_FDC:
00289                                 ret     = XRCALL(cup->ufp.fdc, writertn)
00290                                                 cup->ufp.fdc, WPTR2BP(zbuf),
00291                                                 bleft, &fst, FULL, (int *)&zero);
00292 
00293                                 if (ret != bleft)
00294                                         errn    = fst.sw_error;
00295 
00296                                 break;
00297 
00298                         case STD:
00299                                 ret     = fwrite((void *) zbuf, 1, bleft,
00300                                                  cup->ufp.std);
00301 
00302                                 if (ret != bleft)
00303                                         errn    = errno;
00304 
00305                                 break;
00306 
00307                         default:
00308                                 errn    = FEINTUNK;     /* Deep weeds */
00309                                 break;
00310 
00311                         } /* switch */
00312 
00313                         /* Free any allocated space */
00314 
00315                         if (zbuf != &zero)
00316                                 free(zbuf);
00317                 }
00318         }
00319 
00320         if (errn != 0)
00321                 goto handle_exception;
00322 
00323 out_a_here:
00324 
00325         /* Set IOSTAT variable to 0 if no error, >0 error code otherwise */
00326  
00327         if (cilist->iostat_spec != NULL)
00328                 *(cilist->iostat_spec)  = errn;
00329 
00330         STMT_END(cup, TF_WRITE, NULL, css);     /* Unlock unit */
00331 
00332         /* Return proper status */
00333 
00334         return (retval);
00335 
00336 /*
00337  *      We put the error handling stuff here to reduce its impact when
00338  *      no errors are generated.  If we jump here, errn is set to a nonzero
00339  *      error, eor, or endfile status code.
00340  */
00341 handle_exception:
00342  
00343         retval  = IO_ERR;
00344  
00345         if (! cilist->errflag && ! cilist->iostatflg)
00346                 _ferr(css, errn, errarg);
00347  
00348         if (cup == NULL)
00349                 goto out_a_here;
00350  
00351         goto finalization;
00352 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines