Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
fio.h
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 /* USMID @(#) libf/include/fio.h        92.6    08/02/99 10:40:42 */
00038 
00039 #ifndef _FIO_H
00040 #define _FIO_H
00041 
00042 #include "fstats.h"
00043 #include <errno.h>
00044 #include <ffio.h>
00045 #include <fortran.h>
00046 #ifdef  _UNICOS
00047 #include <procstat.h>
00048 #endif
00049 #include <stdio.h>
00050 #include <sys/types.h>
00051 #if     defined(_UNICOS) || defined(_SOLARIS)
00052 #include <sys/iosw.h>
00053 #endif
00054 #include <cray/assign.h>
00055 #include <cray/fndc.h>
00056 #include <cray/format.h>
00057 #include <cray/fortio.h>        /* For unum_t and recn_t */
00058 #include <cray/mtlock.h>
00059 #include <cray/dopevec.h>
00060 #include <cray/nassert.h>
00061 #include <cray/portdefs.h>
00062 #ifdef  _CRAYMPP
00063 #include <signal.h>
00064 #endif
00065 
00066 /************************************************************************
00067  *
00068  * Debug control
00069  *
00070  ***********************************************************************/
00071 
00072 #ifdef  LIBDEBUG
00073 #define _ASSERT_ON      1               /* turn on assertion checking */
00074 #define DEBUG_MTIO      1               /* unconditional use of locks */
00075 #endif
00076 
00077 #define PRINT_TIP(tipa) {       \
00078         fprintf(stderr, "tip address = %o\n", tipa);            \
00079         fprintf(stderr, "  type90 = %d\n", (tipa)->type90);     \
00080         fprintf(stderr, "  type77 = %d\n", (tipa)->type77);     \
00081         fprintf(stderr, "  intlen = %d\n", (tipa)->intlen);     \
00082         fprintf(stderr, "  extlen = %d\n", (tipa)->extlen);     \
00083         fprintf(stderr, " cnvindx = %d\n", (tipa)->cnvindx);    \
00084         fprintf(stderr, "   count = %ld\n", (tipa)->count);     \
00085         fprintf(stderr, "  stride = %ld\n", (tipa)->stride);    \
00086         fprintf(stderr, "  elsize = %d\n", (tipa)->elsize);     \
00087         if ((tipa)->cnvindx) {                                  \
00088                 fprintf(stderr, " newfunc = %d\n", (tipa)->newfunc);\
00089                 fprintf(stderr, " cnvtype = %d\n", (tipa)->cnvtype);\
00090                 fprintf(stderr, " cnvfunc = %o\n", (tipa)->cnvfunc);\
00091         }                                                       \
00092 }
00093  
00094 /************************************************************************
00095  *
00096  * Constants
00097  *
00098  ***********************************************************************/
00099  
00100 #define HASH_SIZE       256     /* must be a power of 2 */
00101 
00102 #define STDIN_U         100     /* Special stdin unit */
00103 #define STDOUT_U        101     /* Special stdout unit */
00104 #define STDERR_U        102     /* Special stderr unit */
00105 
00106 #define RECMAX          1024    /* Default (initial) size of line buffer */
00107 #define RECMAXLDO       133     /* List-directed output line length */
00108  
00109 #define ERROR   1
00110 #define OK      0
00111 #define YES     1
00112 #define NO      0
00113  
00114 #define WRITE   1       /* write */
00115 #define READ    2       /* read */
00116 #define SEQ     3       /* sequential access */
00117 #define DIR     4       /* direct access */
00118 #define FMT     5       /* formatted */
00119 #define UNF     6       /* unformatted */
00120 #define EXT     7       /* external */
00121 #define INT     8       /* internal */
00122 
00123 /*
00124  *      Types of I/O statements
00125  */
00126                 /* flags folded into the statement code */
00127 
00128 #define TF_WRITE        001     /* write statement */
00129 #define TF_READ         002     /* read statement */
00130 #define TF_POS          004     /* statement which might reposition a file */
00131 #define TF_FMT          010     /* formatted read or write statement */
00132 
00133                 /* statement codes */
00134 
00135 #define T_WSF           (00100 | TF_WRITE | TF_POS | TF_FMT             )
00136 #define T_WSU           (00200 | TF_WRITE | TF_POS                      )
00137 #define T_WDF           (00300 | TF_WRITE | TF_POS | TF_FMT             )
00138 #define T_WDU           (00400 | TF_WRITE | TF_POS                      )
00139 #define T_WLIST         (00500 | TF_WRITE | TF_POS                      )
00140 #define T_WNL           (00600 | TF_WRITE | TF_POS                      )
00141 
00142 #define T_RSF           (00700 | TF_READ  | TF_POS | TF_FMT             )
00143 #define T_RSU           (01100 | TF_READ  | TF_POS                      )
00144 #define T_RDF           (01200 | TF_READ  | TF_POS | TF_FMT             )
00145 #define T_RDU           (01300 | TF_READ  | TF_POS                      )
00146 #define T_RLIST         (01400 | TF_READ  | TF_POS                      )
00147 #define T_RNL           (01500 | TF_READ  | TF_POS                      )
00148 
00149 #define T_BUFOUT        (01600            | TF_POS                      )
00150 #define T_BUFIN         (01700            | TF_POS                      )
00151 
00152 #define T_OPEN          (02000                                          )
00153 #define T_REWIND        (02100            | TF_POS                      )
00154 #define T_BACKSPACE     (02200            | TF_POS                      )
00155 #define T_ENDFILE       (02300            | TF_POS                      )
00156 #define T_CLOSE         (02400                                          )
00157 #define T_INQF          (02500                                          )
00158 #define T_INQU          (02600                                          )
00159 
00160 #define T_MISC          (02700            | TF_POS                      )
00161 
00162 #define T_GETPOS        (03000                                          )
00163 #define T_SETPOS        (03100            | TF_POS                      )
00164 #define T_LENGTH        (03200                                          )
00165 #define T_UNIT          (03300                                          )
00166 #define T_TAPE          (03400            | TF_POS                      )
00167 #define T_FLUSH         (03500                                          )
00168 #define T_NUMBLKS       (03600                                          )
00169 
00170 /*
00171  *      Fortran 77 data types 
00172  */
00173 
00174 #define DT_NONE         0       /* Typeless                             */
00175 #define DT_INT          1       /* Integer                              */
00176 #define DT_REAL         2       /* Real                                 */
00177 #define DT_DBLE         3       /* Double                               */
00178 #define DT_CMPLX        4       /* Complex                              */
00179 #define DT_LOG          5       /* Logical                              */
00180 #define DT_CHAR         6       /* Character                            */
00181 #define DT_SINT         7       /* Short integer                        */
00182 #define DT_DBLCOM       8       /* Double complex (intended for fortran
00183                                    90 support, but never used)          */
00184 #define DT_MAX          9       /* Number of data types                 */
00185 
00186 /*
00187  *      Fortran I/O buffer size constants.
00188  */
00189 
00190 #define BLKSIZE         4096    /* Bytes in a 512-word disk block       */
00191 #define SECTOR          BLKSIZE /* Temporary synonym for BLKSIZE        */
00192 #ifdef  _UNICOS
00193 #define DEF_BIN_BS      _VALUE(_def_bin_bs)
00194 #define DEF_SBIN_BS     _VALUE(_def_sbin_bs)
00195 #else
00196 #define DEF_BIN_BS      1
00197 #define DEF_SBIN_BS     1
00198 #endif
00199 
00200 #ifdef  _CRAYMPP
00201 /* Values used when running on mppsim in user virtual mode */
00202 #define DEF_BINSIM_BS   1
00203 #define DEF_SBINSIM_BS  1
00204 #endif
00205 
00206 #define DFBUFSZ         8       /* Direct formatted buffer size         */
00207 #define SFBUFSZ         8       /* Sequential formatted buffer size     */
00208 #if     defined(__mips) || defined(_LITTLE_ENDIAN)
00209                                 /* We choose this direct unformatted */
00210                                 /* buffer size to match MIPS f77 */
00211 #define DUBUFSZ         16      /* Direct unformatted buffer size       */
00212 #else
00213 #define DUBUFSZ         8       /* Direct unformatted buffer size       */
00214 #endif
00215 #define SUBUFSZ         48      /* Sequential unformatted buffer size   */
00216 
00217 #define DEFAULT_NBUF    4       /* Default no. of direct-access buffers */
00218 
00219 /* Temporary buffer size for packing/unpacking line buffers             */
00220 
00221 #ifdef  _MAXVL
00222 #define TBUFSZW         _MAXVL
00223 #else
00224 #define TBUFSZW         36
00225 #endif
00226 
00227 #define TBUFSZB (TBUFSZW * sizeof(long))
00228 
00229 #define CHBUFSIZE       (1024 * sizeof(long))   /* chunking buf size (bytes) */
00230 
00231 /*
00232  *      CFT77 return status values (set in S3 on return)
00233  */
00234 
00235 #define IO_OKAY 0       /* Normal completion    */
00236 #define IO_ERR  1       /* Error status         */
00237 #define IO_END  2       /* End status           */
00238 
00239 /*
00240  *      Fortran I/O completion status
00241  */
00242 
00243 #define CNT     1       /* Count exhausted              */
00244 #define EOR     0       /* End-of-record                */
00245 #ifndef EOF
00246 #define EOF     -1      /* End-of-file                  */
00247 #endif
00248 #define EOD     -2      /* End-of-data                  */
00249 
00250 #define IOERR   -1      /* Fortran I/O error            */
00251 
00252 /*
00253  *      Fortran I/O request modes
00254  */
00255 
00256 #define PARTIAL 0       /* Partial record I/O           */
00257 #define FULL    1       /* Full record I/O              */
00258 
00259 /*
00260  *      Codes for open processing
00261  */
00262 
00263 enum status_spec        { OS_UNKNOWN = 1, OS_OLD, OS_NEW, OS_SCRATCH,
00264                           OS_REPLACE };
00265 #if     defined(__mips) || defined(_LITTLE_ENDIAN)
00266 enum access_spec        { OS_SEQUENTIAL = 1, OS_DIRECT, OS_OAPPEND, OS_KEYED };
00267 #else
00268 enum access_spec        { OS_SEQUENTIAL = 1, OS_DIRECT };
00269 #endif
00270 enum form_spec          { OS_FORMATTED = 1, OS_UNFORMATTED, OS_BINARY, OS_SYSTEM };
00271 enum blank_spec         { OS_NULL = 1, OS_ZERO };
00272 enum position_spec      { OS_REWIND = 1, OS_ASIS, OS_APPEND };
00273 enum action_spec        { OS_ACTION_UNSPECIFIED = 0, OS_READ = 1, OS_WRITE = 2,
00274                           OS_READWRITE = (OS_READ | OS_WRITE) };
00275 enum delim_spec         { OS_NONE = 1, OS_QUOTE, OS_APOSTROPHE };
00276 enum pad_spec           { OS_NO = 1, OS_YES };
00277 
00278 /*
00279  *      Codes for close processing
00280  */
00281 
00282 #define CLST_UNSPEC     0       /* STATUS= unspecified          */
00283 #define CLST_KEEP       1       /* STATUS='KEEP'                */
00284 #define CLST_DELETE     2       /* STATUS='DELETE'              */
00285 
00286 /************************************************************************
00287  *
00288  * Constants assigned to unit table fields.
00289  *
00290  ***********************************************************************/
00291 /*
00292  * The following flags in 'uflag' are used within a READ/WRITE statement
00293  * and are cleared at finalization.
00294  */
00295 
00296 #define _UERRF   01             /* ERR= specified */
00297 #define _UEORF   02             /* EOR= specified */
00298 #define _UENDF   04             /* END= specified */
00299 #define _UIOSTF 010             /* IOSTAT= specified */
00300 
00301 #define _UERRC  020             /* ERR condition */
00302 #define _UEORC  040             /* EOR condition with ADVANCE='NO' */
00303 #define _UENDC 0100             /* ENDFILE condition */
00304 
00305 /************************************************************************
00306  *
00307  * The CVOLATILE macro must be defined to expand to "volatile" on 
00308  * architectures like CRAY TS which support threading and where storing to 
00309  * memory might render another processor's cache invalid.
00310  *
00311  * On other cache-coherent architectures like Sparc we expand CVOLATILE to
00312  * "volatile" for conceptual correctness, and because there is no negative
00313  * performance impact.
00314  *
00315  * CVOLATILE is not expanded to "volatile" on T3D systems because no 
00316  * threading is supported and there would be a negative performance impact.
00317  *
00318  *
00319  * This keyword must be added to any globally accessed field or variable which 
00320  * might be loaded prior to obtaining a lock (lock routines always render
00321  * the cache coherent) and the field or dataword is not read-only.  This 
00322  * comes up for locked data areas which are dynamically allocated on the 
00323  * heap and are then initialized once and read-only from thence onward.  The 
00324  * fact that the data item previously was in the heap means that some processor
00325  * might have previously used the data area and then deallocated it with
00326  * free(3).  That processor might have a stale data cache entry assigned
00327  * to the data word.
00328  *
00329  ***********************************************************************/
00330 
00331 #ifndef _CRAYT3D
00332 
00333 #define CVOLATILE volatile
00334 
00335 #else
00336 
00337 #define CVOLATILE 
00338 
00339 #endif
00340 
00341 /************************************************************************
00342  *
00343  * Structure and Typedef Definitions
00344  *
00345  ***********************************************************************/
00346 
00347 typedef short           s_flag;
00348 typedef long            ftnlen;
00349 typedef _f_comp8        _gen_complex;   /* Complex of largest supported kind */
00350 
00351 /* FP is a union which may contain a variety of pointer types */
00352 
00353 typedef union {
00354         FILE            *std;
00355         struct fdinfo   *fdc;
00356 } FP;
00357 
00358 /*
00359  *      Define the basic, or smallest, container for a noncharacter datum.
00360  */
00361 
00362 #if     defined(__mips) || defined(_LITTLE_ENDIAN)
00363 typedef _f_int1 bcont;          /* basic container is a half word */
00364 #elif   !defined(_WORD32) && (defined(_F_INT4) || defined(_F_REAL4))
00365 typedef short bcont;            /* basic container is a half word */
00366 #else
00367 typedef long bcont;             /* basic container is a word */
00368 #endif
00369 
00370 /*
00371  *      Fortran unit structure
00372  *
00373  *      UNIT_HEADER is the offset to the start of the part of the unit table 
00374  *      which is initialized by _init_unit().
00375  */
00376 
00377 #define UNIT_HEADER     (offsetof(unit, auxlockp))
00378 
00379 typedef struct unit_s {
00380 
00381 /******************************************************************************
00382  *                                                                            *
00383  *      Hash Table Fields Section                                             *
00384  *                                                                            *
00385  *      Fields used to manage the hash table of units.                        *
00386  *                                                                            *
00387  *      Fields in this section must be at the start of the structure.         *
00388  *      This is to help _init_unit() efficiently initialize all the other     *
00389  *      fields.   All these fields (except uiolock) must never be reset       *
00390  *      because they are needed to maintain a coherent hash table of units.   *
00391  *                                                                            *
00392  *      The CVOLATILE keyword is added to hashlink, uid, private, and utid    *
00393  *      because these fields are loaded by _get_cup() prior to entering a     *
00394  *      critical region.                                                      *
00395  *                                                                            *
00396  ******************************************************************************/
00397 
00398         struct unit_s * CVOLATILE hashlink;     /* Next unit in hash chain    */
00399         CVOLATILE unum_t        uid;            /* Unit number, -1 if internal*/
00400                                                 /* unit                       */
00401         CVOLATILE int           private;        /* 1 if private, 0 if global  */
00402         CVOLATILE int           utid;           /* Tskid of owner of priv unit*/
00403         plock_t uiolock;                        /* Unit lock                  */
00404 
00405 /******************************************************************************
00406  *                                                                            *
00407  *      Connection Properties Section                                         *
00408  *                                                                            *
00409  *      Fields describing unchanging properties of the connection.            *
00410  *                                                                            *
00411  ******************************************************************************/
00412 
00413         plock_t *auxlockp;      /* Pointer to optional 2nd lock (stdio) */
00414         int     ufs;            /* Describes the I/O processing method  */
00415         char    *ufnm;          /* File name or alias                   */
00416         ino_t   uinode;         /* Unique file inode identifier         */
00417         dev_t   udevice;        /* Unique file device number            */
00418         char    *alfnm;         /* Actual file name                     */
00419         long    urecl;          /* RECL value; 0 if absent on sequential*/
00420         int     usysfd;         /* File descriptor.  A value of -1      */
00421                                 /* usually indicates no 'normal' file   */
00422                                 /* is associated with the unit.         */
00423         long    uflagword;      /* Returned flag word from FC_GETINFO   */
00424         int     ucharset;       /* Foreign character set                */
00425         int     unumcvrt;       /* Foreign numeric conversion           */
00426         int     ualignmask;     /* 0 or __fndc_align[cup->unumcvrt]->gran - 1*/
00427         struct _dal_s   ualign; /* FDC alignment information            */
00428 
00429         unsigned
00430                 uostatus:3,     /* STATUS value (enum status_specifier) */
00431                 uposition:3,    /* POSITION value (enum position_specifier) */
00432                 uaction :3,     /* ACTION value (enum action_specifier) */
00433                 udelim  :3,     /* DELIM value (enum delim_spec)        */
00434                 upad    :3,     /* PAD value (enum pad_specifier)       */
00435                 utrunc  :1,     /* 1 if trunc. after sequential write   */
00436                 ubmx    :1,     /* 1 if -s bmx selected by user         */
00437                 usysread:1,     /* 1 if file has system read permission */
00438                 usyswrite:1,    /* 1 if file has system write permission*/
00439                 useek   :1,     /* 1 if backspace or use direct access  */
00440                 ublkd   :1,     /* 1 if record blocking is present      */
00441                 ublnk   :1,     /* 1 if BLANK='ZERO' on open            */
00442                 ufmt    :1,     /* 1 if FORM='FORMATTED'                */
00443                 useq    :1,     /* 1 if ACCESS='SEQUENTIAL'             */
00444                 uscrtch :1,     /* 1 if file is a scratch or temp file  */
00445                 unlinked:1,     /* 1 if file has been unlinked          */
00446                 usnglink:1,     /* 1 if file is not a linked file       */
00447                 umultfil:1,     /* 1 if multiple endfile records allowed*/
00448                 uft90   :1,     /* 0/1 if Fortran 77/90 compatible      */
00449                 umultup :1,     /* 1 if -m on permits multiple access   */
00450                 utmpfil :1,     /* 1 if assigned with -t                */
00451                 ok_wr_seq_fmt:1,/* 1 if seq fmt write is supported      */
00452                 ok_wr_seq_unf:1,/* 1 if seq unfmted write is supported  */
00453                 ok_wr_dir_fmt:1,/* 1 if dir fmt write is supported      */
00454                 ok_wr_dir_unf:1,/* 1 if dir unfmted write is supported  */
00455                 ok_rd_seq_fmt:1,/* 1 if seq fmt read is supported       */
00456                 ok_rd_seq_unf:1,/* 1 if seq unfmted read is supported   */
00457                 ok_rd_dir_fmt:1,/* 1 if dir fmt read is supported       */
00458                 ok_rd_dir_unf:1,/* 1 if dir unfmted read is supported   */
00459                 ufcompat:3,     /* 0/1/2/3 if cf77/cf90/irxf77/irxf90 compat */
00460                 ufcomsep:1,     /* 1 no comma-separated list-dir output */
00461                 ufunilist:1,    /* 1 if not unicos list-dir output      */
00462                 ufcomplen:1,    /* 1 if compressed leng list-dir output */
00463                 ufrptcnt:1,     /* 1 no repeat count in list-dir output */
00464                 ufnl_skip:1,    /* 1 if skipping mismatched nl grp name */
00465                 ufnegzero:1,    /* 1 if skip minus sign in fmt write of -0.0 */
00466                 ukeyed  :1,     /* 1 if ACCESS='KEYED'                  */
00467                 ubinary :1,     /* 1 if FORM='BINARY'                   */
00468                 usystem :1;     /* 1 if FORM='SYSTEM'                   */
00469 
00470 /******************************************************************************
00471  *                                                                            *
00472  *      Unit State Section                                                    *
00473  *                                                                            *
00474  *      Fields which contain state information which must be remembered       *
00475  *      from one I/O statement to the next.                                   *
00476  *                                                                            *
00477  ******************************************************************************/
00478 
00479         FP      ufp;            /* Low-level file pointer               */
00480 
00481         struct repdata *urepdata;/* Repdata structure for list read     */
00482 
00483         int     upfcstsz;       /* Size of parsed format count stack    */
00484         int     *upfcstk;       /* Pointer to parsed format count stack */
00485 
00486         unsigned
00487                 unitchk :1,     /* 1 if UNIT was called since last BUFFER I/O */
00488                 urecmode:1,     /* FULL or PARTIAL record mode for buffer I/O */
00489                 uerr    :1,     /* 1 if error on last buffer in/out     */
00490                 uwrt    :1,     /* 1 if last io was write               */
00491                 pnonadv :1,     /* 1 if ADVANCE='NO' on prev I/O        */
00492                 uspcproc:1;     /* 1 if in EOV special processing (tapes) */
00493 
00494         /*
00495          * The uend field is used to track a file's position relative to
00496          * a final endfile record.  A 'logical endfile' record exists at
00497          * the end of any sequential file which does not have a physical
00498          * endfile preceding the EOD.
00499          */
00500 
00501         enum {
00502             BEFORE_ENDFILE   = 0, 
00503             PHYSICAL_ENDFILE = 1, 
00504             LOGICAL_ENDFILE  = 2
00505         }       uend    :3;     /* 0 if not positioned past a final     *
00506                                  * endfile record.  PHYSICAL_ENDFILE if *
00507                                  * positioned after a logical endfile   *
00508                                  * record.  LOGICAL_ENDFILE if          *
00509                                  * positioned after a logical endfile   *
00510                                  * record.                              */
00511 
00512         long    uwaddr;         /* Current word address for -s bin      */
00513 
00514         int64   ulrecl;         /* Length in bits of previous BUFFER IN,*
00515                                  * BUFFER OUT, READ, or WRITE.  Used for*
00516                                  * the LENGTH function.                 */
00517         enum {
00518             ASYNC_NOTOK  = 0,
00519             ASYNC_OK     = 1,
00520             ASYNC_ACTIVE = 2
00521         }       uasync;         /* > 0 if async permitted or active     */
00522 
00523         struct ffsw uffsw;      /* Status word for asynchronous I/O     */
00524 
00525         union stat_ntry *ftstat;/* Pointer to Fortran statistics packet */
00526 
00527         long    ufbitpos;       /* Bit position in file for PURE files  */
00528 
00529         /* Direct access */
00530 
00531         recn_t  udamax;         /* Largest record number on file        */
00532         recn_t  udalast;        /* Last record number read or written   */
00533 
00534         /* Formatted, list-directed, or namelist I/O */
00535 
00536 /******************************************************************************
00537  *      Line buffer conventions (disregard at your own peril):                *
00538  *                                                                            *
00539  *      ulinebuf        Set in OPEN/CLOSE processing and--possibly--during    *
00540  *                      I/O statement initialization.                         *
00541  *                                                                            *
00542  *      ulineptr        Pointer to current position in line buffer.           *
00543  *                                                                            *
00544  *      uflshptr        Pointer to unflushed part of line buffer.  This is    *
00545  *                      used only for sequential writes.                      *
00546  *                                                                            *
00547  *      ulinecnt        On output (writing), this is the offset or current    *
00548  *                      position in the line buffer; note that ulineptr is    *
00549  *                      normally defined as &ulinebuf[ulinecnt].  On input    *
00550  *                      (reading), this is the number of characters left in   *
00551  *                      the line buffer.                                      *
00552  *                                                                            *
00553  *      ulinemax        On output (writing), this is the highwater mark in    *
00554  *                      the line buffer (e.g., on a tab-left operation,       *
00555  *                      ulineptr and ulinecnt are updated but ulinemax is     *
00556  *                      unchanged).  Note that for output paths that do not   *
00557  *                      support tabbing (list-directed output, for example),  *
00558  *                      ulinemax is used in lieu of ulinecnt, and ulinecnt    *
00559  *                      is undefined.  This field is never used on input      *
00560  *                      (reading).                                            *
00561  *                                                                            *
00562  *      urecsize        Minimum physical size of line buffer and record size  *
00563  *                      (RECL) of current record.  ulinemax must NEVER be     *
00564  *                      larger than this value; ulinecnt may exceed it after  *
00565  *                      a tab-right operation.                                *
00566  *                                                                            *
00567  *      uldwsize        Analogue of urecsize for list-directed writes only.   *
00568  *                                                                            *
00569  *      unmlsize        Analogue of urecsize for namelist writes only.        *
00570  *                                                                            *
00571  ******************************************************************************/
00572 
00573         long    *ulinebuf;      /* Unpacked line buffer                 */
00574         long    *ulineptr;      /* Current position in line buffer      */
00575         long    *uflshptr;      /* Unflushed part of line buffer        */
00576         long    ulinemax;       /* Max position in line buffer to write */
00577         long    ulinecnt;       /* Character count in line buffer       */
00578         long    urecsize;       /* Length of line buffer (characters)   */
00579         long    uldwsize;       /* Length for list-directed writes      */
00580         long    unmlsize;       /* Length for namelist writes           */
00581 
00582 /******************************************************************************
00583  *                                                                            *
00584  *      Statement State Section                                               *
00585  *                                                                            *
00586  *      Fields which contain the state of the current I/O statement.          *
00587  *                                                                            *
00588  ******************************************************************************/
00589 
00590         _f_int  *uiostat;       /* IOSTAT parameter address for cf77    */
00591         long    uflag;          /* Flag word used by interface routines */
00592         unsigned
00593                 ueor_found:1,   /* Found eor already on read            */
00594                 f_lastwritten:1;        /* 1 if we already terminated   */
00595                                         /* the record                   */
00596                                 /* Only those routines that care about  */
00597                                 /* lastiolist currently look at this    */
00598         void    *f_lastiolist;  /* Set in some of the compiler-library  */
00599                                 /* interface routines.  If              */
00600                                 /* iolist_header->iollast is set, this  */
00601                                 /* can be set to the address of the end */
00602                                 /* of the iolist; otherwise NULL.       */
00603 
00604         /* Unformatted I/O */
00605 
00606         int64   urecpos;        /* Bit position in current record       */
00607         int     ulastyp;        /* Type of previous I/O list item       */
00608 
00609 } unit;
00610 
00611 /*
00612  *      Fortran unit hash table structure.  A hash table consists of an
00613  *      array of these structures.  The units in each hash chain are
00614  *      linked together via the "hashlink" field in the unit table.
00615  *
00616  */
00617 typedef CVOLATILE struct {
00618         unit    *ulist; /* Unit at head of hash chain   */
00619 } unit_htable;
00620 
00621 /*
00622  *      The per-task I/O statement state structure
00623  */
00624 
00625 struct fiostate {
00626         unit    *f_cu;          /* Current unit                         */
00627         long    f_iostmt;       /* Current I/O statement type           */
00628         unum_t  f_curun;        /* Current unit number                  */
00629         s_flag  f_intflg;       /* 1 if internal file                   */
00630         long    f_rtbgn;        /* RT value at start of I/O statement   */
00631         unsigned f_shrdput:1;   /* 1 if we need to do a shmem_wait_put  */
00632                                 /* Should be set only on MPP systems    */
00633 
00634         union iostate {
00635         /*
00636          * Unformatted I/O
00637          */
00638         struct unfstate {
00639         int     recpos;         /* Bit position in current record       */
00640         int     lastyp;         /* Type of previous I/O list item       */
00641         } unf;
00642 
00643         /*
00644          * Formatted/list-directed I/O
00645          */
00646         struct fmtstate {
00647         int     (*endrec)(
00648                         struct fiostate *css,
00649                         unit            *cup,
00650                         int             count);
00651                                 /* Record processing function           */
00652 
00653         long    *leftablim;     /* Left tab limit for current statement */
00654         char    *icp;           /* Internal I/O character pointer       */
00655         char    *tempicp;       /* Ptr to a free-able copy of internal file */
00656         int     icl;            /* Internal I/O character length        */
00657         int     iiae;           /* Number of internal array elements    */
00658                                 /* Negative if pre-5.0 code             */
00659                                 /* Zero or greater if 5.0 code or later */
00660 
00661         unsigned
00662                 freefmtbuf:1,   /* 1 if temporary unparsed format to be freed */
00663                 freepfmt:1,     /* 1 if parsed format to be freed       */
00664                 lcomma  :1,     /* List-directed read comma flag        */
00665                 blank0  :1,     /* 1 if blanks currently treated as nulls */
00666                 cplus   :1,     /* 1 if + sign is printed for pos numbers */
00667                 nonl    :1,     /* 1 if no new line, 0 if newline       */
00668                 nonadv  :1,     /* 1 if ADVANCE='NO'                    */
00669                 slash   :1;     /* 1 if list input encountered a slash  */
00670 
00671         union {
00672 
00673         struct {
00674                 char    *fmtbuf;        /* Pointer to unparsed (ASCII) format */
00675                 int     fmtcol;         /* Current position in unparsed format*/
00676                 int     fmtlen;         /* Length of unparsed format    */
00677                 int     fmtnum;         /* Fortran statement label of format */
00678                 fmt_type *pfmt;         /* Pointer to parsed format     */
00679                 fmt_type *pfcp;         /* Parsed format current position */
00680                 int     *pftocs;        /* Current top of count stack   */
00681 
00682                 int     charcnt;        /* Character count for SIZE on read */
00683                 long    scale;          /* Current scale factor         */
00684         } fe; /* formatted editing */
00685 
00686         /*
00687          * The "le" structure contains state of the current list-directed
00688          * output statement.  repcnt, value/copy, elsize, and type all
00689          * are used to save the last output value processed.   We 
00690          * defer printing of output items until we know that we have 
00691          * no more opportunity to combine consecutive equivalent values
00692          * into one value with a repeat count.
00693          *
00694          * The ndchar bit is set if the last *printed* value was 
00695          * non-delimited character.  This must be remembered because it 
00696          * affects the choice of value separator used.
00697          */
00698         struct {
00699             union {
00700                 long    value[4];       /* Repeated output value        */
00701                 void    *copy;          /* Pointer to copy of output value */
00702             } u;
00703             int         repcnt;         /* Number of repeated output values */
00704             int         elsize;         /* Byte size of repeated value  */
00705             ftype_t     type    :8;     /* Data type of repeated value  */
00706             unsigned    ndchar  :1;     /* 1 if prev type was nondelim char */
00707             unsigned    item1   :1;     /* 1 if first item in I/O list  */
00708             unsigned    ldwinit :1;     /* 1 if first call to _ld_write */
00709           } le; /* list-directed editing */
00710 
00711         } u;
00712 
00713         } fmt;
00714     } u;
00715 };
00716 
00717 /*      FIOSPTR - synonym for (struct fiostate *) */
00718 
00719 typedef struct  fiostate        *FIOSPTR;
00720 
00721 /*      olist - for open processing */
00722 
00723 typedef struct {
00724         s_flag                  oerr;
00725         _f_int                  ounit;
00726         char                    *ofile;
00727         ftnlen                  ofilelen;
00728         enum status_spec        ostatus;
00729         enum access_spec        oaccess;
00730         enum form_spec          oform;
00731         _f_int                  orecl;
00732         enum blank_spec         oblank;
00733         enum position_spec      oposition;
00734         enum action_spec        oaction; 
00735         enum delim_spec         odelim; 
00736         enum pad_spec           opad;
00737 } olist;
00738 
00739 /*      cllist - for close processing */
00740  
00741 typedef struct {
00742         s_flag  cerr;
00743         _f_int  cunit;
00744         char    *csta;
00745 } cllist;
00746 
00747 /*      inlist - for INQUIRE processing */
00748 
00749 typedef struct {
00750         s_flag  inerr;
00751         _f_int  inunit;
00752         char    *infile;
00753         ftnlen  infilen;
00754         _f_log  *inex;  /* parameters in standard's order */
00755         _f_log  *inopen;
00756         _f_int  *innum;
00757         _f_log  *innamed;
00758         char    *inname;
00759         ftnlen  innamlen;
00760         char    *inacc;
00761         ftnlen  inacclen;
00762         char    *inseq;
00763         ftnlen  inseqlen;
00764         char    *indir;
00765         ftnlen  indirlen;
00766         char    *infmt;
00767         ftnlen  infmtlen;
00768         char    *inform;
00769         _f_int  informlen;
00770         char    *inunf;
00771         ftnlen  inunflen;
00772         _f_int  *inrecl;
00773         _f_int  *innrec;
00774         char    *inblank;
00775         ftnlen  inblanklen;
00776         char    *inposit;               /* POSITION specifier pointer   */
00777         ftnlen  inpositlen;             /* POSITION specifier length    */
00778         char    *inaction;              /* ACTION specifier pointer     */
00779         ftnlen  inactonlen;             /* ACTION specifier length      */
00780         char    *inread;                /* READ specifier pointer       */
00781         ftnlen  inreadlen;              /* READ specifier length        */
00782         char    *inwrite;               /* WRITE specifier pointer      */
00783         ftnlen  inwritelen;             /* WRITE specifier length       */
00784         char    *inredwrit;             /* READWRITE specifier pointer  */
00785         ftnlen  inrdwrtlen;             /* READWRITE specifier length   */
00786         char    *indelim;               /* DELIM specifier pointer      */
00787         ftnlen  indelimlen;             /* DELIM specifier length       */
00788         char    *inpad;                 /* PAD specifier pointer        */
00789         ftnlen  inpadlen;               /* PAD specifier length         */
00790 } inlist;
00791 
00792 /*
00793  *      Type Information Packet
00794  *
00795  *      This data structure is used extensively in the data-transfer I/O
00796  *      calls.  It exists to consolidate the data type information and to
00797  *      reduce the number of parameters in the mid-level libf routines.
00798  *      It also contains information relevant to numeric data conversion.
00799  *
00800  *      N.B. type77 may not always be correct, especially when libf is
00801  *      entered through one of the f90 interface routines; in which case
00802  *      it will be set to -1.  However, the mid- and low-level routines
00803  *      should all be using the type90 field.
00804  */
00805 
00806 typedef struct type_information_packet {
00807         ftype_t type90;         /* Fortran 90/95 data type      */
00808         short   type77;         /* Fortran 77 data type         */
00809         short   intlen;         /* Internal data length (bits)  */
00810         short   extlen;         /* External data length (bits)  */
00811         short   cnvindx;        /* Data conversion index        */
00812         long    count;          /* Number of data items         */
00813         long    stride;         /* Stride between data items    */
00814 
00815 /*      Element size is the internal length multiplied by the   */
00816 /*      number of elements (equivalent to intlen for everything */
00817 /*      but CHARACTER data), though expressed in bytes.         */
00818 
00819         long    elsize;         /* Element size (bytes)         */
00820 
00821 /*      The following fields are defined iff cnvindx != 0       */
00822 
00823         short   newfunc;        /* 1 if new-style conv. func.   */
00824         short   cnvtype;        /* Data conversion pseudo-type  */
00825         int     (* cnvfunc)();  /* Data conversion function     */
00826 } type_packet;
00827 
00828 /*
00829  *      The xfer_func typedef is a prototype for any functions called by
00830  *      _xfer_iolist.
00831  */
00832 
00833 typedef int xfer_func(FIOSPTR css, unit *cup, void *dptr, type_packet *tip,
00834                         int mode);
00835 
00836 /*
00837  *      The xfer_func_c typedef is a prototype for functions which process 
00838  *      input or output of contiguous data.
00839  */
00840 
00841 typedef long xfer_func_c(unit *cup, void *uda, type_packet *tip, int mode, 
00842                          int *ubc_ret, long *wr, int *status);
00843 
00844 /************************************************************************
00845  *
00846  * Error Handling Macros
00847  *
00848  *      RERROR (error_number);
00849  *      RERROR1(error_number, parameter);
00850  *
00851  *      These routines either terminate the program with an error, or if
00852  *      the user is processing errors, returns the error number.  Two
00853  *      versions of each routine exist to allow for a parameter to be
00854  *      substituted in the error message.
00855  *
00856  *      RERROR and RERROR1 should be used once the unit table pointer has
00857  *      been established.
00858  *
00859  *      GOERROR and GOERROR1 are used where a jump-to-label is desired upon
00860  *      reaching an error condition.  They set a special variable (errn) to the 
00861  *      return value and jump to a label.
00862  *
00863  ***********************************************************************/
00864 
00865 
00866 #define ABORT_ON_ERROR  (cup == NULL || (cup->uflag & (_UERRF | _UIOSTF)) == 0)
00867 
00868 #define RERROR(n) {                     \
00869         if (ABORT_ON_ERROR)             \
00870                 _ferr(css, n);          \
00871         else                            \
00872                 return(n);              \
00873 }
00874 
00875 #define RERROR1(n, p) {                 \
00876         if (ABORT_ON_ERROR)             \
00877                 _ferr(css, n, p);       \
00878         else                            \
00879                 return(n);              \
00880 }
00881 
00882 #define GOERROR(err, label)     { errn = err; goto label; }
00883 #define GOERROR1(err, p, label) { errn = err; parm = p; goto label; }
00884 
00885 /************************************************************************
00886  *
00887  * EOF Handling Macro
00888  *
00889  *      REND(error_number);
00890  *
00891  *      REND either terminates the program with an EOF-type error, or if
00892  *      the user is processing errors, returns the negative error number.
00893  *
00894  ***********************************************************************/
00895 #define REND(n) {       \
00896         if ((cup == NULL) || (cup->uflag & (_UENDF | _UIOSTF)) == 0)    \
00897                 _ferr(css, n);          \
00898         else                            \
00899                 return(n);              \
00900 }
00901 
00902 /************************************************************************
00903  *
00904  * Multitasking Macros
00905  *
00906  ***********************************************************************/
00907 
00908 #ifdef  _UNICOS
00909 #define INITIALIZE_LOCK(x)      { (x) = 0; }
00910 #elif   defined(__mips) || (defined(_LITTLE_ENDIAN) && defined(__sv2))
00911 #define INITIALIZE_LOCK(x)      { (x) = 0; }
00912 #elif   defined(_SOLARIS)
00913 #define INITIALIZE_LOCK(x)      mutex_init(&(x), USYNC_THREAD, NULL)
00914 #elif   defined(_LITTLE_ENDIAN) && !defined(__sv2)
00915 #define INITIALIZE_LOCK(x)      { (x) = 0; }
00916 #endif
00917 
00918 #define OPENLOCK()      MEM_LOCK(&_openlock)
00919 
00920 #define OPENUNLOCK()    MEM_UNLOCK(&_openlock)
00921 
00922 #define PARSELOCK()     MEM_LOCK(&_parselock)
00923 
00924 #define PARSEUNLOCK()   MEM_UNLOCK(&_parselock)
00925 
00926 /*
00927  *      FLSH_MEM
00928  *              Ensures that any prior stores complete before any following 
00929  *              stores.
00930  *
00931  *              On PVP systems, the "suppress" ensures stores are issued and 
00932  *              the _cmr() Waits for this CPU's memory stores to complete.
00933  *
00934  *              On Sparc systems, the call to the _flsh_mem routine ensures
00935  *              that all prior stores are issued (not held in registers).
00936  *
00937  *              On other systems, threading is not supported, so FLSH_MEM
00938  *              may be a no-op.
00939  *              
00940  */
00941 
00942 #ifdef  _CRAY1
00943 #define FLSH_MEM()      { _Pragma("suppress"); _cmr(); }
00944 #elif   defined(_SOLARIS)
00945 #define FLSH_MEM()      { _flsh_mem(); }
00946 #else
00947 #define FLSH_MEM()      { }
00948 #endif
00949 
00950 /************************************************************************
00951  *
00952  * General Macros
00953  *
00954  ***********************************************************************/
00955 
00956 /*
00957  *      MAX and MIN 
00958  *              Prevent compiler warnings by removing any definition added
00959  *              previously by other header files.
00960  */
00961 #undef MAX
00962 #define MAX(a,b)        ((a) > (b) ? (a) : (b))
00963 
00964 #undef MIN
00965 #define MIN(a,b)        ((a) < (b) ? (a) : (b))
00966 
00967 #define FF2FTNST(ffstat)        _ffstat_cnvt[ffstat]
00968 
00969 /*
00970  *      WAITIO
00971  *              Wait for any outstanding I/O to complete.  If an error in
00972  *              the completed asynchronous request is found, "error_handle"
00973  *              is executed.
00974  */
00975 #ifdef  DEBUG
00976 #define AIOCHK(cup)     { if (cup->ufs != FS_FDC) _ferr(NULL, FEINTUNK); }
00977 #else
00978 #define AIOCHK(cup)
00979 #endif
00980 
00981 #define MAXRECALL 1000000
00982 
00983 #define WAITIO(cup, error_handle) {                                     \
00984 /*                                                                      \
00985  *              If uasync is ASYNC_ACTIVE, then the last operation was  \
00986  *              asynchronous.  If the FFSTAT is zero, it has not yet    \
00987  *              completed.                                              \
00988  */                                                                     \
00989                 if (cup->uasync == ASYNC_ACTIVE) {                      \
00990                         register int    ct = 0;                         \
00991                         struct ffsw     zzstat;                         \
00992                         struct fdinfo   *llfio;                         \
00993                                                                         \
00994                         llfio   = (struct fdinfo *)cup->ufp.fdc;        \
00995                         AIOCHK(cup);    /* Do some DEBUG checking */    \
00996 /*                                                                      \
00997  *                      If I/O is still busy, go into recall until the  \
00998  *                      request has been completed.  If FFSTAT is != 0, \
00999  *                      then we really called a synchronous routine,    \
01000  *                      and need not call the recall routine at all.    \
01001  */                                                                     \
01002                         while (FFSTAT(cup->uffsw) == 0) {               \
01003                                 (void)XRCALL(llfio, fcntlrtn) llfio,    \
01004                                         FC_RECALL, &cup->uffsw, &zzstat);\
01005                                                                         \
01006                                 if (ct++ > MAXRECALL) _ferr(NULL, FEINTUNK);\
01007                         }                                               \
01008 /*                                                                      \
01009  *                      Set ulrecl                                      \
01010  */                                                                     \
01011                         cup->ulrecl = (uint64)cup->uffsw.sw_count << 3; \
01012                         cup->ufbitpos += cup->ulrecl;   /* for PURE */  \
01013                         if (cup->urecmode == PARTIAL)                   \
01014                                 cup->urecpos  += cup->ulrecl;           \
01015                                                                         \
01016                         switch (FFSTAT(cup->uffsw)) {                   \
01017                         case FFEOR:                                     \
01018                                 cup->ulastyp    = DT_NONE;              \
01019                                 cup->urecpos    = 0;                    \
01020                         case FFCNT:     /* fall through ! */            \
01021                                 cup->uend       = BEFORE_ENDFILE;       \
01022                                 break;                                  \
01023                         case FFEOF:                                     \
01024                                 cup->uend       = PHYSICAL_ENDFILE;     \
01025                                 break;                                  \
01026                         case FFEOD:                                     \
01027                                 if (cup->uend == BEFORE_ENDFILE)        \
01028                                         cup->uend       = LOGICAL_ENDFILE;\
01029                                 break;                                  \
01030                         }                                               \
01031                                                                         \
01032                         cup->uasync     = ASYNC_OK;                     \
01033 /*                                                                      \
01034  *                      If error, perform requested action.             \
01035  */                                                                     \
01036                         if (cup->uffsw.sw_error != 0) {                 \
01037                                 error_handle;                           \
01038                         }                                               \
01039                 }                                                       \
01040         }
01041 
01042 /*
01043  * POWER_OF_TWO Define a macro to determine if an integer is a power of
01044  *              two.  Use the _popcnt() intrinsic on CRAY PVP sytems.
01045  */
01046 
01047 #ifdef  _CRAY1
01048 #define POWER_OF_TWO(n) (_popcnt(n) == 1)
01049 #else
01050 #define POWER_OF_TWO(n) ((n & (n - 1)) == 0 && n != 0)
01051 #endif
01052 
01053 /*
01054  * COMPADD      Compute padding requirements for a particular file structure 
01055  *              and data conversion type.
01056  *
01057  * Parameters:
01058  *
01059  *      unit    *cup            - (input) unit pointer
01060  *      int     pbytes          - (output) number of pad bytes needed
01061  *      int     pbits           - (output) number of pad bits to subtract from
01062  *                                pbytes
01063  *      int     pval            - (output) the data area written out to
01064  *                                the file to fill the pad space. 
01065  *      
01066  */
01067 
01068 #if     NUMERIC_DATA_CONVERSION_ENABLED
01069 #define COMPADD(cup, pbytes, pbits, pval) {                             \
01070         register int64  bitpos, bits, gran;                             \
01071                                                                         \
01072         if (cup->ualign.pflag) {        /* If aligning */               \
01073                 bitpos  = cup->urecpos;                                 \
01074                 gran    = cup->ualign.gran;                             \
01075 /*                                                                      \
01076  *      Use bit masks rather than (slow) mod function if granularity is \
01077  *      a power of two.                                                 \
01078  */                                                                     \
01079                 if (POWER_OF_TWO(gran)) {                               \
01080                         bits    = gran - (bitpos & (gran - 1));         \
01081                         bits    &= gran - 1;                            \
01082                 }                                                       \
01083                 else {                                                  \
01084                         bits    = gran - (bitpos % gran);               \
01085                         bits    = bits % gran;                          \
01086                 }                                                       \
01087                 pbytes  = (bits + 7) >> 3;                              \
01088                 pbits   = (pbytes << 3) - bits;                         \
01089                 pval    = cup->ualign.padval;                           \
01090         }                                                               \
01091         else    /* No aligning */                                       \
01092                 pbytes = pbits = pval = 0;                              \
01093 }
01094 #else
01095 #define COMPADD(cup, pbytes, pbits, pval)       pbytes = pbits = pval = 0;
01096 #endif  /* NUMERIC_DATA_CONVERSION_ENABLED */
01097 
01098 /*
01099  * SET_F90_INFO Construct a pseudo-f90/f95 type descriptor and type
01100  *              information packet for f77 entry points.
01101  *
01102  * Parameters:
01103  *
01104  *      struct f90_type ts      f90/f95 type descriptor (output)
01105  *      type_packet     tip     Type information packet (output)
01106  *      short           type77  Fortran 77 data type (input)
01107  *      
01108  */
01109 
01110 #define CREATE_F90_INFO(ts, tip, type77) {                      \
01111         ts.type         = _f77_to_f90_type_cnvt[type77];        \
01112         ts.dpflag       = (type77 == DT_DBLE) ? 1 : 0;          \
01113         ts.int_len      = _f77_type_len[type77] << 3;           \
01114         ts.dec_len      = ts.int_len >> 3;                      \
01115         if (type77 == DT_SINT) {                                \
01116                 ts.kind_or_star = DVD_STAR;                     \
01117                 if (ts.dec_len == sizeof(_f_int))               \
01118                         ts.dec_len      = ts.dec_len >> 1;      \
01119         }                                                       \
01120         else                                                    \
01121                 ts.kind_or_star = DVD_DEFAULT;                  \
01122         tip.type77      = type77;                               \
01123         tip.type90      = ts.type;                              \
01124         tip.intlen      = ts.int_len;                           \
01125         tip.extlen      = ts.int_len;                           \
01126         tip.elsize      = ts.int_len >> 3;                      \
01127         tip.stride      = 1;                                    \
01128         tip.cnvindx     = 0;                                    \
01129 }
01130 
01131 /*
01132  * GOOD_UNUM(u) - verifies unit numbers.  Returns 1 if the given
01133  *                unit number could be connected.   
01134  */
01135 
01136 #define GOOD_UNUM(u)    ((u) >= 0)
01137 
01138 /*
01139  * RSVD_UNUM(u) - returns 1 iff u is a reserved unit number which cannot
01140  *                be opened by the user.
01141  */
01142 
01143 #define RSVD_UNUM(_U)   ((_U) >= STDIN_U && (_U) <= STDERR_U)
01144 
01145 /*
01146  * OPEN_UPTR    - returns 1 iff u points to a connected unit.  Returns 0
01147  *                if u is unconnected.
01148  */
01149 
01150 #define OPEN_UPTR(_U)   ((_U) != NULL && (_U)->ufs != 0)
01151 
01152 /*
01153  * UHASH        - computes the hash value for a unit number = x mod HASH_SIZE
01154  */
01155 
01156 #define UHASH(x)        (x & (HASH_SIZE - 1))
01157 
01158 /*
01159  * UNIT_NUM and GT_UNUM get the unit number for a given unit pointer.
01160  */
01161 
01162 #define UNIT_NUM(_U)    ((_U)->uid)
01163 
01164 #define GT_UNUM(_U, _N) { _N = UNIT_NUM(_U); }
01165 
01166 /*
01167  * MYTASK expands to a unique task identification number.
01168  */
01169 
01170 #ifdef  _CRAY1
01171 #define MYTASK  (t_tid())
01172 #elif   defined(_CRAYMPP)
01173 #define MYTASK  (_my_pe())
01174 #else
01175 #define MYTASK  0
01176 #endif
01177 
01178 /*
01179  *      STMT_BEGIN
01180  *
01181  *      This macro stores information about the current I/O statement,
01182  *      and snaps the current RT clock value for statistics gathering.
01183  *
01184  *      Returned is a (locked) current unit pointer if the unit is connected.
01185  *      Null is returned if the unit number is invalid or not connected.
01186  *
01187  *      Arguments
01188  *
01189  *              unum_t  _UNUM           - (input) unit number
01190  *              int     _INTFLAG        - (input) 1 if internal file
01191  *              int     _STMTCODE       - (input) statement code
01192  *              long    *_CILIST        - (unused) cilist from Fortran 90
01193  *              FIOSPTR _LOCFIOSP       - (input) FIOSPTR from Fortran 90
01194  *                                        or passed in from caller.  If this
01195  *                                        argument is NULL, task common
01196  *                                        is used.
01197  *              unit    *_CUP           - (output) unit pointer
01198  */
01199 #ifndef _UNICOS
01200 #define _rtc()  0
01201 #endif
01202 #ifdef  _CRAYMPP
01203 /* These macros are used for STOP_ALL processing */
01204 #define INCRINIO        {_infio++;}                                     
01205 #define CHKSTOP         {                                               \
01206                                 _infio--;                               \
01207                                 if (_needtostop){                       \
01208                                         _f_stopsig(SIGBUFIO);           \
01209                                 }                                       \
01210                         }
01211 #else
01212 #define INCRINIO        
01213 #define CHKSTOP
01214 #endif
01215 #define STMT_BEGIN(_UNUM, _INTFLAG, _STMTCODE, _CILIST, _LOCFIOSP, _CUP) {\
01216                 FIOSPTR fiosp;                                          \
01217                                                                         \
01218                 assert( _CILIST == NULL );                              \
01219                 if (_LOCFIOSP != NULL)                                  \
01220                         fiosp   = _LOCFIOSP;                            \
01221                 else                                                    \
01222                         GET_FIOS_PTR(fiosp);                            \
01223                 if (_INTFLAG)                                           \
01224                         _CUP    = _get_int_cup(); /* internal file */   \
01225                 else                                                    \
01226                         _CUP    = _get_cup(_UNUM); /* external file */  \
01227                                                                         \
01228                 /* Set fields which are accessed by _fcontext(). */     \
01229                                                                         \
01230                 INCRINIO;                                               \
01231                 fiosp->f_cu     = _CUP;                                 \
01232                 fiosp->f_curun  = _UNUM;                                \
01233                 fiosp->f_intflg = _INTFLAG;                             \
01234                 fiosp->f_iostmt = _STMTCODE;                            \
01235                                                                         \
01236                 if ((_STMTCODE) & TF_FMT)                               \
01237                         fiosp->u.fmt.u.fe.fmtbuf        = NULL;         \
01238                                                                         \
01239                 fiosp->f_rtbgn  = _rtc();       /* for statistics */    \
01240 }
01241 
01242 /*
01243  *      STMT_END
01244  *
01245  *      This macro processes the end of an I/O statement.  The unit is
01246  *      unlocked and procstat statistics are optionally posted if _CUP
01247  *      is non-null.
01248  * 
01249  *
01250  *      Parameters
01251  *
01252  *              unit    *_CUP           - (input) unit pointer
01253  *              int     _STATSCODE      - (input) statement code or TF_WRITE
01254  *                                        or TF_READ for statistics gathering
01255  *              long    *_CILIST        - (unused) cilist from Fortran 90
01256  *              FIOSPTR _LOCFIOSP       - (input) FIOSPTR from Fortran 90
01257  *                                        or passed in from caller.  If this
01258  *                                        argument is NULL, task common
01259  *                                        is used.
01260  */
01261 #define STMT_END(_CUP, _STATSCODE, _CILIST, _LOCFIOSP) {                \
01262                 FIOSPTR fiosp;                                          \
01263                                                                         \
01264                 assert( _CILIST == NULL );                              \
01265                 if (_LOCFIOSP != NULL)                                  \
01266                         fiosp   = _LOCFIOSP;                            \
01267                 else                                                    \
01268                         GET_FIOS_PTR(fiosp);                            \
01269                 if ((_CUP) != NULL) {                                   \
01270                         if (fiosp->f_iostmt & TF_POS)                   \
01271                                 cup->uposition  = 0;                    \
01272                         FSTATS_POST(_CUP, _STATSCODE, fiosp);           \
01273                         _release_cup(_CUP);     /* unlock the unit */   \
01274                 }                                                       \
01275                 CHKSTOP                                                 \
01276                 fiosp->f_curun  = -1;                                   \
01277                 fiosp->f_iostmt = 0;                                    \
01278                 fiosp->f_cu     = NULL;                                 \
01279 }
01280 
01281 /*
01282  *      CFT77_RETVAL
01283  *
01284  *      This macro returns the specified value to the CFT77 compiler-
01285  *      generated code at the end of a library I/O interface routine.
01286  */
01287 
01288 #if     defined(_CRAYMPP) || !defined(_UNICOS)
01289 #define CFT77_RETVAL(_VAL)      (_VAL)
01290 #else   /* _CRAYMPP || ! _UNICOS */
01291 #define CFT77_RETVAL(_VAL)      _sets3(_VAL)
01292 #endif
01293 
01294 /*
01295  *      GET_FIOS_PTR    Assign a pointer to the Fortran I/O Statement
01296  *                      state structure in task common.
01297  */
01298 
01299 #define GET_FIOS_PTR(_P) _P = &_tsk_fiostate;
01300 
01301 /*
01302  * IO_TYPE      - macro to categorize a unit as to the type of Fortran I/O which
01303  *                is permitted on it.
01304  *                Returns FIO_SU, FIO_SF, FIO_DU, or FIO_DF.
01305  *
01306  *      _U      pointer to the unit table entry.
01307  */
01308 
01309 #define IO_TYPE(_U) ((_U->useq) ?               \
01310                 (_U->ufmt ? FIO_SF : FIO_SU):   \
01311                 (_U->ufmt ? FIO_DF : FIO_DU))
01312 
01313 /************************************************************************
01314  *
01315  * External function prototypes
01316  *
01317  ***********************************************************************/
01318 extern unit     *_alloc_unit(unum_t unum, int private);
01319 extern void     _fcleanup(void);
01320 extern void     _fcontext(FIOSPTR fiosp);
01321 extern void     _ferr(FIOSPTR fiosp, int _Errno, ...);
01322 extern long     _frch(unit *_Cup, long *_Uda, long _Chars, int _Mode,
01323                         long *_Status);
01324 extern long     _fwch(unit *_Cup, long *_Uda, long _Chars, int _Mode);
01325 extern unit     *_search_unit_list(unit *p, unum_t unum);
01326 extern unit     *_get_next_unit(unit *p, int iflock, int iftask);
01327 extern unit     *_implicit_open(int acc, int form, unum_t unum, int errf,
01328                         int *errn);
01329 extern unit     *_imp_open(struct fiostate *css, int acc, int form, unum_t unum,
01330                         int errf, int *errn);
01331 extern unit     *_imp_open77(struct fiostate *css, int acc, int form,
01332                         unum_t unum, int errf, int *errn);
01333 extern void     _initialize_fortran_io(void);
01334 extern void     _init_unit(unit *cup);
01335 extern unit     *_init_internal_unit(void);
01336 extern int      _parse(FIOSPTR _Css, unit *_Cup, fmt_type **_Prsfmt);
01337 extern int      _unit_bksp(unit *cup);
01338 extern int      _unit_close(unit *cup, int cstat, FIOSPTR css);
01339 extern int      _unit_scratch(unit *cup);
01340 extern int      _unit_seek(unit *cup, recn_t recn, int iost);
01341 extern int      _unit_trunc(unit *cup);
01342 extern int      _setpos(FIOSPTR css, unit *cup, int *pa, int len);
01343 extern int      _uniqinod(unit *cup, assign_info *aip);
01344 extern int      _f_opn(char *actnam, unit *cup, FIOSPTR css, int tufs,
01345                         int aifound, assign_info *aip, struct stat *statp,
01346                         int statp_valid, int catcherr, int o_sysflgs);
01347 extern int      _do_open(unit *cup, FIOSPTR css, int tufs, char *actnam, 
01348                         int flags, int aifound, assign_info *aip, 
01349                         union spec_u *fdspec, int catcherr);
01350 extern void     _set_device_and_inode(int sysfd, dev_t *devicep, ino_t *inodep);
01351 
01352 extern xfer_func        _rdunf;
01353 extern xfer_func        _wrunf;
01354 extern xfer_func        _rdfmt;
01355 extern xfer_func        _wrfmt;
01356 extern xfer_func        _ld_read;
01357 extern xfer_func        _ld_write;
01358 extern xfer_func_c      _frwd;
01359 extern xfer_func_c      _fwwd;
01360 
01361 extern int      _dw_endrec(FIOSPTR _Css, unit *_Cup, int _Count);
01362 extern int      _iw_endrec(FIOSPTR _Css, unit *_Cup, int _Count);
01363 extern int      _sw_endrec(FIOSPTR _Css, unit *_Cup, int _Count);
01364 extern int      _nonadv_endrec(FIOSPTR _Css, unit *_Cup);
01365 extern int      _lw_after_nonadv(FIOSPTR _Css, unit *_Cup, int _Linelimit,
01366                         int _Namelistflag);
01367 
01368 extern int      _dr_endrec(FIOSPTR _Css, unit *_Cup, int _Count);
01369 extern int      _ir_endrec(FIOSPTR _Css, unit *_Cup, int _Count);
01370 extern int      _sr_endrec(FIOSPTR _Css, unit *_Cup, int _Count);
01371 
01372 extern void     _gather_data(void *lbuf, long items, long inc, int len,
01373                         void *ptr);
01374 extern void     _scatter_data (void *ptr, long items, long inc, int len,
01375                         void *lbuf);
01376 
01377 extern void     _set_ok_flags(unit *cup);
01378 extern int      _get_mismatch_error(int noabort, int iost, unit *cup,
01379                         FIOSPTR css);
01380 
01381 extern int      _iochunk(FIOSPTR css, unit *cup, xfer_func *func,
01382                         struct DvDimen *dimen, type_packet *tip, short nd,
01383                         long extent, int bshft, bcont *addr);
01384 
01385 extern void     _flsh_mem(void);
01386 
01387 extern int      _deduce_fstruct(int, struct fdinfo *, int);
01388 extern void     _setup_cvrt(unit *cup);
01389 extern void     _b_char(char *a, char *b, ftnlen blen);
01390 extern void     _copy_n_trim(char *a, ftnlen alen, char *b);
01391 /************************************************************************
01392  *
01393  * External symbols
01394  *
01395  ***********************************************************************/
01396 
01397 #define errfile stderr
01398 
01399 extern  unit_htable     _fort_unit[];   /* Hash table of units          */
01400 
01401 extern  plock_t _openlock;      /* Connecting unit lock                 */
01402 extern  plock_t _ioblock;       /* __iob table lock                     */
01403 extern  plock_t _parselock;     /* Format parsing lock                  */
01404 extern  plock_t _stdin_lock;    /* Stdin lock                           */
01405 extern  plock_t _stdout_lock;   /* Stdout lock                          */
01406 extern  plock_t _stderr_lock;   /* Stderr lock                          */
01407 
01408 extern  int     _f_rcsz;        /* Default sequential formatted RECL    */
01409 extern  int     _f_ldsz;        /* Default list-directed output RECL    */
01410 extern  int     _def_bin_bs;    /* Default '-s bin' buffer size         */
01411 extern  int     _def_sbin_bs;   /* Default '-s sbin' buffer size        */
01412 #ifdef  _CRAYMPP
01413 extern  volatile int    _infio;         /* Set when inside an i/o statement*/
01414 extern  volatile int    _needtostop;    /* Set when we need to stop     */
01415 #endif
01416 
01417 /* External tables and structures (defined in tables.c) */
01418 
01419 extern const ftype_t
01420         _f77_to_f90_type_cnvt[DT_MAX];  /* f77 to f90 type conversion   */
01421 extern const short
01422         _f90_to_f77_type_cnvt[DVTYPE_NTYPES]; /* f90 to f77 type conv.  */
01423 extern const short
01424         _f77_type_len[DT_MAX];          /* f77 type lengths (bytes)     */
01425 extern const char *
01426         _f90_type_name[DVTYPE_NTYPES];  /* f90 data type names          */
01427 extern const char *
01428         _f77_type_name[DT_MAX];         /* f77 data type names          */
01429 extern const short
01430         _charset_cnvt[CS_MAX];          /* Character to numeric conv.   */
01431 extern const short
01432         _ffstat_cnvt[7];                /* FFIO to frch status conv.    */
01433 extern const short
01434         _old_namelist_to_f77_type_cnvt[10]; /* Namelist to f77 type cnv.*/
01435 extern type_packet      __tip_null;     /* Null type packet             */
01436 
01437 #ifdef  _CRAY1
01438 #pragma _CRI taskcommon _tsk_fiostate
01439 #endif
01440 extern struct fiostate  _tsk_fiostate;  /* Task local I/O state */
01441 extern short    _fortran_io_is_init;    /* 0 until Fortran I/O is init */
01442 extern short    _e_fortran_io_is_init;  /* 0 until ext Fortran I/O is init */
01443 extern short    _i_fortran_io_is_init;  /* 0 until int Fortran I/O is init */
01444 extern unit     *_fort_internal_unit;   /* Pointer to internal unit     */
01445 
01446 /************************************************************************
01447  *
01448  * Inline Functions
01449  *
01450  ***********************************************************************/
01451 
01452 /*
01453  *      _get_cup 
01454  *
01455  *              This inline function returns a unit pointer for a particular
01456  *              unit connected to an external file.  If the unit is not open, 
01457  *              then NULL is returned.  The errstat parameter is assigned an 
01458  *              error status if an error is encountered.
01459  *
01460  *              Any necessary locking of the unit is performed.
01461  *
01462  *              NOTE: this version of _get_cup will be rewritten soon
01463  *              when dynamic unit allocation is activated.
01464  *              
01465  *      Return value:
01466  *              Pointer to a connected unit.  If the unit number is not 
01467  *              connected NULL is returned. 
01468  */
01469 _PRAGMA_INLINE(_get_cup)
01470 static unit *
01471 _get_cup(unum_t unum)
01472 {
01473         unit    *cup;
01474 
01475         cup     = _fort_unit[UHASH(unum)].ulist;
01476 
01477         if (cup != NULL) {
01478 #ifdef  _CRAYMPP
01479                 if (cup->uid != unum)
01480 #else
01481                 if (cup->private || cup->uid != unum)
01482 #endif
01483                         cup     = _search_unit_list(cup, unum);
01484         }
01485 
01486         if (cup != NULL) {
01487                 MEM_LOCK(&cup->uiolock);        /* lock the unit */
01488                 if (OPEN_UPTR(cup)) {   /* if unit is connected */
01489                         /*
01490                          * Lock the auxiliary lock if this unit has one.
01491                          * This lock is necessary for standard files, which 
01492                          * are connected to more than one unit.
01493                          */
01494                         if (cup->auxlockp != NULL) {
01495                                 MEM_LOCK(cup->auxlockp);        
01496                         }
01497                 }
01498                 else {                  /* else unit is not connected */
01499                         MEM_UNLOCK(&cup->uiolock);
01500                         cup     = NULL;         /* unit not connected */
01501                 }
01502         }
01503         return(cup);
01504 }
01505 
01506 /*
01507  *      _get_int_cup
01508  *
01509  *              This inline function returns a unit pointer for an internal
01510  *              file.
01511  *
01512  *              Any necessary locking of the unit is performed.
01513  *
01514  *      Return value:
01515  *              Pointer to a unit.  If an error occurs, then NULL is returned.
01516  */
01517 
01518 _PRAGMA_INLINE(_get_int_cup)
01519 static unit *
01520 _get_int_cup(void)
01521 {
01522         unit    *cup;
01523         cup     = _fort_internal_unit;
01524         if (cup == NULL)
01525                 cup     = _init_internal_unit();
01526         MEM_LOCK(&cup->uiolock);
01527         return(cup);
01528 }
01529 
01530 /*
01531  *      _release_cup 
01532  *
01533  *              Unlock a unit pointer.
01534  */
01535 _PRAGMA_INLINE(_release_cup)
01536 static void
01537 _release_cup(unit *cup)
01538 {
01539         MEM_UNLOCK(&cup->uiolock);
01540         if (cup->auxlockp != NULL)
01541                 MEM_UNLOCK(cup->auxlockp);
01542 }
01543 
01544 #if     defined(LIBDEBUG) && ! defined(_UNICOS)
01545 /*
01546  *      _ferr macro.  This is handy on Sparc where tracebacks cannot be printed.
01547  */
01548 #define _ferr  \
01549          fprintf(stderr,"ERROR on line %d in file \"%s\"\n", \
01550                 __LINE__, __FILE__), \
01551         _ferr_routine
01552 #endif  /* LIBDEBUG */
01553 
01554 #if     defined(__mips) || defined(_LITTLE_ENDIAN)
01555 /* Putting the pragma inline before the function declaration wasn't */
01556 /* effective on MIPS systems. */
01557 #pragma inline _get_cup
01558 #pragma inline _get_int_cup
01559 #pragma inline _release_cup
01560 #endif
01561 
01562 #endif /* !_FIO_H */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines