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