Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
opn.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/opn.c      92.3    06/23/99 16:08:16"
00039 
00040 #include <errno.h>
00041 #include <fortran.h>
00042 #include <liberrno.h>
00043 #include <string.h>
00044 #include <stdarg.h>
00045 #include <cray/nassert.h>
00046 #include "fmt.h"
00047 #include "fio.h"
00048 #include "f90io.h"
00049 
00050 #define OPNERR(n) { \
00051         errn    = n;    \
00052         goto opn_done;  \
00053 }
00054 
00055 #define SETSPEC(_specifier, _default_value, _error_code, _nval, _spec_list) \
00056  \
00057         if (_fcdtocp(_specifier) == NULL) \
00058                 a.o##_specifier = _default_value; \
00059         else if (! findmatch(_specifier, (int*) &a.o##_specifier, _nval \
00060                              _spec_list)) \
00061                 OPNERR(_error_code)
00062 
00063 #undef S
00064 #define S(_spec) , #_spec, OS_##_spec
00065 
00066 /*
00067  *      PASSED_ARG(x) is nonzero if argument x was passed.
00068  */
00069 
00070 #define ARGS_11         (4 + 7*sizeof(_fcd)/sizeof(long))
00071 #define ARGS_12         (4 + 8*sizeof(_fcd)/sizeof(long))
00072 #define ARGS_13         (4 + 9*sizeof(_fcd)/sizeof(long))
00073 #define ARGS_16         (7 + 9*sizeof(_fcd)/sizeof(long))
00074 #if _UNICOS
00075 #define PASSED_ARG(x)   (_numargs() >= x)
00076 #else
00077 #define PASSED_ARG(x)   (1)
00078 #endif
00079 
00080 
00081 static int      findmatch(_fcd fortstring, int *result, int nval, ...);
00082 
00083 /*
00084  *      $OPN - Fortran-77 runtime open routine.  Processes an OPEN statement.
00085  */
00086 
00087 #ifdef  _UNICOS
00088 #pragma _CRI duplicate __OPN as $OPN
00089 #endif
00090 
00091 #ifdef _CRAYMPP
00092 __OPN(
00093 _f_int  *unitn,
00094 _f_int  *iostat,
00095 int     *errf,
00096 ...
00097 )
00098 #else
00099 __OPN(
00100 _f_int  *unitn,
00101 _f_int  *iostat,
00102 int     *errf,
00103 _fcd    file,
00104 _fcd    status,
00105 _fcd    access,
00106 _fcd    form,
00107 _f_int  *recl,
00108 _fcd    blank,
00109 _fcd    position,
00110 _fcd    action_arg,
00111 _fcd    delim_arg,
00112 _fcd    pad_arg,
00113 int     unused1,        /* for a future CFT77 open specifier */
00114 int     unused2,        /* for a future CFT77 open specifier */
00115 int     isf90_arg)      /* =1 iff Fortran-90 OPEN */
00116 #endif
00117 {
00118         olist           a;              /* OPEN specifier list          */
00119         long            fstrlen;        /* Length of Fortran string     */
00120         int             errn;           /* IOSTAT error number          */
00121         int             error;          /* Error flag                   */
00122         unum_t          unum;           /* Fortran unit number          */
00123         _fcd            action;
00124         _fcd            delim;
00125         _fcd            pad;
00126         int             isf90;
00127         unit            *cup;           /* Pointer to unit table entry  */
00128         enum form_spec  formdef;
00129         struct fiostate cfs;
00130 
00131 #ifdef _CRAYMPP
00132         va_list args;
00133         _fcd    file;
00134         _fcd    status;
00135         _fcd    access;
00136         _fcd    form;
00137         _f_int  *recl;
00138         _fcd    blank;
00139         _fcd    position;
00140         int     unused1;        /* for a future CFT77 open specifier */
00141         int     unused2;        /* for a future CFT77 open specifier */
00142         int     isf90_arg;      /* =1 iff Fortran-90 OPEN */
00143 #endif
00144 
00145 /*
00146  *      The ACTION, DELIM, and PAD specifiers are supported by CFT77
00147  *      release 5.0 and later on CX/CEA systems, and by CFT77 release 6.0 and
00148  *      later on CRAY-2 systems.
00149  */
00150         action  = _cptofcd(NULL, 0);
00151         delim   = _cptofcd(NULL, 0);
00152         pad     = _cptofcd(NULL, 0);
00153 #ifdef _CRAYMPP
00154         va_start(args,errf);
00155         file    = va_arg(args, _fcd);
00156         status  = va_arg(args, _fcd);
00157         access  = va_arg(args, _fcd);
00158         form    = va_arg(args, _fcd);
00159         recl    = va_arg(args, _f_int *);
00160         blank   = va_arg(args, _fcd);
00161         position = va_arg(args, _fcd);
00162         
00163 #endif
00164         if (PASSED_ARG(ARGS_11)) {
00165 #ifdef _CRAYMPP
00166                 action  = va_arg(args, _fcd);
00167 #else
00168                 action  = action_arg;
00169 #endif
00170         }
00171         if (PASSED_ARG(ARGS_12)) {
00172 #ifdef _CRAYMPP
00173                 delim   = va_arg(args, _fcd);
00174 #else
00175                 delim   = delim_arg;
00176 #endif
00177         }
00178         if (PASSED_ARG(ARGS_13)) {
00179 #ifdef _CRAYMPP
00180                 pad     = va_arg(args, _fcd);
00181 #else
00182                 pad     = pad_arg;
00183 #endif
00184         }
00185 /*
00186  *      The isf90 argument is not passed from CFT77.
00187  */
00188         isf90   = 0;
00189 
00190         if (PASSED_ARG(ARGS_16)) {
00191 #ifdef _CRAYMPP
00192                 unused1 = va_arg(args, int);
00193                 unused2 = va_arg(args, int);
00194                 isf90   = va_arg(args, int);
00195 #else
00196                 isf90   = isf90_arg;
00197 #endif
00198         }
00199 #ifdef _CRAYMPP
00200         va_end(args);
00201 #endif
00202         errn    = 0;
00203 
00204         OPENLOCK();             /* prevent other OPENs or CLOSEs right now */
00205 
00206         unum    = *unitn;       /* UNIT= is required by compiler */
00207         a.ounit = unum;
00208 
00209         STMT_BEGIN(unum, 0, T_OPEN, NULL, &cfs, cup);   /* lock unit if open */
00210 
00211         if (!GOOD_UNUM(unum) || RSVD_UNUM(unum))
00212                 OPNERR(FEIVUNTO);
00213 
00214         a.oerr  = (errf || iostat) ? 1 : 0;     /* Catch errs if ERR | IOSTAT */
00215 
00216 /*
00217  *      Process FILE= and RECL= specifiers.
00218  */
00219         if (_fcdtocp(file) != NULL) {
00220                 a.ofile         = _fcdtocp(file);
00221                 a.ofilelen      = _fcdlen (file);
00222         }
00223         else {
00224                 a.ofile         = NULL;
00225                 a.ofilelen      = 0;
00226         }
00227 
00228         if (recl != NULL)
00229                 a.orecl = *recl;
00230         else
00231                 a.orecl = 0;    /* 0 means unspecified */
00232 
00233 /*
00234  *      Process remaining specifiers.
00235  *
00236  *      Specifier               Default                 Error Code
00237  *      Value List
00238  */
00239 
00240         SETSPEC(status,         OS_UNKNOWN,             FEOPSTAT,       5,
00241         S(OLD) S(NEW) S(SCRATCH) S(UNKNOWN) S(REPLACE));
00242 
00243 #if     !defined(__mips) && !defined(_LITTLE_ENDIAN)
00244         SETSPEC(access,         OS_SEQUENTIAL,          FEOPACCS,       2,
00245         S(DIRECT) S(SEQUENTIAL));
00246         SETSPEC(position,       OS_ASIS,                FEOPPOSN,       3,
00247         S(APPEND) S(ASIS) S(REWIND));
00248 #else   /* not __mips and not little endian */
00249         SETSPEC(access,         OS_SEQUENTIAL,          FEOPACCS,       4,
00250         S(DIRECT) S(SEQUENTIAL) S(KEYED) S(APPEND));
00251         if ((_fcdtocp(access) != NULL) && (a.oaccess == OS_OAPPEND)) {
00252                 if (_fcdtocp(position) != NULL) {
00253                         OPNERR(FEOPACCS);       /* Invalid ACCESS */
00254                 }
00255                 else if (isf90) {
00256                         OPNERR(FEOPACCS);       /* Invalid ACCESS */
00257                 }
00258                 else {
00259                         a.oposition     = OS_APPEND;
00260                         a.oaccess       = OS_SEQUENTIAL;
00261                 }
00262         }
00263         else {
00264         /* use POSITION= if ACCESS='APPEND' is not provided */
00265         SETSPEC(position,       OS_ASIS,                FEOPPOSN,       3,
00266         S(APPEND) S(ASIS) S(REWIND));
00267         }
00268 #endif  /* not __mips and not little endian */
00269 
00270         formdef = (a.oaccess == OS_SEQUENTIAL) ? OS_FORMATTED : OS_UNFORMATTED;
00271 
00272         SETSPEC(form,           formdef,                FEOPFORM,       4,
00273         S(UNFORMATTED) S(FORMATTED) S(BINARY) S(SYSTEM));
00274 
00275         SETSPEC(blank,          OS_NULL,                FEOPBLNK,       2,
00276         S(ZERO) S(NULL));
00277 
00278         SETSPEC(action,         OS_ACTION_UNSPECIFIED,  FEOPACTB,       3,
00279         S(READ) S(WRITE) S(READWRITE));
00280 
00281         SETSPEC(delim,          OS_NONE,                FEOPDLMB,       3,
00282         S(APOSTROPHE) S(QUOTE) S(NONE));
00283 
00284         SETSPEC(pad,            OS_YES,                 FEOPPADB,       2,
00285         S(YES) S(NO));
00286 
00287 /*
00288  *      Diagnose errors.
00289  */
00290 
00291         if (recl != NULL && a.orecl <= 0)
00292                 OPNERR(FEOPRECL);               /* Invalid RECL */
00293 
00294         if (recl == NULL && a.oaccess == OS_DIRECT)
00295                 OPNERR(FEOPRCRQ);               /* RECL required for direct */
00296 
00297         if (_fcdtocp(blank) != NULL && (a.oform == OS_UNFORMATTED ||
00298            a.oform == OS_BINARY || a.oform == OS_SYSTEM))
00299                 OPNERR(FEOPBKIV);               /* BLANK= invalid if unform. */
00300  
00301         if (_fcdtocp(delim) != NULL && (a.oform == OS_UNFORMATTED ||
00302            a.oform == OS_BINARY || a.oform == OS_SYSTEM))
00303                 OPNERR(FEOPDLMI);               /* DELIM invalid if unform. */
00304 
00305         if (_fcdtocp(pad) != NULL && (a.oform == OS_UNFORMATTED ||
00306            a.oform == OS_BINARY || a.oform == OS_SYSTEM))
00307                 OPNERR(FEOPPDIV);               /* PAD= invalid if unformatted*/
00308 
00309         if (_fcdtocp(position) != NULL && a.oaccess == OS_DIRECT)
00310                 OPNERR(FEOPPSIV);               /* POSITION invalid on direct */
00311 
00312 /*
00313  *      Done with OPEN specifiers.
00314  */
00315         if (OPEN_UPTR(cup) && cup->ufs == FS_AUX)
00316                 OPNERR(FEOPAUXT);       /* Unit is opened by AQ/MS/DR/WA IO */
00317 
00318         if (OPEN_UPTR(cup) &&
00319             (_fcdtocp(file) == NULL || (cup->ufnm != NULL &&
00320              strncmp(cup->ufnm, a.ofile, a.ofilelen) == 0))) {
00321                 /*
00322                  * A re-open of the same file occurs when the FILE= specifier
00323                  * is present and matches the name with which the file was
00324                  * originally opened, or if the FILE= specifier is absent
00325                  * (these are re-opens of the same file by definition).
00326                  *
00327                  * In this case, only a subset of the OPEN specifiers
00328                  * (the BLANK=, PAD=, and DELIM= specifiers) may be provided
00329                  * with values which are different from those currently in 
00330                  * effect.   Any new value passed with the BLANK=, PAD=, or
00331                  * DELIM= specifier will go into effect.
00332                  *
00333                  * An attempt to change the other OPEN specifers is an error.
00334                  */
00335 
00336                 if (_fcdtocp(status) != NULL && a.ostatus != cup->uostatus) {
00337                         if (a.ostatus == OS_NEW && cup->uostatus == OS_OLD) {
00338                                 OPNERR(FEOPNNEW); /* STATUS=NEW became OLD */
00339                         }
00340                         else
00341                                 OPNERR(FEOPCBNK); /* Can't change STATUS */
00342                 }
00343 
00344                 if (_fcdtocp(access) != NULL &&
00345                     ((a.oaccess == OS_SEQUENTIAL && cup->useq == 0 ) ||
00346                      (a.oaccess == OS_DIRECT     && cup->useq == 1)   ))
00347                         OPNERR(FEOPCBNK);       /* Can't change ACCESS */
00348 
00349                 if (_fcdtocp(form) != NULL &&
00350                     ((a.oform == OS_FORMATTED   && cup->ufmt == 0) ||
00351                      (a.oform == OS_UNFORMATTED && cup->ufmt == 1)   ))
00352                         OPNERR(FEOPCBNK);       /* Can't change FORM */
00353 
00354                 if (recl != NULL && a.orecl != cup->urecl)
00355                         OPNERR(FEOPCBNK);       /* Can't change RECL */
00356                         
00357                 if (_fcdtocp(position) != NULL && a.oposition != cup->uposition)
00358                         OPNERR(FEOPCBNK);       /* Can't change POSITION */
00359 
00360                 if (_fcdtocp(action) != NULL && a.oaction != cup->uaction)
00361                         OPNERR(FEOPCBNK);       /* Can't change ACTION */
00362 
00363                 /*
00364                  * Place into effect any new BLANK=, DELIM=, or PAD= specifier
00365                  * provided on the OPEN statement.
00366                  */
00367 
00368                 if (_fcdtocp(blank) != NULL)
00369                         cup->ublnk      = (a.oblank == OS_ZERO);
00370 
00371                 if (_fcdtocp(delim) != NULL)
00372                         cup->udelim     = a.odelim;     
00373 
00374                 if (_fcdtocp(pad)   != NULL)
00375                         cup->upad       = a.opad;       
00376         }
00377         else {
00378 
00379                 /*
00380                  * Open the unit.  If the unit is currently connected, it
00381                  * will be closed and then reopened for the new file.  
00382                  */
00383 
00384 #if     !defined(__mips) && !defined(_LITTLE_ENDIAN)
00385                 /*
00386                  * SGI's F77 and old F90 allowed open with status=NEW,
00387                  * OLD, or REPLACE without FILE specifier, so we continue
00388                  * to allow it on MIPS systems.
00389                  */
00390                 if (a.ostatus == OS_REPLACE && a.ofile == NULL)
00391                         OPNERR(FEOPFNRQ); /* FILE= required for 'REPLACE' */
00392 
00393                 if (a.ostatus == OS_OLD && a.ofile == NULL)
00394                         OPNERR(FEOPFNRQ); /* FILE= required for 'OLD' */
00395 
00396                 if (a.ostatus == OS_NEW && a.ofile == NULL)
00397                         OPNERR(FEOPFNRQ); /* FILE= required for 'NEW' */
00398 #endif
00399 #ifdef  _CRAYMPP
00400                 /*
00401                  * This check should be added for CX/CEA someday.
00402                  */
00403                 if (a.ostatus == OS_SCRATCH && a.ofile != NULL)
00404                         OPNERR(FEOPFNIV); /* FILE= should not be specified */
00405 #endif
00406 
00407 
00408                 /*
00409                  * We assume that _f_open does not change cfs.f_cu if
00410                  * the unit was already open.
00411                  */
00412                 errn    = _f_open(&cfs, &cup, &a, isf90);
00413         }
00414 
00415 /*
00416  *      Process results
00417  */
00418 opn_done:
00419         error   = (errn != 0) ? IO_ERR : IO_OKAY;
00420 
00421         if (iostat != NULL)
00422                 *iostat = errn;
00423         else
00424                 if (error != IO_OKAY && errf == 0)
00425                         if (errn == FEIVUNTO)
00426                                 _ferr(&cfs, errn, unum);
00427                         else
00428                                 _ferr(&cfs, errn);
00429 
00430         STMT_END(cup, T_OPEN, NULL, NULL);      /* unlock unit */
00431 
00432         OPENUNLOCK();
00433 
00434         return(CFT77_RETVAL(error));
00435 }
00436 
00437 /*
00438  *      _OPEN - Fortran-90 runtime open routine.  Processes an OPEN statement.
00439  */
00440 int
00441 _OPEN(struct open_spec_list *o)
00442 {
00443 /*
00444  *      Pass value of 1 in argument #16 to indicate that this is a Fortran-90
00445  *      OPEN.
00446  */
00447         assert ( o->version == 0 );
00448 
00449         return( __OPN(o->unit, o->iostat, (int*)o->err, o->file, o->status,
00450                      o->access, o->form, o->recl, o->blank, o->position,
00451                      o->action, o->delim, o->pad, (int)NULL, (int)NULL, 1) );
00452 }
00453 
00454 
00455 #if 0   /* ifdef it out.   Remove it when we're really sure it's not needed. */
00456 /*
00457  *      _OPN - Obsolete Fortran-90 runtime open routine.  Processes an OPEN 
00458  *      statement.
00459  */
00460 
00461 int
00462 _OPN(
00463 _f_int  *unitn,
00464 _f_int  *iostat,
00465 int     *errf,
00466 _fcd    file,
00467 _fcd    status,
00468 _fcd    access,
00469 _fcd    form,
00470 _f_int  *recl,
00471 _fcd    blank,
00472 _fcd    position,
00473 _fcd    action_arg,
00474 _fcd    delim_arg,
00475 _fcd    pad_arg)
00476 {
00477 /*
00478  *      Pass value of 1 in argument #16 to indicate that this is a Fortran-90
00479  *      OPEN.
00480  */
00481         return( __OPN(unitn, iostat, errf, file, status, access, form, recl, \
00482                      blank, position, action_arg, delim_arg, pad_arg,
00483                      NULL, NULL, 1) );
00484 }
00485 #endif /* 0 */
00486 
00487 /*
00488  *      findmatch - does a case-insensitive match of Fortran string fortstring 
00489  *      with a list of possible values.  The integer code of the matched 
00490  *      value is returned in *result.
00491  *
00492  *      Return value is 1 if a match was made, and 0 otherwise.
00493  */
00494 static int 
00495 findmatch(_fcd fortstring, int *result, int nval, ...)
00496 {
00497         va_list ap;
00498         char    *fstring;       /* Pointer to Fortran string    */
00499         long    fstrlen;        /* Length of Fortran string     */
00500         int     _string_cmp();  /* String compare routine in libu */
00501         char    *next_string;
00502         int     next_value;
00503         int     ret, i;
00504 
00505         va_start(ap, nval);
00506 
00507         fstring = _fcdtocp(fortstring);
00508         fstrlen = _fcdlen (fortstring);
00509 
00510         ret     = 0;            /* assume match not found */
00511 
00512         for (i = 0; i < nval; i++) {
00513                 next_string     = va_arg(ap, char *);
00514                 next_value      = va_arg(ap, int);
00515                 if (_string_cmp(next_string, fstring, fstrlen)) {
00516                         *result = next_value;
00517                         ret     = 1;
00518                         break;
00519                 }
00520         }
00521 
00522         va_end(ap);
00523 
00524         return(ret);
00525 }
00526 
00527 #if     defined(__mips) || defined(_LITTLE_ENDIAN)
00528 /*
00529  *      _OPEN - IRIX f77 -craylibs runtime open routine.
00530  *       Processes an OPEN statement.
00531  */
00532 int
00533 _OPENF77(struct open_spec_list *o)
00534 {
00535 /*
00536  *      Pass value of 0 in argument #16 to indicate that this
00537  *      is a Fortran-77 IRIX OPEN.
00538  */
00539         assert ( o->version == 0 );
00540 
00541         return( __OPN(o->unit, o->iostat, (int*)o->err, o->file, o->status,
00542                      o->access, o->form, o->recl, o->blank, o->position,
00543                      o->action, o->delim, o->pad, (int)NULL, (int)NULL, (int)NULL) );
00544 }
00545 #endif  /* mips  or little endian */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines