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/wf90.c 92.4 06/18/99 10:01:44" 00039 00040 #include <stdio.h> 00041 #include <cray/format.h> 00042 #include <cray/nassert.h> 00043 #include "fio.h" 00044 #include "f90io.h" 00045 00046 /* 00047 * _FWF Called by compiled Fortran programs to process a formatted 00048 * write statement. Each statement is processed by one or 00049 * more calls to _FWF. 00050 * 00051 * Synopsis 00052 * 00053 * int _FWF( ControlList *cilist, 00054 * iolist_header *iolist, 00055 * void *stck); 00056 * 00057 * Where 00058 * 00059 * cilist Pointer to the control information list 00060 * information. This describes the specifiers 00061 * for the current I/O statement. This cilist 00062 * is guaranteed by the compiler to reflect 00063 * the original values of control information 00064 * list variables for the duration of the I/O 00065 * statement (ie through multiple calls). 00066 * iolist Pointer to the I/O list information. 00067 * stck Pointer to stack space which is passed 00068 * to each call to _FWF for a particular 00069 * statement. This space is used by the 00070 * library. 00071 * 00072 * Return value 00073 * 00074 * IO_OKAY or IO_ERR 00075 */ 00076 00077 int 00078 _FWF(ControlListType *cilist, iolist_header *iolist, void *stck) 00079 { 00080 register int errf; /* ERR processing flag */ 00081 register int errn; /* Error number */ 00082 register int iost; /* I/O statement type */ 00083 register int retval; /* _FWF return value */ 00084 register recn_t errarg; /* Extra _ferr argument */ 00085 register unum_t unum; /* Unit number */ 00086 xfer_func *xfunc; /* Data transfer func. */ 00087 unit *cup; /* Unit table pointer */ 00088 FIOSPTR css; /* I/O statement state */ 00089 00090 /* 00091 * Assertions 00092 */ 00093 /* Validate that the size of *stck is large enough */ 00094 00095 assert ( cilist->stksize >= sizeof(struct fiostate)/sizeof(long) ); 00096 00097 /* The compiler disallows EOR= on WRITE */ 00098 00099 assert ( cilist->eorflag == 0 ); 00100 00101 /* The compiler disallows SIZE= on WRITE */ 00102 00103 assert ( cilist->size_spec == NULL ); 00104 00105 /* The compiler disallows ADVANCE= w/ internal files */ 00106 00107 assert( ! (cilist->advcode != CI_ADVYES && cilist->internal != 0)); 00108 00109 /* The compiler disallows ADVANCE= w/ list-directed */ 00110 00111 assert( ! (cilist->advcode != CI_ADVYES && cilist->fmt == CI_LISTDIR)); 00112 00113 css = stck; 00114 errn = 0; 00115 errarg = 0; 00116 retval = IO_OKAY; 00117 xfunc = (cilist->fmt == CI_LISTDIR) ? _ld_write : _wrfmt; 00118 00119 if (iolist->iolfirst == 0) { 00120 cup = css->f_cu; 00121 /* 00122 * Copy the user's error processing options into the unit table 00123 */ 00124 cup->uflag = (cilist->errflag ? _UERRF : 0) | 00125 (cilist->iostat_spec != NULL ? _UIOSTF : 0); 00126 goto data_transfer; 00127 } 00128 00129 /******************************************************************************* 00130 * 00131 * Statement Initialization Section 00132 * 00133 ******************************************************************************/ 00134 00135 errf = (cilist->errflag || cilist->iostatflg); 00136 00137 if (cilist->fmt == CI_LISTDIR) 00138 iost = T_WLIST; 00139 else if (cilist->dflag) 00140 iost = T_WDF; 00141 else 00142 iost = T_WSF; 00143 00144 css->u.fmt.freefmtbuf = 0; 00145 css->u.fmt.freepfmt = 0; 00146 css->u.fmt.tempicp = NULL; 00147 00148 /* Check if we're doing internal I/O or external I/O */ 00149 00150 if (cilist->internal) { /* If internal I/O */ 00151 STMT_BEGIN(-1, 1, iost, NULL, css, cup); 00152 cup->uft90 = 1; /* set F90 mode for internal file */ 00153 #if !defined(__mips) 00154 cup->ufcompat = 2; /* set cf90 on internal file */ 00155 cup->ufunilist = 0; 00156 cup->ufcomsep = 0; 00157 cup->ufcomplen = 0; 00158 cup->ufrptcnt = 0; 00159 cup->ufnegzero = 1; /* set default write of -0.0 */ 00160 #elif defined(_LITTLE_ENDIAN) 00161 cup->ufcompat = 0; /* set no f90 on internal file */ 00162 cup->ufunilist = 0; 00163 cup->ufcomsep = 0; 00164 cup->ufcomplen = 0; 00165 cup->ufrptcnt = 0; 00166 cup->ufnegzero = 1; /* set default write of -0.0 */ 00167 #else 00168 cup->ufcompat = 4; /* set irixf90 on internal file */ 00169 cup->ufunilist = 0; 00170 cup->ufcomsep = 0; 00171 cup->ufcomplen = 0; 00172 cup->ufrptcnt = 0; 00173 cup->ufnegzero = 1; /* set default write of -0.0 */ 00174 #endif 00175 } 00176 else { /* Else external I/O */ 00177 if (cilist->uflag == CI_UNITASTERK) 00178 unum = STDOUT_U; 00179 else 00180 unum = *cilist->unit.wa; 00181 00182 STMT_BEGIN(unum, 0, iost, NULL, css, cup); 00183 00184 if (cup == NULL) { /* If not connected */ 00185 int stat; 00186 00187 cup = _imp_open( css, 00188 (cilist->dflag ? DIR : SEQ), 00189 FMT, 00190 unum, 00191 errf, 00192 &stat); 00193 00194 /* 00195 * If the open failed, cup is NULL and stat contains 00196 * the error number. 00197 */ 00198 if (cup == NULL) { 00199 errn = stat; 00200 goto handle_exception; 00201 } 00202 } 00203 } 00204 00205 /* All paths which lead here have set cup to a non-null value */ 00206 00207 assert (cup != NULL); 00208 00209 /* 00210 * Copy the user's error processing options into the unit table 00211 */ 00212 cup->uflag = (cilist->errflag ? _UERRF : 0) | 00213 (cilist->iostat_spec != NULL ? _UIOSTF : 0); 00214 00215 /* Initialize fields in the Fortran statement state structure */ 00216 00217 css->u.fmt.icp = NULL; 00218 css->u.fmt.nonl = 0; 00219 00220 /* Process the format and related specifiers */ 00221 00222 if (cilist->fmt != CI_LISTDIR) { /* If formatted output */ 00223 register int stat; 00224 00225 css->u.fmt.u.fe.fmtbuf = NULL; 00226 css->u.fmt.u.fe.fmtnum = 0; 00227 css->u.fmt.u.fe.fmtcol = 0; 00228 css->u.fmt.u.fe.scale = 0; 00229 css->u.fmt.cplus = 0; 00230 00231 errn = setup_format(css, cup, cilist); 00232 00233 if (errn == 0) { /* If no error, handle ADVANCE specifier */ 00234 00235 stat = _is_nonadv(cilist); 00236 00237 if (stat < 0) /* If invalid ADVANCE specifier */ 00238 errn = FEADVSPC; /* Invalid ADVANCE */ 00239 } 00240 00241 if (errn != 0) 00242 goto handle_exception; 00243 00244 css->u.fmt.nonadv = stat; 00245 } 00246 else { /* Else list-directed output */ 00247 css->u.fmt.u.le.ldwinit = 1; 00248 css->u.fmt.nonadv = 0; 00249 } 00250 00251 /* Set processing functions */ 00252 00253 if (cilist->dflag) { 00254 00255 if (!cup->ok_wr_dir_fmt) 00256 errn = _get_mismatch_error(errf, iost, cup, css); 00257 else { 00258 recn_t recn; /* Record number */ 00259 00260 recn = (recn_t) *cilist->rec_spec; 00261 errarg = recn; 00262 errn = _unit_seek(cup, recn, iost); 00263 } 00264 00265 cup->uend = BEFORE_ENDFILE; 00266 cup->ulinecnt = 0; /* Number of characters written */ 00267 cup->ulinemax = 0; /* Highwater mark */ 00268 cup->ulineptr = cup->ulinebuf;/* Current character position */ 00269 css->u.fmt.endrec = _dw_endrec; 00270 } 00271 else { 00272 00273 if (!cup->ok_wr_seq_fmt) { 00274 errn = _get_mismatch_error(errf, iost, cup, css); 00275 goto handle_exception; 00276 } 00277 00278 if (cilist->internal) { 00279 00280 cup->ulinecnt = 0; /* Number characters written */ 00281 cup->ulinemax = 0; /* Highwater mark */ 00282 00283 css->u.fmt.endrec = _iw_endrec; 00284 00285 if (cilist->uflag == CI_UNITCHAR) { 00286 css->u.fmt.iiae = 1; 00287 css->u.fmt.icp = _fcdtocp(cilist->unit.fcd); 00288 css->u.fmt.icl = _fcdlen (cilist->unit.fcd); 00289 } 00290 else { 00291 DopeVectorType *dv = cilist->unit.dv; 00292 void *newar; 00293 int nocontig = 0; 00294 long extent = 0; 00295 long nbytes = 0; 00296 00297 css->u.fmt.icp = _fcdtocp(dv->base_addr.charptr); 00298 css->u.fmt.icl = _fcdlen (dv->base_addr.charptr); 00299 00300 /* 00301 * check for contiguous array 00302 */ 00303 newar = (void *) NULL; 00304 00305 if (dv->p_or_a && (dv->assoc == 0)) 00306 errn = FEUNOTAL; /* Not allocated/associated */ 00307 else 00308 errn = _cntig_chk(dv, &newar, &nocontig, 00309 &extent, &nbytes); 00310 if (errn > 0) 00311 goto handle_exception; 00312 00313 css->u.fmt.iiae = extent; 00314 00315 if (nocontig) { 00316 css->u.fmt.icp = newar; 00317 css->u.fmt.tempicp = newar; 00318 } 00319 } 00320 00321 cup->uldwsize = css->u.fmt.icl; 00322 00323 /* 00324 * If the size of the internal record is greater 00325 * than the existing line buffer, then realloc() 00326 * another one; else just decrease urecsize. 00327 */ 00328 00329 if (css->u.fmt.icl > cup->urecsize) { 00330 00331 cup->ulinebuf = (long *)realloc(cup->ulinebuf, 00332 sizeof(long) * (css->u.fmt.icl + 00333 1)); 00334 00335 if (cup->ulinebuf == NULL) 00336 errn = FENOMEMY; /* No memory */ 00337 } 00338 00339 cup->urecsize = css->u.fmt.icl; 00340 cup->ulineptr = cup->ulinebuf; 00341 } 00342 else { /* external sequential formatted I/O */ 00343 00344 if (cup->uend != BEFORE_ENDFILE) { 00345 /* 00346 * If positioned after an endfile, and the file 00347 * does not support multiple endfiles, a write 00348 * is invalid. 00349 */ 00350 if (!cup->umultfil && !cup->uspcproc) { 00351 errn = FEWRAFEN; 00352 goto handle_exception; 00353 } 00354 00355 /* 00356 * If a logical endfile record had just been 00357 * read, replace it with a physical endfile 00358 * record before starting the current data 00359 * record. 00360 */ 00361 if ((cup->uend == LOGICAL_ENDFILE) && 00362 !(cup->uspcproc)) { 00363 struct ffsw fst; /* FFIO status block */ 00364 00365 if (XRCALL(cup->ufp.fdc, weofrtn) 00366 cup->ufp.fdc, &fst) < 0) { 00367 errn = fst.sw_error; 00368 goto handle_exception; 00369 } 00370 } 00371 00372 cup->uend = BEFORE_ENDFILE; 00373 } 00374 00375 if (cup->pnonadv && cup->uwrt == 0) { 00376 register int offset; 00377 /* 00378 * A formatted or list-directed write statement 00379 * follows a nonadvancing read. Switch the 00380 * current line (record) from read to write 00381 * mode. Then backspace the file so the 00382 * current record gets written back in place. 00383 */ 00384 00385 offset = cup->ulineptr - cup->ulinebuf; 00386 cup->ulinemax = offset + cup->ulinecnt; 00387 cup->ulinecnt = offset; 00388 cup->uflshptr = cup->ulinebuf; 00389 errn = _unit_bksp(cup); 00390 00391 if (errn != 0) 00392 goto handle_exception; 00393 } 00394 else if (cup->pnonadv == 0) { 00395 /* 00396 * There is no current record (due to a prior 00397 * nonadvancing read or write). Initialize 00398 * the empty line buffer. 00399 */ 00400 cup->ulinecnt = 0; /* Num chars written */ 00401 cup->ulinemax = 0; /* Highwater mark */ 00402 cup->ulineptr = cup->ulinebuf; 00403 cup->uflshptr = cup->ulinebuf; 00404 } 00405 00406 /* 00407 * If list-directed write and there is a current 00408 * record, then truncate the current record at the 00409 * current position and flush it if the current record 00410 * is already beyond uldwsize. 00411 */ 00412 00413 if (cup->pnonadv && cilist->fmt == CI_LISTDIR) 00414 errn = _lw_after_nonadv(css, cup, 00415 cup->uldwsize, 0); 00416 00417 css->u.fmt.endrec = _sw_endrec; 00418 cup->pnonadv = css->u.fmt.nonadv; 00419 } 00420 } 00421 00422 if (errn != 0) 00423 goto handle_exception; 00424 00425 css->u.fmt.leftablim = cup->ulineptr; /* Set left tab limit */ 00426 cup->uwrt = 1; /* Set write mode */ 00427 00428 /******************************************************************************* 00429 * 00430 * Data Transfer Section 00431 * 00432 ******************************************************************************/ 00433 data_transfer: 00434 00435 assert (cup != NULL); /* cup assumed non-NULL */ 00436 00437 errn = _xfer_iolist(css, cup, iolist, xfunc); 00438 00439 if (errn != 0) 00440 goto handle_exception; 00441 00442 if (! iolist->iollast) 00443 return (IO_OKAY); 00444 00445 /****************************************************************************** 00446 * 00447 * Statement Finalization Section 00448 * 00449 ******************************************************************************/ 00450 finalization: 00451 00452 /* Assertion */ 00453 assert ( cup != NULL ); 00454 00455 /* If formatted I/O and no error complete processing */ 00456 00457 /* 00458 * Complete formatted or list-directed output processing. 00459 */ 00460 00461 if (errn == 0) { 00462 errn = xfunc(css, cup, (void *) NULL, &__tip_null, 0L); 00463 00464 if (errn != 0) 00465 goto handle_exception; 00466 00467 if (css->u.fmt.nonadv) 00468 errn = _nonadv_partrec(css, cup); 00469 else 00470 errn = (*css->u.fmt.endrec)(css, cup, 1); 00471 00472 if (errn != 0) 00473 goto handle_exception; 00474 } 00475 00476 if (cilist->fmt != CI_LISTDIR) /* If formatted */ 00477 if (css->u.fmt.freepfmt || css->u.fmt.freefmtbuf) { 00478 00479 /* If we allocated memory for a variable format, free it */ 00480 00481 if (css->u.fmt.freepfmt && css->u.fmt.u.fe.pfmt != NULL) 00482 free(css->u.fmt.u.fe.pfmt); 00483 /* 00484 * If we allocated memory for a noncontiguous format, 00485 * free it. 00486 */ 00487 00488 if (css->u.fmt.freefmtbuf && 00489 css->u.fmt.u.fe.fmtbuf != NULL) 00490 free(css->u.fmt.u.fe.fmtbuf); 00491 } 00492 00493 /* 00494 * If we allocated memory for an internal file, move 00495 * the output file from the temporary array to the 00496 * noncontiguous array and free the temporary array. 00497 */ 00498 00499 if (cilist->internal && css->u.fmt.tempicp != NULL) { 00500 (void) _unpack_arry (css->u.fmt.tempicp, cilist->unit.dv); 00501 free(css->u.fmt.tempicp); 00502 } 00503 00504 out_a_here: 00505 00506 /* Set IOSTAT variable to 0 if no error, >0 error code otherwise */ 00507 00508 if (cilist->iostat_spec != NULL) 00509 *(cilist->iostat_spec) = errn; 00510 00511 STMT_END(cup, TF_WRITE, NULL, css); /* Unlock unit */ 00512 00513 /* Return proper status */ 00514 00515 return (retval); 00516 00517 /* 00518 * We put the error handling stuff here to reduce its impact when 00519 * no errors are generated. If we jump here, errn is set to a nonzero 00520 * error, eor, or endfile status code. 00521 */ 00522 handle_exception: 00523 retval = IO_ERR; 00524 00525 if (! cilist->errflag && ! cilist->iostatflg) 00526 _ferr(css, errn, errarg); 00527 00528 if (cup == NULL) 00529 goto out_a_here; 00530 00531 goto finalization; 00532 }