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