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/frwd.c 92.3 09/29/99 19:50:24" 00039 00040 #include <errno.h> 00041 #include <fortran.h> 00042 #include <liberrno.h> 00043 #ifdef _ABSOFT 00044 #include <stdlib.h> 00045 #endif 00046 #include <cray/nassert.h> 00047 #include "fio.h" 00048 00049 #include <stdlib.h> 00050 00051 #define TBFSZ (4096 * sizeof(long)) /* Size of temporary buffer (bytes) */ 00052 00053 static const _f_int bitoff = 0; 00054 static const _f_int stride = 1; 00055 00056 /* 00057 * _frwd 00058 * Read binary data from one record of a Fortran file. 00059 * 00060 * Side effects 00061 * 00062 * Increments cup->urecpos by the change in bit position within 00063 * the record, including pad bits. 00064 * 00065 * Sets *status as follows: 00066 * 00067 * CNT - if the requested number of items were read, and 00068 * more data remains in the current record (if 00069 * the file has records). 00070 * EOR - if all remaining data in the current record was 00071 * read by this request. 00072 * EOF - if a physical EOF mark was read and no data 00073 * preceded the EOF mark. 00074 * EOD - if the end-of-data mark was reached and no data 00075 * was read. 00076 * 00077 * Return value 00078 * The number of items read. -1 on error with errno set to 00079 * the error code. 00080 * 00081 * Note 00082 * If a nonzero amount of data was read and an EOF mark or the 00083 * end of file was encountered before reading the full amount 00084 * of data requested and before encountering EOR, CNT status is 00085 * returned. This is not well supported because we never detect 00086 * that we processed the EOF. However, no FFIO layers currently 00087 * support embedded EOF marks inside a record. 00088 */ 00089 00090 long 00091 _frwd( 00092 unit *cup, /* Unit pointer */ 00093 void *uda, /* User data address */ 00094 type_packet *tip, /* Type information packet */ 00095 int mode, /* FULL or PARTIAL record mode */ 00096 int *ubcret, /* If non-NULL, pointer to unused bit count in 00097 * the last item. This is both an input and 00098 * output parameter. On input it enables the 00099 * caller to request an arbitrary number of 00100 * bits. On output it reflects the actual data 00101 * transfer. 00102 * NOTE: Normal item alignment (normally 00103 * forced to word boundaries) is 00104 * disabled when this parameter is 00105 * passed. */ 00106 long *wr, /* If non-NULL, pointer to number of items read. 00107 * This is an output parameter. It is useful 00108 * because it is possible to have an error 00109 * return, but still return data. This 00110 * parameter is set only if an error is 00111 * encountered with data being delivered. It 00112 * is currently only set for FFIO files where 00113 * foreign data conversion is not active. */ 00114 int *status) /* assigned on return to CNT, EOR, EOF, or EOD*/ 00115 { 00116 register int fdsize; /* Item size (bits) in file */ 00117 register int padbyts; 00118 register long elsize; 00119 register long items; 00120 register ftype_t type; /* Fortran data type */ 00121 register size_t breq; 00122 register ssize_t ret; 00123 register int64 totbits; 00124 int padubc; 00125 int ubc; 00126 _f_int icount; 00127 00128 /* Assertions */ 00129 00130 #ifdef _UNICOS 00131 assert ( _numargs() == 7 ); 00132 #endif 00133 assert ( mode == FULL || mode == PARTIAL ); 00134 assert ( tip != NULL ); 00135 assert ( status != NULL ); 00136 00137 type = tip->type90; 00138 elsize = tip->elsize; 00139 items = tip->count; 00140 breq = elsize * items; /* bytes requested */ 00141 padbyts = 0; 00142 padubc = 0; 00143 ubc = 0; 00144 /* 00145 * If a ubc word is passed, this call is asking for typeless data; no 00146 * data conversion will be done. The ubcret and wr arguments are used 00147 * by CALL READ/READP. 00148 */ 00149 if (ubcret != NULL) { 00150 if ((*ubcret & 7) != 0 && cup->ufs != FS_FDC) { 00151 errno = FEUBCINV; 00152 return(IOERR); 00153 } 00154 if (type != DVTYPE_TYPELESS) { 00155 errno = FEINTUNK; 00156 return(IOERR); 00157 } 00158 /* 00159 * Adjust breq for ubc input, which can be 0-63 00160 */ 00161 breq -= *ubcret >> 3; 00162 ubc = *ubcret & 7; 00163 } 00164 #if NUMERIC_DATA_CONVERSION_ENABLED 00165 else { 00166 /* 00167 * Pad word-aligned numeric data on word boundaries within 00168 * the record for CRI and some foreign data formats. Note 00169 * that the elsize expression needs to be cleaned up to be 00170 * something like: external_size > granularity. 00171 */ 00172 if ((cup->urecpos & cup->ualignmask) != 0 && 00173 type != DVTYPE_ASCII && 00174 items > 0 && 00175 #if defined(__mips) || defined(_LITTLE_ENDIAN) 00176 elsize > 2 ) { 00177 #else 00178 elsize > 4 ) { 00179 #endif 00180 00181 long blanks; 00182 COMPADD(cup, padbyts, padubc, blanks); 00183 } 00184 } 00185 #endif /* NUMERIC_DATA_CONVERSION_ENABLED */ 00186 00187 cup->ulastyp = type; 00188 00189 *status = CNT; /* default return status */ 00190 /* 00191 * According to the file structure make the appropriate 00192 * low level read request. 00193 */ 00194 switch ( cup->ufs ) { 00195 00196 case STD: 00197 /* 00198 * If the number of items to read is zero return to caller. 00199 * Unicos binary files have no record structure. Except for 00200 * an end of file, a read request always returns CNT status. 00201 */ 00202 if (items == 0) 00203 return(0); 00204 00205 ret = 1; 00206 00207 if (padbyts > 0) { /* Flush a few bytes */ 00208 int dummy; 00209 00210 ret = fread(&dummy, 1, padbyts, cup->ufp.std); 00211 00212 if (ret > 0) 00213 cup->urecpos += (uint64)ret << 3; 00214 00215 } 00216 if (ret > 0) /* don't continue if last read failed. */ 00217 ret = fread(uda, 1, breq, cup->ufp.std ); 00218 00219 if (ret == 0) { 00220 if ( ferror(cup->ufp.std) ) { 00221 if (errno == 0) 00222 errno = FESTIOER; 00223 return(IOERR); 00224 } 00225 *status = EOD; 00226 return(0); 00227 } 00228 /* 00229 * If the read produced an integral number of items, return. 00230 * else allow partial items only for typeless. 00231 */ 00232 icount = ret / elsize; 00233 cup->urecpos = cup->urecpos + (uint64) (ret << 3); 00234 00235 if ((ret % elsize) != 0) 00236 if (type == DVTYPE_TYPELESS) { 00237 00238 icount = icount + 1; 00239 00240 if (ubcret != NULL) 00241 *ubcret = (elsize - (ret % elsize)) << 3; 00242 } 00243 else 00244 if (icount == 0) { 00245 errno = FERDPEOR; 00246 return(IOERR); 00247 } 00248 00249 break; 00250 00251 case FS_FDC: 00252 /* 00253 * Align the FD to a word boundary if required. 00254 */ 00255 00256 if (padbyts > 0) { 00257 long paddval; 00258 00259 ret = XRCALL(cup->ufp.fdc, readrtn) cup->ufp.fdc, 00260 CPTR2BP(&paddval), padbyts, &cup->uffsw, 00261 PARTIAL, &padubc); 00262 00263 if (ret != padbyts || FFSTAT(cup->uffsw) != FFCNT) { 00264 00265 if (ret < 0) { 00266 errno = cup->uffsw.sw_error; 00267 return(IOERR); 00268 } 00269 00270 *status = FF2FTNST(FFSTAT(cup->uffsw)); 00271 00272 return(0); 00273 } 00274 00275 cup->urecpos += ((uint64)ret << 3) - padubc; 00276 } 00277 /* 00278 * If no conversion to be done, just read in the data 00279 */ 00280 if (tip->cnvindx == 0) { 00281 register short erret; 00282 /* 00283 * read in the data 00284 */ 00285 ret = XRCALL(cup->ufp.fdc, readrtn) cup->ufp.fdc, 00286 CPTR2BP(uda), breq, 00287 &cup->uffsw, mode, &ubc); 00288 00289 *status = FF2FTNST(FFSTAT(cup->uffsw)); 00290 erret = 0; 00291 00292 if (*status == EOR) 00293 cup->ulastyp = DVTYPE_TYPELESS; 00294 00295 if (ret < 0) { /* if an error */ 00296 00297 errno = cup->uffsw.sw_error; 00298 00299 if (errno == FETAPUTE) { 00300 ret = cup->uffsw.sw_count; 00301 erret = 1; 00302 } 00303 else 00304 return(IOERR); 00305 } 00306 else 00307 if (ret == 0) 00308 return(0); 00309 /* 00310 * Data was returned (ret > 0), process it 00311 * 00312 * If the read produced an integral number of items, 00313 * then return. Else allow partial items only for 00314 * typeless. 00315 */ 00316 totbits = ((uint64)ret << 3) - ubc; 00317 cup->urecpos = cup->urecpos + totbits; 00318 icount = totbits / (elsize << 3); 00319 00320 if (type == DVTYPE_TYPELESS) { 00321 00322 if ((((uint64)icount*elsize) << 3) != totbits) { 00323 00324 icount = icount + 1; 00325 00326 if (ubcret != NULL) 00327 *ubcret = (elsize << 3) - 00328 (totbits % (elsize << 3)); 00329 } 00330 00331 if (wr != NULL) 00332 *wr = icount; 00333 } 00334 else 00335 if (icount == 0) { 00336 errno = FERDPEOR; 00337 erret = 1; 00338 } 00339 00340 if (erret == 1) 00341 return(IOERR); 00342 00343 goto done; /* Return number of items read */ 00344 } 00345 00346 #if NUMERIC_DATA_CONVERSION_ENABLED 00347 /* 00348 * Process numeric or character conversion. 00349 */ 00350 { 00351 int (* cvt_fun)(); /* Conversion function */ 00352 _f_int dctype; 00353 char tbuf[TBFSZ]; /* Temporary buffer */ 00354 char *bptr; /* Buffer pointer */ 00355 00356 cvt_fun = __fndc_ncfunc[tip->cnvindx].to_native; 00357 00358 #if !defined(__mips) && !defined(_LITTLE_ENDIAN) 00359 if (!_loaded(cvt_fun)) { 00360 errno = FELDDCNV; 00361 return(IOERR); 00362 } 00363 #endif 00364 00365 fdsize = tip->extlen; 00366 dctype = tip->cnvtype; 00367 00368 /* 00369 * Point the pointer to the tail end of the buffer by 00370 * calculating the total bit count, and then rounding down 00371 * to a word boundary. Note that fdsize is the size of 00372 * each byte for type==DVTYPE_ASCII, so we must multiply by 00373 * elsize to get the real total bit count. 00374 */ 00375 if (fdsize == 0) { 00376 errno = FDC_ERR_NCVRT; 00377 return(IOERR); 00378 } 00379 00380 totbits = items * fdsize; /* Bit size of foreign data to 00381 * be read from the file. */ 00382 00383 if (type == DVTYPE_ASCII) 00384 totbits = totbits * tip->elsize; 00385 00386 if (ubcret != NULL) 00387 totbits = totbits - *ubcret; 00388 00389 /* 00390 * Round pointer down to the next byte if numeric conversion 00391 * is requested. 00392 */ 00393 00394 bptr = tbuf; /* Assume data will fit in temporary buffer */ 00395 breq = (totbits + 7) >> 3; 00396 ubc = ((uint64)breq << 3) - totbits; 00397 00398 if (breq > TBFSZ) { 00399 bptr = (char *) malloc(breq); 00400 00401 if (bptr == NULL) { /* malloc() failed! */ 00402 errno = FENOMEMY; 00403 return(IOERR); 00404 } 00405 } 00406 /* 00407 * read in the data 00408 */ 00409 ret = XRCALL(cup->ufp.fdc, readrtn) cup->ufp.fdc, 00410 CPTR2BP(bptr), breq, 00411 &cup->uffsw, mode, &ubc); 00412 00413 *status = FF2FTNST(FFSTAT(cup->uffsw)); 00414 00415 if (*status == EOR) 00416 cup->ulastyp = DVTYPE_TYPELESS; 00417 00418 if (ret <= 0) { /* If an error or no data */ 00419 register long stat = EOR; 00420 00421 if (bptr != tbuf) /* Free allocated space */ 00422 free(bptr); 00423 00424 if (ret < 0) { 00425 errno = cup->uffsw.sw_error; 00426 stat = IOERR; 00427 } 00428 00429 return(stat); 00430 } 00431 00432 /* 00433 * If the read produced an integral number of items, return. 00434 * else diagnose partial items. 00435 */ 00436 totbits = ((uint64)ret << 3) - ubc; 00437 icount = totbits / fdsize; 00438 00439 if (((int64)icount * fdsize) != totbits) { 00440 if (bptr != tbuf) /* Free allocated space */ 00441 free(bptr); 00442 /* partial items with conversion on is weird */ 00443 errno = FDC_ERR_PITM; 00444 return(IOERR); 00445 } 00446 /* 00447 * Do the numeric conversion 00448 */ 00449 { 00450 register _f_int numerr; /* Error code */ 00451 #ifdef _CRAY 00452 _fcd craychr; /* Only used for char. conversion */ 00453 00454 craychr = _cptofcd((char *)uda, items); 00455 #endif 00456 00457 if (tip->newfunc) { 00458 _f_int flen; /* Foreign length, in bits */ 00459 _f_int nlen; /* Native length, in bits */ 00460 00461 flen = fdsize; 00462 nlen = tip->intlen; 00463 00464 numerr = cvt_fun(&dctype, &icount, (void *) bptr, 00465 &bitoff, (void *)uda, &stride, &nlen, 00466 &flen, 00467 #ifdef _CRAY 00468 craychr); 00469 #else 00470 (char *)uda, items); 00471 #endif 00472 } 00473 else { 00474 00475 numerr = cvt_fun(&dctype, &icount, (void *)bptr, 00476 &bitoff, (void *)uda, &stride, 00477 #ifdef _CRAY 00478 craychr); 00479 #else 00480 (char *)uda, items); 00481 #endif 00482 } 00483 00484 if (bptr != tbuf) /* Free allocated space */ 00485 free(bptr); 00486 00487 if (numerr != 0) { 00488 errno = (numerr < 0) ? FEINTUNK : FDC_ERR_NCVRT; 00489 return(IOERR); 00490 } 00491 } 00492 } 00493 00494 cup->urecpos += totbits; 00495 #endif /* NUMERIC_DATA_CONVERSION_ENABLED */ 00496 00497 break; 00498 00499 case FS_AUX: 00500 errno = FEMIXAUX; 00501 icount = IOERR; 00502 break; 00503 00504 default: 00505 errno = FEINTFST; 00506 icount = IOERR; 00507 break; 00508 } /* switch */ 00509 00510 done: 00511 return(icount); /* Return number of items read or status */ 00512 }