00001 /* 00002 * Copyright 2004 PathScale, Inc. All Rights Reserved. 00003 */ 00004 00005 /* 00006 00007 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00008 00009 This program is free software; you can redistribute it and/or modify it 00010 under the terms of version 2.1 of the GNU Lesser General Public License 00011 as published by the Free Software Foundation. 00012 00013 This program is distributed in the hope that it would be useful, but 00014 WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00016 00017 Further, this software is distributed without any warranty that it is 00018 free of the rightful claim of any third person regarding infringement 00019 or the like. Any license provided herein, whether implied or 00020 otherwise, applies only to this software file. Patent licenses, if 00021 any, provided herein do not apply to combinations of this program with 00022 other software, or any other product whatsoever. 00023 00024 You should have received a copy of the GNU Lesser General Public 00025 License along with this program; if not, write the Free Software 00026 Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, 00027 USA. 00028 00029 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00030 Mountain View, CA 94043, or: 00031 00032 http://www.sgi.com 00033 00034 For further information regarding this notice, see: 00035 00036 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00037 00038 */ 00039 00040 00041 /* USMID @(#) libf/include/f90io.h 92.3 10/29/99 21:41:49 */ 00042 00043 00044 #ifndef _F90IO_H 00045 #define _F90IO_H 00046 00047 /******************************************************************************* 00048 * 00049 * This header file contains declarations of compiler-library interface 00050 * routines, constants, and information packets. 00051 * 00052 * Header files which must be included in addition to this header file: 00053 * 00054 * "fio.h" 00055 * 00056 ******************************************************************************/ 00057 00058 #include <ctype.h> 00059 #include <stdlib.h> 00060 #include <string.h> 00061 #include <cray/dopevec.h> 00062 #include "util/utildefs.h" 00063 00064 /******************************************************************************* 00065 * 00066 * Constants 00067 * 00068 ******************************************************************************/ 00069 00070 /* 00071 * The following values are returned by the single call I/O interface 00072 * routines for use in condition handling, i.e., END=, ERR=, and EOR= 00073 * specifiers in I/O statements. 00074 */ 00075 00076 #define IO_OKAY 0 /* Normal completion */ 00077 #define IO_ERR 1 /* Error status */ 00078 #define IO_END 2 /* End status */ 00079 #define IO_EOR 3 /* End of record status */ 00080 00081 /******************************************************************************* 00082 * 00083 * General structures 00084 * 00085 ******************************************************************************/ 00086 00087 /* 00088 * gfptr_t represents all forms of pointers to Fortran data. 00089 */ 00090 00091 typedef union { 00092 _fcd fcd; /* Fortran character descriptor */ 00093 void *v; /* pointer to byte address */ 00094 _f_int *wa; /* pointer to word address */ 00095 struct DopeVector *dv; /* pointer to dope vector */ 00096 } gfptr_t; 00097 00098 00099 extern int _cntig_chk(DopeVectorType *dv, 00100 void **newar, 00101 int *nocontig, 00102 long *extent, 00103 long *nbytes); 00104 00105 /******************************************************************************* 00106 * 00107 * Packets for OPEN, CLOSE, INQUIRE, BUFFER IN, and BUFFER OUT 00108 * 00109 ******************************************************************************/ 00110 00111 /* 00112 * In open_spec_list, inquire_spec_list, close_spec_list structures, 00113 * some common conventions exist. 00114 * 00115 * 1) all specifier fields are in the order as listed in the ANSI standard 00116 * 00117 * 2) For fields of type (_f_int *), NULL implies that the specifier is 00118 * not passed. For fields x of type _fcd, the absence of the specifier is 00119 * implied when _fcdtocp(x) == NULL, 00120 * 00121 * 3) All version numbers are 0 in initial release. The numbers are 00122 * incremented when incompatible changes are made to the structures. 00123 */ 00124 00125 /* 00126 * open_spec_list is the interface packet passed to _OPEN. 00127 */ 00128 struct open_spec_list { 00129 #if defined(_UNICOS) || defined(__mips) || defined(_LITTLE_ENDIAN) 00130 unsigned int :32; /* reserved */ 00131 #endif 00132 unsigned int :24; /* reserved */ 00133 unsigned int version :8; /* version number */ 00134 _f_int *unit; 00135 _f_int *iostat; 00136 long err; /* -1 if ERR= specified; 0 otherwise */ 00137 _fcd file; 00138 _fcd status; 00139 _fcd access; 00140 _fcd form; 00141 _f_int *recl; 00142 _fcd blank; 00143 _fcd position; 00144 _fcd action; 00145 _fcd delim; 00146 _fcd pad; 00147 }; 00148 00149 /* 00150 * inquire_spec_list is the interface packet passed to _INQUIRE. 00151 */ 00152 struct inquire_spec_list { 00153 #if defined(_UNICOS) || defined(__mips) || defined(_LITTLE_ENDIAN) 00154 unsigned int :32; /* reserved */ 00155 #endif 00156 unsigned int :24; /* reserved */ 00157 unsigned int version :8; /* version number */ 00158 _f_int *unit; 00159 _fcd file; 00160 _f_int *iostat; 00161 long err; /* -1 if ERR= specified; 0 otherwise */ 00162 _f_log *exist; 00163 _f_log *opened; 00164 _f_int *number; 00165 _f_log *named; 00166 _fcd name; 00167 _fcd access; 00168 _fcd sequential; 00169 _fcd direct; 00170 _fcd form; 00171 _fcd formatted; 00172 _fcd unformatted; 00173 _f_int *recl; 00174 _f_int *nextrec; 00175 _fcd blank; 00176 _fcd position; 00177 _fcd action; 00178 _fcd read; 00179 _fcd write; 00180 _fcd readwrite; 00181 _fcd delim; 00182 _fcd pad; 00183 }; 00184 00185 /* 00186 * close_spec_list is the interface packet passed to _OPEN. 00187 */ 00188 struct close_spec_list { 00189 #if defined(_UNICOS) || defined(__mips) || defined(_LITTLE_ENDIAN) 00190 unsigned int :32; /* reserved */ 00191 #endif 00192 unsigned int :24; /* reserved */ 00193 unsigned int version :8; /* version number */ 00194 _f_int *unit; 00195 _f_int *iostat; 00196 long err; /* -1 if ERR= specified; 0 otherwise */ 00197 _fcd status; 00198 }; 00199 00200 /* 00201 * bio_spec_list is the interface packet passed to _BUFFERIN and 00202 * _BUFFEROUT. 00203 */ 00204 struct bio_spec_list { 00205 #if defined(_UNICOS) || defined(__mips) || defined(_LITTLE_ENDIAN) 00206 unsigned int :32; /* reserved */ 00207 #endif 00208 unsigned int :24; /* reserved */ 00209 unsigned int version :8; /* version number */ 00210 _f_int *unit; /* Unit */ 00211 _f_int *recmode; /* Mode */ 00212 gfptr_t bloc; /* Beginning location */ 00213 gfptr_t eloc; /* Ending location */ 00214 f90_type_t *tiptr; /* Data type word */ 00215 }; 00216 00217 /******************************************************************************* 00218 * 00219 * Packets for _FRF, _FWF, _FRU, and _FWU 00220 * 00221 ******************************************************************************/ 00222 00223 /* 00224 * The cilist describes all specifiers passed to a READ or WRITE 00225 * statement. 00226 */ 00227 00228 #ifndef CILIST_VERSION 00229 #define CILIST_VERSION 1 /* cilist version number */ 00230 #endif 00231 00232 typedef struct ControlList { 00233 unsigned int version :8; /* contains CILIST_VERSION */ 00234 enum uflag_spec { 00235 CI_UNITNUM = 0, /* Unit number */ 00236 CI_UNITASTERK = 1, /* Asterisk */ 00237 CI_UNITCHAR = 2, /* Character variable (_fcd) */ 00238 /* internal file or ENCODE/DECODE */ 00239 CI_UNITDOPEVEC = 3 /* character array */ 00240 } uflag :8; /* type of unit identifier */ 00241 unsigned int :4; /* unused */ 00242 unsigned int iostatflg:1; /* iostat= present flag */ 00243 unsigned int eorflag :1; /* eor= present flag */ 00244 unsigned int endflag :1; /* end= present flag */ 00245 unsigned int errflag :1; /* err= present flag */ 00246 unsigned int :2; /* unused */ 00247 enum advan_spec { 00248 CI_ADVYES = 0, /* ADVANCE=YES or not specified */ 00249 CI_ADVNO = 1, /* ADVANCE=NO */ 00250 CI_ADVVAR = 2 /* ADVANCE=variable */ 00251 } advcode :3; /* ADVANCE= specifier value */ 00252 unsigned int edcode :1; /* 1 if ENCODE/DECODE flag */ 00253 unsigned int internal :1; /* 1 if internal file */ 00254 /* must be 1 if edcode is 1 */ 00255 unsigned int dflag :1; /* 1 if direct access */ 00256 enum fmtflag_spec { 00257 CI_LISTDIR = 0, /* List-directed formatting */ 00258 CI_EDITCHAR = 1, /* Format in character variable */ 00259 CI_EDITCHARAY = 2, /* Format in char array section */ 00260 CI_EDITHOL = 3, /* Format in Hollerith */ 00261 CI_EDITHOLARAY = 4, /* Format in Hollerith array */ 00262 CI_NAMELIST = 5 /* Namelist formatting */ 00263 } fmt :8; /* type of format (or list-directed) */ 00264 unsigned int stksize :8; /* size in words of stack space */ 00265 /* passed as 3rd arg to */ 00266 /* _FRF/_FWF/_FRU/_FWU */ 00267 unsigned int :8; /* unused */ 00268 unsigned int icount :8; /* size of struct control list in */ 00269 /* words */ 00270 00271 gfptr_t unit; /* pointer to unit */ 00272 00273 _f_int *iostat_spec; /* address of IOSTAT= variable */ 00274 _f_int *rec_spec; /* address of REC= variable */ 00275 struct fmt_entry *parsfmt; /* pointer to parsed fmt */ 00276 00277 gfptr_t fmtsrc; /* pointer to format text */ 00278 00279 _fcd advance_spec; /* addr of ADVANCE= variable */ 00280 _f_int *size_spec; /* addr of SIZE= variable */ 00281 } ControlListType; 00282 00283 /* 00284 * The IO item list passed to a Fortran 90 single call data transfer (IO) 00285 * interface routine can take any of these forms: 00286 * 00287 * One IO item list is passed with each call to an interface routine. 00288 * IO item lists from a sequence of one or more library calls are needed 00289 * to completely process each data transfer (READ or WRITE) statements. 00290 * 00291 * 00292 * An IO item list has the following structure (using grammar notation): 00293 * 00294 * IO-item-list is 00295 * iolist_header compound-item 00296 * 00297 * compound-item is 00298 * compound-item iolist-item 00299 * or iolist-item 00300 * 00301 * iolist-item is 00302 * ioentry_header ioscalar_entry 00303 * or ioentry_header ioarray_entry 00304 * or ioentry_header implieddo-item 00305 * 00306 * implieddo-item is 00307 * ioimplieddo_entry iolist_header compound-item 00308 */ 00309 00310 #ifndef IOLIST_VERSION 00311 #define IOLIST_VERSION 1 /* current iolist version number */ 00312 #endif 00313 00314 /* 00315 * iolist_header is the first structure of an I/O item list. One I/O 00316 * item list is passed with each call to a compiler-library interface 00317 * routine. Several calls, and several I/O item lists, may be needed 00318 * to completely process a data transfer (READ or WRITE) statement. 00319 * 00320 * iolist_header is also passed immediately following the ioimplieddo_entry 00321 * in an implied do control list. 00322 */ 00323 00324 typedef struct { 00325 unsigned int version :3; /* contains IOLIST_VERSION */ 00326 unsigned int :27; /* unused */ 00327 00328 /* 00329 * Iolist table entry bits indicate whether data transfer statement 00330 * contains more than one iolist table. If iolfirst=iollast=1, then 00331 * table is entire iolist. If iolfirst=iollast=0, then table is 00332 * middle iolist table. 00333 */ 00334 00335 unsigned int iolfirst:1; /* 1 if first IO item list for current*/ 00336 /* statment IO statement */ 00337 unsigned int iollast :1; /* 1 if last IO item list for current */ 00338 /* statment IO statement */ 00339 unsigned int icount :16; /* number of iolist-items in this */ 00340 /* IO item list. If zero and it is */ 00341 /* both first and last io list, there */ 00342 /* is no io list in statement */ 00343 unsigned int ioetsize:16; /* number of words in the current */ 00344 /* IO item list, including this */ 00345 /* iolist_header */ 00346 /* On SGI systems, in 32-bit mode */ 00347 /* this is the number of 32-bit */ 00348 /* words, and in 64-bit mode this is */ 00349 /* the number of 64-bit words. */ 00350 } iolist_header; 00351 00352 /* 00353 * ioentry_header describes the type of iolist item. 00354 */ 00355 typedef struct { 00356 enum valtype_spec { 00357 IO_VALUNUSED = 0, 00358 IO_SCALAR = 1, /* scalar */ 00359 IO_DOPEVEC = 2, /* dopevector */ 00360 IO_LOOP = 3, /* implied-DO loop */ 00361 IO_STRUC_A = 4, /* struc for namelist array */ 00362 IO_STRUC_S = 5 /* struc for namelist scalar */ 00363 } valtype :8; /* type of iolist entry */ 00364 #if defined(_UNICOS) || defined(__mips) || defined(_LITTLE_ENDIAN) 00365 unsigned int :24; /* unused */ 00366 unsigned int :16; /* unused */ 00367 #else 00368 unsigned int :8; /* unused */ 00369 #endif 00370 unsigned int ioentsize:16; /* number of words of the current */ 00371 /* iolist item, including this */ 00372 /* ioentry_header */ 00373 /* On SGI systems, in 32-bit mode */ 00374 /* this is the number of 32-bit */ 00375 /* words, and in 64-bit mode this is */ 00376 /* the number of 64-bit words. */ 00377 } ioentry_header; 00378 00379 /* 00380 * ioscalar_entry describes a scalar IO list item. Pointers to scalars 00381 * are processed with the ioarray_entry type of IO list item. 00382 */ 00383 typedef struct { 00384 f90_type_t tinfo; /* type information for variable */ 00385 gfptr_t iovar_address; /* pointer to variable */ 00386 } ioscalar_entry; 00387 00388 /* 00389 * ioarray_entry describes an array section IO list item. It contains an 00390 * implied-DO multiplier address for each dimension of the array iff 00391 * indflag is set. 00392 */ 00393 typedef struct { 00394 struct DopeVector *dv; /* pointer to dope vector */ 00395 unsigned int indflag :1; /* 1 if indexed array */ 00396 unsigned int boundchk:1; /* Array bounds checking flag */ 00397 /* Not used for F90 release 1. */ 00398 /* 0=no bounds checking on array */ 00399 /* 1=bounds checking on array */ 00400 00401 unsigned int :30; /* pad to end of word */ 00402 #if defined(_UNICOS) || defined(__mips) || defined(_LITTLE_ENDIAN) 00403 unsigned int :32; 00404 #endif 00405 00406 int *dovar[MAXDIM]; /* array of pointers to indices. A */ 00407 /* NULL index pointer references the */ 00408 /* entire extent of a dimension. */ 00409 } ioarray_entry; 00410 00411 /* 00412 * ioimplieddo_entry describes an implied-DO loop IO list item. This 00413 * structure is followed by idcount iolist-items, which each consist 00414 * of an ioentry_header structure followed by an ioscalar_entry, 00415 * an ioarray_entry structure, or a nested implieddo-item. 00416 */ 00417 typedef struct { 00418 int *ioloopvar; /* address of loop variable */ 00419 int *iobegcnt; /* address of beginning count of loop */ 00420 int *ioendcnt; /* address of ending count of loop */ 00421 int *ioinccnt; /* address of increment of loop */ 00422 } ioimplieddo_entry; 00423 00424 /****************************************************************************** 00425 * 00426 * Inline function definitions. 00427 * 00428 ******************************************************************************/ 00429 00430 /* 00431 * _is_nonadv returns 00432 * 00433 * 0 ADVANCE='YES' 00434 * 1 ADVANCE='NO' 00435 * -1 invalid ADVANCE= specifier 00436 */ 00437 _PRAGMA_INLINE(_is_nonadv) 00438 static int 00439 _is_nonadv(ControlListType *cilist) 00440 { 00441 if (cilist->advcode == CI_ADVYES) { 00442 return(0); /* ADVANCE='YES' */ 00443 } 00444 else if (cilist->advcode == CI_ADVNO) { 00445 return(1); /* ADVANCE='NO' */ 00446 } 00447 else { /* (cilist->advcode == CI_ADVVAR) */ 00448 if (_string_cmp("YES", _fcdtocp(cilist->advance_spec), 00449 _fcdlen(cilist->advance_spec))) 00450 return(0); /* ADVANCE='YES' */ 00451 else if (_string_cmp("NO", _fcdtocp(cilist->advance_spec), 00452 _fcdlen(cilist->advance_spec))) 00453 return(1); /* ADVANCE='NO' */ 00454 } 00455 return(-1); 00456 } 00457 00458 /* 00459 * setup_format Initialize unit table fields and obtain the 00460 * parsed format. 00461 * 00462 * Returns 00463 * 0 on normal return 00464 * >0 error status 00465 */ 00466 _PRAGMA_INLINE(setup_format) 00467 static int 00468 setup_format( 00469 struct fiostate *css, 00470 unit *cup, 00471 ControlListType *cilist) 00472 { 00473 register long flen; 00474 register int fnum; 00475 register int stsz; 00476 char *fptr; /* Pointer to unparsed format */ 00477 fmt_type *ppfmt; /* Pointer to parsed format */ 00478 00479 /* 00480 * For formats passed as hollerith (integer) variables, 00481 * cft90 guarantees that they are terminated by a zero byte. 00482 * We use strlen() to obtain the length. 00483 * 00484 * For static formats (FORMAT statements) or formats 00485 * which are character constants or simple character 00486 * variables, the length of the format is the length of 00487 * the character string. 00488 * 00489 * For formats passed as character or Hollerith arrays, the 00490 * length of the format is the length of the entire array. 00491 * We compute this by multiplying the length of the element 00492 * passed times the dimension of the array. 00493 */ 00494 00495 switch (cilist->fmt) { 00496 00497 case CI_EDITCHAR: /* character variable */ 00498 fptr = _fcdtocp(cilist->fmtsrc.fcd); 00499 flen = _fcdlen (cilist->fmtsrc.fcd); 00500 break; 00501 00502 case CI_EDITCHARAY: /* dopevector */ 00503 case CI_EDITHOLARAY: 00504 { 00505 register int errn; 00506 int nocontig = 0; 00507 long extent = 0; 00508 long nbytes = 0; 00509 void *newar; 00510 DopeVectorType *dv = cilist->fmtsrc.dv; 00511 00512 if (dv->p_or_a && (dv->assoc == 0)) 00513 _ferr(css, FEFMTPAL); /* array or ptr not alloc/assoc */ 00514 00515 /* Check for contiguous array */ 00516 00517 errn = _cntig_chk(dv, &newar, &nocontig, &extent, &nbytes); 00518 00519 if (errn > 0) 00520 _ferr(css, errn); /* No memory available */ 00521 00522 css->u.fmt.freefmtbuf = nocontig; 00523 00524 fptr = (nocontig) ? newar : _fcdtocp(dv->base_addr.charptr); 00525 00526 /* Zero length array or character is bad format */ 00527 00528 if (extent == 0) 00529 _ferr(css, FEFMTNUL); 00530 00531 /* 00532 * flen is the element length in bytes times the number 00533 * of elements in the array 00534 */ 00535 00536 flen = nbytes; 00537 break; 00538 } 00539 00540 case CI_EDITHOL: /* Null-terminated hollerith */ 00541 fptr = (char *) cilist->fmtsrc.wa; 00542 flen = (long) strlen(fptr); 00543 break; 00544 00545 default: 00546 _ferr(css, FEINTUNK); /* Deep weeds... */ 00547 } 00548 00549 /* 00550 * For compatibility with ancient compilers, pull an optional 00551 * statement number off of the beginning of the format and save 00552 * it. If a statement number is found, update the format string 00553 * pointer and length. Someday, Obi-wan, we'll do this only for 00554 * static formats; or not at all. 00555 */ 00556 00557 fnum = 0; 00558 00559 while (isdigit(*fptr) && flen-- > 0) 00560 fnum = (fnum << 3) + (fnum << 1) + 00561 ((int) *fptr++ - (int) '0'); 00562 00563 css->u.fmt.u.fe.fmtbuf = fptr; 00564 css->u.fmt.u.fe.fmtlen = flen; 00565 css->u.fmt.u.fe.fmtnum = fnum; 00566 00567 /* 00568 * If the format is a variable format, or if it has not yet 00569 * been parsed, or if it was parsed by an incompatible version 00570 * of the format parser, then parse it. 00571 */ 00572 00573 ppfmt = cilist->parsfmt; 00574 00575 if (ppfmt == NULL || ppfmt->offset != PARSER_LEVEL) { /* not parsed */ 00576 register int errn; 00577 00578 errn = _parse(css, cup, (fmt_type **) ppfmt); 00579 00580 /* 00581 * If the parsed format was of an old version, store the 00582 * new version of the parsed format in the cilist for 00583 * subsequent executions of this I/O statement. 00584 */ 00585 00586 if (ppfmt != NULL) 00587 cilist->parsfmt = ppfmt; 00588 00589 if (errn != 0) 00590 return(errn); 00591 } 00592 else 00593 css->u.fmt.u.fe.pfmt = ppfmt; 00594 00595 /* 00596 * Ensure that the format count stack is allocated and is 00597 * large enough to accomodate the maximum nesting depth of 00598 * this format. 00599 */ 00600 00601 stsz = css->u.fmt.u.fe.pfmt->rep_count; 00602 00603 if (stsz > cup->upfcstsz) { 00604 00605 cup->upfcstsz = stsz; /* Set new depth */ 00606 00607 if (cup->upfcstk != NULL) 00608 free(cup->upfcstk); /* Free old stack */ 00609 00610 cup->upfcstk = (int *) malloc(sizeof(int) * stsz); 00611 00612 if (cup->upfcstk == NULL) 00613 return(FENOMEMY); /* No memory */ 00614 00615 } 00616 00617 css->u.fmt.u.fe.pftocs = cup->upfcstk; /* Set top of count stack */ 00618 00619 /* Skip first entry of parsed format */ 00620 00621 css->u.fmt.u.fe.pfcp = css->u.fmt.u.fe.pfmt + 1; 00622 00623 /* Set initial repeat count */ 00624 00625 *css->u.fmt.u.fe.pftocs = css->u.fmt.u.fe.pfcp->rep_count; 00626 00627 return(0); 00628 } 00629 00630 /****************************************************************************** 00631 * 00632 * Function prototypes and declarations. 00633 * 00634 ******************************************************************************/ 00635 00636 extern int _FRF(ControlListType *cilist, iolist_header *iolist, void *stck); 00637 extern int _FWF(ControlListType *cilist, iolist_header *iolist, void *stck); 00638 extern int _FRU(ControlListType *cilist, iolist_header *iolist, void *stck); 00639 extern int _FWU(ControlListType *cilist, iolist_header *iolist, void *stck); 00640 extern int _OPEN(struct open_spec_list *osl); 00641 extern int _CLOSE(struct close_spec_list *csl); 00642 extern int _INQUIRE(struct inquire_spec_list *isl); 00643 extern void _BUFFERIN(struct bio_spec_list *bisl); 00644 extern void _BUFFEROUT(struct bio_spec_list *bosl); 00645 00646 extern int _xfer_iolist(FIOSPTR css, unit *cup, iolist_header *iolist, 00647 xfer_func *func); 00648 00649 /****************************************************************************** 00650 * 00651 * External symbols 00652 * 00653 ******************************************************************************/ 00654 00655 typedef enum valtype_spec entrycode_t; /* io or namelist entry codes */ 00656 00657 #endif /* !_F90IO_H */
1.5.6