|
|
1.1 ! root 1: /* ! 2: * libc/stdio/setvbuf.c ! 3: * ANSI-compliant C standard i/o library. ! 4: * setvbuf() ! 5: * ANSI 4.9.5.6. ! 6: * Set i/o buffer. ! 7: */ ! 8: ! 9: #include <stdio.h> ! 10: #include <stdlib.h> ! 11: ! 12: /* ! 13: * The get and put function pointers in a FILE ! 14: * initially contain &_fginit() and &_fpinit(). ! 15: * The buffering characteristics of the stream ! 16: * are determined either by an explicit setvbuf() ! 17: * before the first get or put on the stream ! 18: * or by a setvbuf() call from finit() on the first get or put. ! 19: * setvbuf() allocates a buffer if necessary and ! 20: * initializes various fields in the FILE. ! 21: * ! 22: * For unbuffered streams, _cc == 0 and _bp == _cp == _dp == _ep == NULL. ! 23: * For buffered streams: ! 24: * _cc == 0 nothing is buffered ! 25: * _cc > 0 _cc input or output characters are buffered ! 26: * _bp base of buffer ! 27: * _cp current buffer pointer ! 28: * _dp data pointer ! 29: * _ep end of buffer pointer ! 30: * The old version of the stdio functions used ! 31: * _cc < 0 -(_cc) input characters are buffered ! 32: * _cc > 0 _cc output characters are buffered ! 33: * which makes much more sense but is unfortunately not compatible with ! 34: * the Unix version of stdio.h. This stdio gets very confused if you ! 35: * mix input and output calls without fflush() in between on a rw stream; ! 36: * this is non-ANSI compliant but works right with the old version. ! 37: */ ! 38: int ! 39: setvbuf(stream, buf, mode, size) register FILE *stream; char *buf; int mode; size_t size; ! 40: { ! 41: register _FILE2 *f2p; ! 42: ! 43: #if _ASCII ! 44: register int isascii; ! 45: ! 46: isascii = stream->_ff2 & _FASCII; ! 47: #endif ! 48: ! 49: if (stream->_mode != _MODE_UNINIT) ! 50: return 1; /* Mode assigned, failure */ ! 51: ! 52: /* Allocate a buffer if necessary. */ ! 53: if (mode != _IONBF && buf == NULL) { ! 54: if ((buf = malloc(size)) == NULL) ! 55: return 1; /* Buffer allocation failure */ ! 56: stream->_ff2 |= _FFREEB; /* Free buffer when closed */ ! 57: } ! 58: ! 59: f2p = stream->_f2p; ! 60: switch(mode) { ! 61: ! 62: case _IOFBF: /* Fully buffered. */ ! 63: stream->_ff1 |= _IOFBF; ! 64: stream->_mode = _MODE_FBUF; ! 65: #if _ASCII ! 66: f2p->_pt = isascii ? &_fputba : &_fputb; ! 67: #else ! 68: f2p->_pt = &_fputb; ! 69: #endif ! 70: f2p->_dp = stream->_cp = buf + boffset(stream, size); ! 71: lab: ! 72: #if _ASCII ! 73: f2p->_gt = isascii ? &_fgetba : &_fgetb; ! 74: #else ! 75: f2p->_gt = &_fgetb; ! 76: #endif ! 77: f2p->_bp = buf; ! 78: f2p->_ep = buf + size; ! 79: break; ! 80: ! 81: case _IOLBF: /* Line buffered */ ! 82: stream->_ff1 |= _IOLBF; ! 83: stream->_mode = _MODE_LBUF; ! 84: #if _ASCII ! 85: f2p->_pt = isascii ? &_fputta : &_fputt; ! 86: #else ! 87: f2p->_pt = &_fputt; ! 88: #endif ! 89: f2p->_dp = stream->_cp = buf; ! 90: goto lab; ! 91: ! 92: case _IONBF: /* Unbuffered */ ! 93: stream->_ff1 |= _IONBF; ! 94: stream->_mode = _MODE_NBUF; ! 95: #if _ASCII ! 96: f2p->_gt = isascii ? &_fgetca : &_fgetc; ! 97: f2p->_pt = isascii ? &_fputca : &_fputc; ! 98: #else ! 99: f2p->_gt = &_fgetc; ! 100: f2p->_pt = &_fputc; ! 101: #endif ! 102: break; ! 103: ! 104: default: /* Unrecognized mode */ ! 105: return 1; ! 106: } ! 107: ! 108: if (stream->_ff1 & _FWONLY) ! 109: f2p->_gt = &_fgete; ! 110: if (stream->_ff1 & _FRONLY) ! 111: f2p->_pt = &_fpute; ! 112: stream->_cc = 0; ! 113: return 0; /* Success */ ! 114: } ! 115: ! 116: /* ! 117: * Return the current offset of a stream. ! 118: * This is an attempt to keep buffered file i/o properly aligned. ! 119: * For example, a 200 byte file opened in append mode with a ! 120: * default buffer size of 512 bytes will have boffset 200 ! 121: * and subsequent write()s will hopefully occur at 512-byte boundaries. ! 122: * If the user calls setvbuf() explicitly with a strange buffer size ! 123: * (not a multiple of the size for optimum disk i/o), ! 124: * the user will get degraded performance. ! 125: */ ! 126: static ! 127: int ! 128: boffset(fp, size) register FILE *fp; register size_t size; ! 129: { ! 130: register long offset; ! 131: ! 132: if ((offset=lseek(fileno(fp), 0L, SEEK_CUR)) == -1L || size == 0) ! 133: return 0; ! 134: return (unsigned)offset%(unsigned)size; ! 135: } ! 136: ! 137: /* end of libc/stdio/setvbuf.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.