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/frch.c 92.2 06/22/99 11:11:33" 00039 00040 #include <errno.h> 00041 #include <liberrno.h> 00042 #if defined(_SOLARIS) || (defined(_LITTLE_ENDIAN) && !defined(__sv2)) 00043 #include <stdio.h> 00044 #endif 00045 #include <stdlib.h> 00046 #include <string.h> 00047 #include "fio.h" 00048 #ifdef _ABSOFT 00049 #include "ac_sysdep.h" 00050 #else /* NOT _ABSOFT */ 00051 00052 #if defined(_LITTLE_ENDIAN) && !defined(__sv2) 00053 #ifndef FILE_CNT 00054 #define FILE_CNT(__f) (__f)->_IO_write_end - (__f)->_IO_write_ptr 00055 #endif 00056 00057 #ifndef FILE_PTR 00058 #define FILE_PTR(__f) (__f)->_IO_write_ptr 00059 #endif 00060 00061 #ifndef FILE_FLAG 00062 #define FILE_FLAG(__f) (__f)->_flags 00063 #endif 00064 00065 #ifndef IOWRT 00066 #define IOWRT = _IO_CURRENTLY_PUTTING 00067 #endif 00068 #ifndef IOREAD 00069 #define IOREAD = _IO_CURRENTLY_APPENDING 00070 #endif 00071 #ifndef IORW 00072 #define IORW = _IO_TIED_PUTGET 00073 #endif 00074 00075 #else /* LITTLE_ENDIAN and not sv2 */ 00076 #ifndef FILE_CNT 00077 #define FILE_CNT(__f) (__f)->_cnt 00078 #endif 00079 00080 #ifndef FILE_PTR 00081 #define FILE_PTR(__f) (__f)->_ptr 00082 #endif 00083 00084 #ifndef FILE_FLAG 00085 #define FILE_FLAG(__f) (__f)->_flag 00086 #endif 00087 00088 #endif /* LITTLE_ENDIAN and not sv2 */ 00089 00090 #endif /* _ABSOFT */ 00091 00092 #ifdef _SOLARIS 00093 #undef getc 00094 #ifndef MIN 00095 #define MIN(x,y) (((x) < (y)) ? (x) : (y)) 00096 #endif 00097 #endif /* end _SOLARIS */ 00098 #ifdef _CRAY 00099 extern int G@INTIO; 00100 #define _GINTIO G@INTIO 00101 #else 00102 extern int _intio; 00103 #define _GINTIO _intio 00104 #endif 00105 /* 00106 * _frch 00107 * Read and unpack characters from the current record of a file. 00108 * 00109 * Arguments 00110 * cup: unit pointer 00111 * uda: character pointer to user's data area 00112 * chars: Number of characters to read 00113 * mode: Full or partial mode flag 00114 * status: Address of caller's status word. 00115 * 00116 * Side effects 00117 * 00118 * Sets *status as follows: 00119 * 00120 * CNT - if the requested number of items were read, and 00121 * more data remains in the current record (if 00122 * the file has records). 00123 * EOR - if all remaining data in the current record was 00124 * read by this request. 00125 * EOF - if a physical endfile record was read and no data 00126 * preceded the endfile record. 00127 * EOD - if the end-of-data mark was reached and no data 00128 * preceded the the end-of-data. 00129 * 00130 * Return value 00131 * The number of characters read from the current record. The 00132 * record delimitting character (for example a newline) is not 00133 * counted. An error results in a -1 return value with errno set 00134 * to the error code. 00135 * 00136 * Note 00137 * 00138 * If a nonzero amount of data was read and an EOF mark or the 00139 * end of file (EOD) was encountered before reading the full amount 00140 * of data requested and before encountering EOR, beware that 00141 * CNT status is returned. 00142 */ 00143 00144 long 00145 _frch( 00146 unit *cup, 00147 long *uda, 00148 long chars, 00149 int mode, 00150 long *status) 00151 { 00152 register int bytsiz; 00153 register int chr; 00154 register long nchr; 00155 register long ncnt; 00156 unsigned char tbuf[TBUFSZB], *tp; /* Line buffer */ 00157 FILE *fptr; 00158 struct ffsw stat; 00159 struct fdinfo *fio; 00160 #if defined(_SOLARIS) || (defined(_LITTLE_ENDIAN) && !defined(__sv2)) 00161 register long count; 00162 char *tpinterim; 00163 #endif 00164 00165 switch (cup->ufs) { 00166 00167 case FS_TEXT: 00168 case STD: 00169 fptr = cup->ufp.std; 00170 /* 00171 * Switch the FILE structure into read mode 00172 */ 00173 #if !defined(_LITTLE_ENDIAN) || (defined(_LITTLE_ENDIAN) && defined(__sv2)) 00174 if ((FILE_FLAG(fptr) & (_IOREAD | _IORW)) == _IORW) { 00175 00176 if (FILE_FLAG(fptr) & _IOWRT) 00177 (void) fseek(fptr, 0, SEEK_CUR); 00178 00179 FILE_FLAG(fptr) |= _IOREAD; 00180 } 00181 #endif 00182 /* 00183 * Loop on getc until the character count has been 00184 * exhausted, an end of file is encountered, or end 00185 * of record. 00186 */ 00187 nchr = 0; 00188 #if defined(_SOLARIS) || (defined(_LITTLE_ENDIAN) && !defined(__sv2)) 00189 while (nchr < chars) { 00190 fill: 00191 errno = 0; 00192 count = chars - nchr; 00193 tp = tbuf; 00194 count = MIN(TBUFSZB, (count + 1)); 00195 tpinterim = fgets((char *)tp, count, fptr); 00196 if (tpinterim == NULL) { 00197 /* 00198 * Search for the newline char in the buffer, but 00199 * search only the number of characters left in 00200 * the request, plus one in case it is the 00201 * newline (if it is in the buffer). If we find 00202 * newline, we're done. 00203 */ 00204 /* EOF here means incomplete record. */ 00205 if (ferror(fptr)) { 00206 if ( errno == EINTR && _GINTIO == 0) { 00207 clearerr(fptr); 00208 goto fill; 00209 } 00210 if (errno == 0) 00211 errno = FESTIOER; 00212 return(IOERR); 00213 } 00214 /* 00215 * If nchr > zero, file has no newline. 00216 * Make sure we handle it properly. 00217 */ 00218 if (feof(fptr)) { 00219 if (nchr == 0) { 00220 *status = EOD; 00221 return(0); 00222 } 00223 *status = CNT; 00224 return(nchr); 00225 } 00226 } else { 00227 unsigned char *tmpptr; 00228 ncnt = count - 1; 00229 tmpptr = memchr(tp, '\n', ncnt); 00230 if (tmpptr != NULL) { /* eor */ 00231 *status = EOR; 00232 ncnt = tmpptr - tp; 00233 nchr += ncnt; 00234 _unpack(tp, uda, ncnt, -1); 00235 /* Return number of chars read */ 00236 return(nchr); 00237 } 00238 _unpack(tp, uda, ncnt, -1); 00239 nchr += ncnt; 00240 uda += ncnt; 00241 00242 /* go refill the buffer */ 00243 } 00244 } 00245 #else 00246 while (nchr < chars) { 00247 if (FILE_CNT(fptr) <= 0) { 00248 fill: 00249 errno = 0; 00250 chr = _filbuf(fptr); 00251 00252 /* EOF here means incomplete record. */ 00253 00254 if (chr == EOF) { 00255 00256 if (ferror(fptr)) { 00257 00258 if ( errno == EINTR && 00259 _GINTIO == 0 ) { 00260 clearerr(fptr); 00261 goto fill; 00262 } 00263 00264 if (errno == 0) 00265 errno = FESTIOER; 00266 00267 return(IOERR); 00268 } 00269 /* 00270 * If nchr > zero, file has no newline. 00271 * Make sure we handle it properly. 00272 */ 00273 if (nchr == 0) { 00274 *status = EOD; 00275 return(0); 00276 } 00277 00278 *status = CNT; 00279 return(nchr); 00280 } 00281 /* 00282 * Put character returned by filbuf() back 00283 */ 00284 FILE_CNT(fptr)++; 00285 FILE_PTR(fptr)--; 00286 } 00287 /* 00288 * Search for a newline char in the buffer, but search 00289 * only the number of characters left in the request, 00290 * plus one in case it is the newline (if it is in 00291 * the buffer). If we find the newline, we're done. 00292 */ 00293 if ((chars - nchr) < FILE_CNT(fptr)) { 00294 ncnt = chars - nchr; 00295 tp = memchr(FILE_PTR(fptr), '\n', ncnt + 1); 00296 } 00297 else { 00298 ncnt = FILE_CNT(fptr); /* assume no EOR yet */ 00299 tp = memchr(FILE_PTR(fptr), '\n', ncnt); 00300 } 00301 00302 if (tp != NULL) { /* Found end of record */ 00303 00304 *status = EOR; 00305 ncnt = tp - FILE_PTR(fptr); 00306 nchr += ncnt; 00307 00308 _unpack((char *)FILE_PTR(fptr), uda, ncnt, -1); 00309 00310 FILE_CNT(fptr) -= ncnt + 1; 00311 FILE_PTR(fptr) += ncnt + 1; 00312 00313 return(nchr); /* Return number of characters read */ 00314 } 00315 00316 _unpack((char *)FILE_PTR(fptr), uda, ncnt, -1); 00317 00318 FILE_CNT(fptr) -= ncnt; 00319 FILE_PTR(fptr) += ncnt; 00320 nchr += ncnt; 00321 uda += ncnt; 00322 00323 /* go refill the buffer */ 00324 } 00325 #endif 00326 /* 00327 * Get the next character to see if at end of record. 00328 * Set the user's status word accordingly. 00329 */ 00330 chr = getc(fptr); 00331 00332 *status = CNT; 00333 00334 if (chr == '\n' ) { 00335 *status = EOR; 00336 return(nchr); /* Return number of characters read */ 00337 } 00338 /* 00339 * We are not at end of record. Thus if reading in full 00340 * record mode skip until EOR is found. If reading in 00341 * partial record mode, unget the last character read. 00342 */ 00343 if (mode == FULL) 00344 #if defined(_SOLARIS) || (defined(_LITTLE_ENDIAN) && !defined(__sv2)) 00345 { 00346 fill2: 00347 count = TBUFSZB; 00348 tp = tbuf; 00349 tpinterim = fgets((char *)tp, count, fptr); 00350 if (tpinterim == NULL) { 00351 /* EOF means incomplete record. */ 00352 if (ferror(fptr)) { 00353 if ( errno == EINTR && _GINTIO == 0 ) { 00354 clearerr(fptr); 00355 goto fill2; 00356 } 00357 } 00358 /* Return number of chars read. */ 00359 return(nchr); 00360 } else { 00361 unsigned char *tmpptr; 00362 ncnt = count - 1; 00363 tmpptr = memchr(tp, '\n', ncnt); 00364 if (tmpptr != NULL) { /* Found eor */ 00365 /* Return number of chars read */ 00366 return(nchr); 00367 } else 00368 goto fill2; 00369 } 00370 } 00371 #else 00372 while (1) { 00373 if (FILE_CNT(fptr) <= 0) { 00374 fill2: 00375 chr = _filbuf(fptr); 00376 00377 /* EOF here means incomplete record. */ 00378 00379 if (chr == EOF) { 00380 00381 if (ferror(fptr)) { 00382 00383 if ( errno == EINTR && 00384 _GINTIO == 0 ) { 00385 clearerr(fptr); 00386 goto fill2; 00387 } 00388 00389 } 00390 00391 /* Return number of characters read */ 00392 00393 return(nchr); 00394 } 00395 00396 FILE_CNT(fptr)++; 00397 FILE_PTR(fptr)--; 00398 } 00399 00400 tp = memchr(FILE_PTR(fptr), '\n', FILE_CNT(fptr)); 00401 00402 if (tp != NULL) { 00403 00404 tp++; 00405 FILE_CNT(fptr) -= tp - FILE_PTR(fptr); 00406 FILE_PTR(fptr) = tp; 00407 00408 return(nchr); 00409 } 00410 else 00411 FILE_CNT(fptr) = 0; 00412 } 00413 #endif 00414 else { 00415 ungetc ((char) chr, fptr); 00416 } 00417 00418 return(nchr); /* return number of character read */ 00419 00420 case FS_FDC: 00421 nchr = 0; 00422 fio = cup->ufp.fdc; 00423 /* 00424 * If no conversion is to be done, or no characters requested 00425 * (usually for null request, FULL mode), make it simple and direct. 00426 */ 00427 if (cup->ucharset == 0 || chars == 0) { 00428 register long breq; 00429 register int ffstat; 00430 register int ret; 00431 /* 00432 * If file is direct access, we know that all reads are 00433 * going to be whole records in FULL mode. We also 00434 * know that the open code would not let us get this far 00435 * if we were not dealing with a stream layer. 00436 */ 00437 00438 breq = chars; 00439 00440 ret = XRCALL(fio, readcrtn) fio, CPTR2BP(uda), 00441 breq, &stat, mode); 00442 00443 if (ret < 0) { 00444 errno = stat.sw_error; 00445 return(IOERR); 00446 } 00447 00448 ffstat = FFSTAT(stat); 00449 00450 if (!cup->useq && !cup->ublkd && ffstat == FFCNT) 00451 ffstat = FFEOR; 00452 00453 *status = FF2FTNST(ffstat); 00454 nchr = ret; 00455 00456 return(nchr); /* Return number of characters read */ 00457 } 00458 /* 00459 * Get proper byte size (might not be 8-bits if doing conversion). 00460 */ 00461 00462 #if NUMERIC_DATA_CONVERSION_ENABLED 00463 bytsiz = __fndc_charsz[cup->ucharset]; 00464 #else 00465 bytsiz = 8; 00466 #endif 00467 FFSTAT(cup->uffsw) = FFCNT; 00468 *status = CNT; 00469 00470 while (nchr < chars && FFSTAT(cup->uffsw) != FFEOR) { 00471 register long bgot; 00472 register long breq; 00473 register long padc; 00474 register int ret; 00475 register long totbits; 00476 int ubc; 00477 /* 00478 * Calculate the number of bits that need to be taken 00479 * from the foreign data stream. 00480 * 00481 * ncnt = number of resultant bytes 00482 */ 00483 ncnt = chars - nchr; 00484 00485 if (ncnt > TBUFSZB) 00486 ncnt = TBUFSZB; 00487 00488 totbits = bytsiz * ncnt; /* bit count */ 00489 breq = (totbits + 7) >> 3; /* full 8-bit bytes */ 00490 ubc = (breq << 3) - totbits;/* unused bits */ 00491 00492 ret = XRCALL(fio, readrtn) fio, CPTR2BP(tbuf), 00493 breq, &cup->uffsw, PARTIAL, &ubc); 00494 00495 if (ret < 0) { /* if an error */ 00496 errno = cup->uffsw.sw_error; 00497 return(IOERR); 00498 } 00499 00500 /* if end of file */ 00501 00502 if (ret == 0) { 00503 if (nchr == 0) 00504 *status = FF2FTNST(FFSTAT(stat)); 00505 return(nchr); /* Return number of characters read */ 00506 } 00507 00508 /* 00509 * how many bits did we get? Convert back to foreign 00510 * character count. 00511 */ 00512 totbits = (ret << 3) - ubc; 00513 bgot = totbits / bytsiz; /* foreign bytes */ 00514 ubc = totbits - (bgot * bytsiz); 00515 00516 if (ubc != 0) { 00517 errno = FEINTUNK; 00518 return(IOERR); 00519 } 00520 00521 padc = 0; 00522 00523 if (FFSTAT(cup->uffsw) == FFEOR) { 00524 padc = chars - (bgot + nchr); 00525 *status = EOR; 00526 } 00527 00528 if (_fdc_unpackc(tbuf, &uda[nchr], bgot, padc, 00529 cup->ucharset) < 0) { 00530 return(IOERR); 00531 } 00532 00533 nchr += bgot; 00534 } 00535 00536 /* check for null request, non-EOR */ 00537 00538 if (FFSTAT(cup->uffsw) == FFCNT && mode == FULL) { 00539 register int ret; 00540 int ubc; 00541 00542 ret = XRCALL(fio, readrtn) fio, CPTR2BP(tbuf), 0, 00543 &cup->uffsw, FULL, &ubc); 00544 00545 if (ret < 0) { /* if an error */ 00546 errno = cup->uffsw.sw_error; 00547 return(IOERR); 00548 } 00549 } 00550 return(nchr); 00551 00552 case FS_AUX: 00553 errno = FEMIXAUX; 00554 return(IOERR); 00555 00556 default: 00557 errno = FEINTFST; 00558 return(IOERR); 00559 } 00560 }