/* * _sds_fr_mem moves data into SDS from user memory. * * Returns 0 on normal return, or else -1 with error code in errno. */ _sds_fr_mem( bitptr sdsaddr, /* SDS bit address where data will be received */ bitptr ubuf, /* user buffer containing data */ int nbits /* number of bits to move */ ) { long sds_bit_offset; char *ucaddr; long *uwaddr; int ret; if (nbits & (BITPBLOCK - 1)) { errno = FDC_ERR_GRAN; /* must be block multiple */ return -1; } ucaddr = BPTR2CP(ubuf); uwaddr = BPTR2WP(ubuf); if (ucaddr != (char*)uwaddr) { errno = FDC_ERR_SDSWB; /* must be word-aligned */ return -1; } sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); if (sds_bit_offset & (BITPBLOCK - 1)) { errno = FDC_ERR_GRAN; /* must be block multiple */ return -1; } ret = sswrite(uwaddr, BITS2BLOCKS(sds_bit_offset), BITS2BLOCKS(nbits)); if (ret == -1) errno = FDC_ERR_SDSIO; return ret; }
long _fwch( unit *cup, long *uda, long chars, int mode) { register int bytsiz; register long nchr; unsigned char tbuf[TBUFSZB]; /* Line packing buffer */ FILE *fptr; /* * If positioned after an endfile, and the file does not * support multiple endfiles, a write is invalid. */ if (cup->uend && !cup->umultfil && !cup->uspcproc) { errno = FEWRAFEN; return(IOERR); } nchr = 0; switch (cup->ufs) { case FS_TEXT: case STD: fptr = cup->ufp.std; /* switch the FILE structure into write mode */ #if !defined(_LITTLE_ENDIAN) || (defined(_LITTLE_ENDIAN) && defined(__sv2)) if ((FILE_FLAG(fptr) & (_IOWRT | _IORW)) == _IORW) { if (FILE_FLAG(fptr) & _IOREAD) (void) fseek(fptr, 0, SEEK_CUR); FILE_FLAG(fptr) |= _IOWRT; } #endif #if defined(_SOLARIS) || (defined(_LITTLE_ENDIAN) && !defined(__sv2)) while (nchr < chars) { register long count; register int ret; /* Pack chars into temp buffer and write them */ count = chars - nchr; if (count > TBUFSZB) count = TBUFSZB; #ifdef KEY /* Bug 5926 */ count = _pack(&uda[nchr], (char *)tbuf, count, terminator(&mode, nchr, count, chars)); #else /* KEY Bug 5926 */ _pack(&uda[nchr], (char *)tbuf, count, -1); #endif /* KEY Bug 5926 */ ret = fwrite(tbuf, 1, count, fptr); if ( ret != count || ferror(fptr) ) { if ( ret != count || errno == 0) errno = FESTIOER; return(IOERR); } nchr += count; } #else /* If the stream is unbuffered... */ if (FILE_FLAG(fptr) & (_IONBF | _IOLBF)) { while (nchr < chars) { register long count; register long ret; /* Pack chars into temp buffer and write them */ count = chars - nchr; if (count > TBUFSZB) count = TBUFSZB; #ifdef KEY /* Bug 5926 */ count= _pack(&uda[nchr], (char *)tbuf, count, terminator(&mode, nchr, count, chars)); #else /* KEY Bug 5926 */ _pack(&uda[nchr], (char *)tbuf, count, -1); #endif /* KEY Bug 5926 */ ret = fwrite(tbuf, 1, count, fptr); if ( ret != count || ferror(fptr) ) { if ( ret != count || errno == 0) errno = FESTIOER; return(IOERR); } nchr += count; } } else { /* for a buffered stream... */ while (FILE_CNT(fptr) < chars - nchr) { register long count; register int ret; count = FILE_CNT(fptr); /* space left in buffer */ if (count > 0) { /* pack data into the buffer */ _pack(&uda[nchr], (char *)FILE_PTR(fptr), count, -1); FILE_PTR(fptr) += count; FILE_CNT(fptr) = 0; } /* * We set errno to 0 here in case the following * buffer flush fails. UNICOS 8.2 fputc (and * previous) was not X/Open compliant and did * not always set errno when a buffer flush * completed partially due to a disk full * conditon. The zeroing of errno may be * removed when we can assume that the fputc() * from UNICOS and Solaris are X/Open compliant. */ errno = 0; /* * This fputc() will either trigger a buffer * flush or cause the buffer to be allocated * for the first time. */ ret = fputc(uda[nchr + count], fptr); if (ret == EOF && ferror(fptr)) { if (errno == 0) errno = FESTIOER; return(IOERR); } nchr += count + 1; } if (nchr < chars) { /* Put data in buffer */ _pack(&uda[nchr], (char *)FILE_PTR(fptr), chars - nchr, -1); FILE_CNT(fptr) -= chars - nchr; FILE_PTR(fptr) += chars - nchr; } } #endif if (mode == FULL) { register int ret; ret = putc('\n', fptr);; if (ret == EOF && ferror(fptr)) { if (errno == 0) errno = FESTIOER; return(IOERR); } chars++; } return(chars); case FS_FDC: /* * If a logical endfile record had just been read, * replace it with a physical endfile record before * starting the current data record. */ if ((cup->uend == LOGICAL_ENDFILE) && !(cup->uspcproc)) { if (XRCALL(cup->ufp.fdc, weofrtn)cup->ufp.fdc, &cup->uffsw) < 0){ errno = cup->uffsw.sw_error; return(IOERR); } } cup->uend = BEFORE_ENDFILE; if (cup->ucharset == 0) { register long ret; ret = XRCALL(cup->ufp.fdc, writecrtn) cup->ufp.fdc, WPTR2BP(uda), chars, &cup->uffsw, mode); if (ret < 0) { errno = cup->uffsw.sw_error; return(IOERR); } return(chars); } /* * Get proper byte size (might not be 8-bits if doing conversion). */ #if NUMERIC_DATA_CONVERSION_ENABLED bytsiz = __fndc_charsz[cup->ucharset]; #else bytsiz = 8; #endif do { register long breq; register int fulp; register long ncnt; register long ret; int ubc; ncnt = TBUFSZB; breq = 0; ubc = 0; if ((chars - nchr) > 0) { register long totbits; if (ncnt > (chars - nchr)) ncnt = chars - nchr; if (_fdc_packc((char *)tbuf, &uda[nchr], ncnt, cup->ucharset) < 0) { return(IOERR); } totbits = bytsiz * ncnt; /* bit count */ breq = (totbits + 7) >> 3; /* 8-bit bytes */ ubc = (breq << 3) - totbits; } nchr += ncnt; if ((nchr >= chars) && ( mode == FULL )) fulp = FULL; else fulp = PARTIAL; ret = XRCALL(cup->ufp.fdc, writertn) cup->ufp.fdc, CPTR2BP(tbuf), breq, &cup->uffsw, fulp, &ubc); if (ret != breq) { /* if an error */ errno = cup->uffsw.sw_error; return(IOERR); } } while (nchr < chars); return(chars); /* * unsupported structure if not TEXT/STD, or FDC */ default: errno = FEINTFST; return(IOERR); } }
/* * _any_mem_fr_sds moves data into user memory from a secondary data segment (SDS). * * unlike _mem_fr_sds, _any_mem_fr_sds handles moving a number of bits that * may not be a multiple of 512. * * Returns 0 on normal return, or else -1 with error code in errno. */ _any_mem_fr_sds( bitptr ubuf, /* user buffer to receive data */ bitptr sdsaddr, /* SDS bit address of data */ int nbits /* number of bits to move */ ) { int sds_bit_offset; int sds_bit_offset_blk; int rbits; char localbuf[BYTPBLOCK]; bitptr locptr; long *uwaddr; char *ucaddr; sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); if (sds_bit_offset & (BITPBLOCK -1)) { /* The sds address is not on a block boundary. */ /* Read data from sds to a local buffer. Copy the */ /* appropriate part of the local buffer to user's memory. */ sds_bit_offset_blk = (sds_bit_offset & ~(BITPBLOCK - 1)); if(ssread((int *)localbuf, BITS2BLOCKS(sds_bit_offset_blk), 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } rbits = MIN(nbits, BITPBLOCK - (sds_bit_offset - sds_bit_offset_blk)); locptr = CPTR2BP(localbuf); SET_BPTR(locptr, INC_BPTR(locptr, sds_bit_offset - sds_bit_offset_blk)); MOV_BITS(ubuf, locptr, rbits); SET_BPTR(ubuf, INC_BPTR(ubuf, rbits)); nbits -= rbits; SET_BPTR(sdsaddr, INC_BPTR(sdsaddr, rbits)); if (nbits == 0) return(0); /* Verify that our sds address is now on a block boundary */ assert (((SUBT_BPTR(sdsaddr, WPTR2BP(0))) & (BITPBLOCK -1)) == 0); } sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); uwaddr = BPTR2WP(ubuf); ucaddr = BPTR2CP(ubuf); if ((nbits & (BITPBLOCK-1)) || (ucaddr != (char *)uwaddr)){ int left; /* Either we are not reading in a multiple of blocks or */ /* the user's address is not word-aligned. */ /* Round nbits down to a block boundary and */ /* move those to user's memory. */ locptr = CPTR2BP(localbuf); rbits = nbits & ~(BITPBLOCK-1); if (rbits) { if (ucaddr != (char*)uwaddr) { /* ubuf is not word aligned. */ /* Read the data from sds into a local */ /* buffer and copy to the user's memory */ left = rbits; sds_bit_offset_blk = BITS2BLOCKS(sds_bit_offset); while (left > 0) { if (ssread((int *)localbuf, sds_bit_offset_blk, 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } MOV_BITS(ubuf, locptr, BITPBLOCK); SET_BPTR(ubuf, INC_BPTR(ubuf, BITPBLOCK)); SET_BPTR(sdsaddr, INC_BPTR(sdsaddr, BITPBLOCK)); sds_bit_offset_blk++; left-= BITPBLOCK; } } else { if (ssread(uwaddr, BITS2BLOCKS(sds_bit_offset), BITS2BLOCKS(rbits)) == -1) { errno = FDC_ERR_SDSIO; return(-1); } SET_BPTR(ubuf, INC_BPTR(ubuf, rbits)); SET_BPTR(sdsaddr, INC_BPTR(sdsaddr, rbits)); } sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); } /* get last block into local memory and */ /* transfer to user's memory */ if (ssread((int *)localbuf, BITS2BLOCKS(sds_bit_offset), 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } assert((nbits - rbits) < BITPBLOCK); MOV_BITS(ubuf, locptr, nbits - rbits); } else { if(ssread(uwaddr, BITS2BLOCKS(sds_bit_offset), BITS2BLOCKS(nbits)) == -1) { errno = FDC_ERR_SDSIO; return(-1); } } return(0); }
/* * _any_sds_fr_mem moves data into a secondary data segment (SDS) from * user memory * * unlike _sds_fr_mem, _any_sds_fr_mem handles moving a number of bits that * may not be a multiple of 512. * * Returns 0 on normal return, or else -1 with error code in errno. */ _any_sds_fr_mem( bitptr sdsaddr, /* SDS bit address of data */ bitptr ubuf, /* user buffer to receive data */ int nbits /* number of bits to move */ ) { int sds_bit_offset; int sds_bit_offset_blk; int rbits; char localbuf[BYTPBLOCK]; bitptr locptr; long *uwaddr; char *ucaddr; sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); if (sds_bit_offset & (BITPBLOCK -1)) { /* The sds address is not on a block boundary. */ /* Read data from sds to a local buffer. Copy the */ /* user's memory to the appropriate part of the local */ /* buffer, and write it back out to sds. */ sds_bit_offset_blk = (sds_bit_offset & ~(BITPBLOCK - 1)); if (ssread((int *)localbuf, BITS2BLOCKS(sds_bit_offset_blk), 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } rbits = MIN(nbits, BITPBLOCK - (sds_bit_offset - sds_bit_offset_blk)); locptr = CPTR2BP(localbuf); SET_BPTR(locptr, INC_BPTR(locptr, sds_bit_offset - sds_bit_offset_blk)); MOV_BITS(locptr, ubuf, rbits); SET_BPTR(ubuf, INC_BPTR(ubuf, rbits)); nbits -= rbits; if(sswrite((int *)localbuf, BITS2BLOCKS(sds_bit_offset_blk), 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } SET_BPTR(sdsaddr, INC_BPTR(sdsaddr, rbits)); if (nbits == 0) return(0); assert(((SUBT_BPTR(sdsaddr, WPTR2BP(0))) & (BITPBLOCK -1)) == 0); } sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); uwaddr = BPTR2WP(ubuf); ucaddr = BPTR2CP(ubuf); if ((nbits & (BITPBLOCK-1)) || (ucaddr != (char *)uwaddr)){ int left; locptr = CPTR2BP(localbuf); /* round down nbits to a block boundary */ rbits = nbits & ~(BITPBLOCK-1); if (rbits) { if (ucaddr != (char*)uwaddr) { /* ubuf is not word aligned. */ left = rbits; sds_bit_offset_blk = BITS2BLOCKS(sds_bit_offset); while (left > 0) { if( ssread((int *)localbuf, sds_bit_offset_blk, 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } MOV_BITS(locptr, ubuf, BITPBLOCK); SET_BPTR(ubuf, INC_BPTR(ubuf, BITPBLOCK)); if( sswrite((int *)localbuf, sds_bit_offset_blk, 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } SET_BPTR(sdsaddr, INC_BPTR(sdsaddr, BITPBLOCK)); sds_bit_offset_blk++; left-= BITPBLOCK; } } else { if (_sds_fr_mem(sdsaddr, ubuf, rbits) == -1) { return(-1); } SET_BPTR(ubuf, INC_BPTR(ubuf, rbits)); SET_BPTR(sdsaddr, INC_BPTR(sdsaddr, rbits)); } sds_bit_offset = SUBT_BPTR(sdsaddr, WPTR2BP(0)); } /* Get last block into local memory. Merge in user's memory */ /* and write it back out to sds. */ if( ssread((int *)localbuf, BITS2BLOCKS(sds_bit_offset), 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } MOV_BITS(locptr, ubuf, nbits - rbits); if( sswrite((int *)localbuf, BITS2BLOCKS(sds_bit_offset), 1) == -1) { errno = FDC_ERR_SDSIO; return(-1); } } else { if(sswrite(uwaddr, BITS2BLOCKS(sds_bit_offset), BITS2BLOCKS(nbits)) == -1) { errno = FDC_ERR_SDSIO; return(-1); } } return(0); }
static void _rb( FIOSPTR css, /* Current Fortran I/O state */ unit *cup, /* Unit pointer */ _f_int *recmode, /* Mode */ gfptr_t bloc, /* Beginning location */ gfptr_t eloc, /* Ending location */ type_packet *tip) /* Type information packet */ { register int bytshft; register int mode; register long bytes; register long elsize; register long itemlen; register long items; register long stat; register ftype_t type90; int state; char *uda, *udax; #ifdef _CRAYT3D register short shared; register long ntot; register long numleft; long shrd[MAXSH]; #endif if (cup->useq == 0) /* If direct access file */ _ferr(css, FEBIONDA, "BUFFER IN"); if (cup->ufmt) /* If formatted file */ _ferr(css, FEBIONFM, "BUFFER IN"); if (cup->uerr && !cup->unitchk) _ferr(css, cup->uffsw.sw_error); /* * This check taken out temporarily because we'd like to be able to * follow an ENDFILE statement or a READ which encounters an endfile * record with a BUFFER IN statement. The sticky EOF principle should * permit such a BUFFER IN to simply return an EOF status. But what * really happens is the preceding ENDFILE or READ statement sets * cup->uend, triggering an error here. We really need a flag to * store the status of the previous BUFFER IN/OUT statement which is * separate from cup->uend. * * if (cup->uend && !cup->unitchk) * _ferr(css, FERDPEOF); */ cup->unitchk = 0; cup->uerr = 0; elsize = tip->elsize; /* Data size in bytes */ type90 = tip->type90; /* * Adjust the word count depending on the type. */ bytshft = ((sizeof(elsize) << 3) - 1) - _leadz(elsize); /* log2(elsize) */ if (type90 == DVTYPE_ASCII) { /* If character item */ uda = _fcdtocp(bloc.fcd); udax = _fcdtocp(eloc.fcd); itemlen = _fcdlen (eloc.fcd); } else { #ifdef _CRAYT3D shared = 0; if (_issddptr(bloc.v)) { int *tmpptr; /* Shared data */ if (!_issddptr(eloc.v)) { _ferr(css, FEINTUNK); } shared = 1; ntot = 0; if ((cup->ufs == FS_FDC) && (cup->uflagword & FFC_ASYNC)) { /* When we can do I/O from shared memory */ /* we can support this. */ _ferr(css, FESHRSUP); } /* * When compiler spr 76429 (on T3D) is closed, we can try replacing * the lines that use tmpptr with this. * items = _sdd_read_offset((void *)eloc.v) - * _sdd_read_offset((void *)bloc.v) + 1; */ uda = bloc.v; /* temporary */ udax = eloc.v; tmpptr = (int *)((int)udax & 0x7fffffffffffffff); items = *(tmpptr + 1); tmpptr = (int *)((int)uda & 0x7fffffffffffffff); items = items - *(tmpptr + 1) + 1; } else #endif /* _CRAYT3D */ { uda = bloc.v; udax = eloc.v; } itemlen = elsize; } #ifdef _CRAYT3D if (shared) { bytes = items << bytshft; } else #endif { bytes = (udax - uda) + itemlen; items = bytes >> bytshft; } if (bytes < 0) _ferr(css, FEBIOFWA, "BUFFER IN"); mode = (*recmode < 0) ? PARTIAL : FULL; cup->urecmode = mode; cup->uwrt = 0; state = CNT; if ((items << bytshft) != bytes) _ferr(css, FEBIOFWD); #ifdef _CRAYT3D if ( !shared && cup->uasync ) { #else if (cup->uasync) { #endif int ubc = 0; WAITIO(cup, _ferr(css, cup->uffsw.sw_error)); #if defined(_UNICOS) || defined(NUMERIC_DATA_CONVERSION_ENABLED) /* * Pad word-aligned numeric data on word boundaries within * the record for CRI and some foreign data formats. */ if ((cup->urecpos & cup->ualignmask) != 0 && type90 != DVTYPE_ASCII && elsize > 4 ) { int padubc; register int pbytes; int padval; COMPADD(cup, pbytes, padubc, padval); if (pbytes != 0) { stat = XRCALL(cup->ufp.fdc, readrtn) cup->ufp.fdc, WPTR2BP(&padval), pbytes, &cup->uffsw, PARTIAL, &padubc); if (stat != pbytes || FFSTAT(cup->uffsw) != FFCNT) { cup->uerr = 1; goto badpart; } cup->urecpos += (stat << 3) - padubc; } }