da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1985-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "sfhdr.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Add a new discipline to the discipline stack. Each discipline
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** provides alternative I/O functions that are analogues of the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** system calls.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin**
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** When the application fills or flushes the stream buffer, data
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** will be processed through discipline functions. A case deserving
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** consideration is stacking a discipline onto a read stream. Each
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** discipline operation implies buffer synchronization so the stream
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** buffer should be empty. However, a read stream representing an
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** unseekable device (eg, a pipe) may not be synchronizable. In that
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** case, any buffered data must then be fed to the new discipline
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** to preserve data processing semantics. This is done by creating
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** a temporary discipline to cache such buffered data and feed
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** them to the new discipline when its readf() asks for new data.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Care must then be taken to remove this temporary discipline
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** when it runs out of cached data.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin**
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Written by Kiem-Phong Vo
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct _dccache_s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{ Sfdisc_t disc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin uchar* data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin uchar* endb;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin} Dccache_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int _dccaexcept(Sfio_t* f, int type, Void_t* val, Sfdisc_t* disc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int _dccaexcept(f,type,val,disc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfio_t* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint type;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinVoid_t* val;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfdisc_t* disc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(disc && type == SF_FINAL)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(disc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic ssize_t _dccaread(Sfio_t* f, Void_t* buf, size_t size, Sfdisc_t* disc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic ssize_t _dccaread(f, buf, size, disc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfio_t* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinVoid_t* buf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinsize_t size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfdisc_t* disc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ssize_t sz;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfdisc_t *prev;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Dccache_t *dcca;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!f) /* bad stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make sure that this is on the discipline stack */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(prev = f->disc; prev; prev = prev->disc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(prev->disc == disc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!prev)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(size <= 0) /* nothing to do */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* read from available data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dcca = (Dccache_t*)disc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((sz = dcca->endb - dcca->data) > (ssize_t)size)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sz = (ssize_t)size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy(buf, dcca->data, sz);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((dcca->data += sz) >= dcca->endb) /* free empty cache */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { prev->disc = disc->disc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(disc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return sz;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
7c2fbfb345896881c631598ee3852ce9ce33fb07April ChinSfdisc_t* sfdisc(Sfio_t* f, Sfdisc_t* disc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfdisc_t* sfdisc(f,disc)
7c2fbfb345896881c631598ee3852ce9ce33fb07April ChinSfio_t* f;
7c2fbfb345896881c631598ee3852ce9ce33fb07April ChinSfdisc_t* disc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Sfdisc_t *d, *rdisc;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Sfread_f oreadf;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Sfwrite_f owritef;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Sfseek_f oseekf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ssize_t n;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin Dccache_t *dcca = NIL(Dccache_t*);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin SFMTXDECL(f);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin SFMTXENTER(f, NIL(Sfdisc_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((Sfio_t*)disc == f) /* special case to get the top discipline */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin SFMTXRETURN(f,f->disc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->flags&SF_READ) && f->proc && (f->mode&SF_WRITE) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* make sure in read mode to check for read-ahead data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(_sfmode(f,SF_READ,0) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFMTXRETURN(f, NIL(Sfdisc_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin { if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin SFMTXRETURN(f, NIL(Sfdisc_t*));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFLOCK(f,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rdisc = NIL(Sfdisc_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* disallow popping while there is cached data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!disc && f->disc && f->disc->disc && f->disc->disc->readf == _dccaread )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* synchronize before switching to a new discipline */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(f->flags&SF_STRING))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { (void)SFSYNC(f); /* do a silent buffer synch */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->mode&SF_READ) && (f->mode&SF_SYNCED) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { f->mode &= ~SF_SYNCED;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->endb = f->next = f->endr = f->endw = f->data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* if there is buffered data, ask app before proceeding */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(((f->mode&SF_WRITE) && (n = f->next-f->data) > 0) ||
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ((f->mode&SF_READ) && (n = f->endb-f->next) > 0) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { int rv = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(rv == 0 && f->disc && f->disc->exceptf) /* ask current discipline */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { SFOPEN(f,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rv = (*f->disc->exceptf)(f, SF_DBUFFER, &n, f->disc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFLOCK(f,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(rv == 0 && disc && disc->exceptf) /* ask discipline being pushed */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { SFOPEN(f,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rv = (*disc->exceptf)(f, SF_DBUFFER, &n, disc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFLOCK(f,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(rv < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* trick the new discipline into processing already buffered data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->mode&SF_READ) && n > 0 && disc && disc->readf )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(!(dcca = (Dccache_t*)malloc(sizeof(Dccache_t)+n)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memclear(dcca, sizeof(Dccache_t));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dcca->disc.readf = _dccaread;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dcca->disc.exceptf = _dccaexcept;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* move buffered data into the temp discipline */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dcca->data = ((uchar*)dcca) + sizeof(Dccache_t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dcca->endb = dcca->data + n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy(dcca->data, f->next, n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->endb = f->next = f->endr = f->endw = f->data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save old readf, writef, and seekf to see if stream need reinit */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define GETDISCF(func,iof,type) \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { for(d = f->disc; d && !d->iof; d = d->disc) ; \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin func = d ? d->iof : NIL(type); \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin GETDISCF(oreadf,readf,Sfread_f);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin GETDISCF(owritef,writef,Sfwrite_f);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin GETDISCF(oseekf,seekf,Sfseek_f);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(disc == SF_POPDISC)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* popping, warn the being popped discipline */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(d = f->disc) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin disc = d->disc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(d->exceptf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { SFOPEN(f,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((*(d->exceptf))(f,SF_DPOP,(Void_t*)disc,d) < 0 )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFLOCK(f,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->disc = disc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rdisc = d;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* pushing, warn being pushed discipline */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin do
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* loop to handle the case where d may pop itself */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin d = f->disc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(d && d->exceptf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { SFOPEN(f,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if( (*(d->exceptf))(f,SF_DPUSH,(Void_t*)disc,d) < 0 )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFLOCK(f,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } while(d != f->disc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make sure we are not creating an infinite loop */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(; d; d = d->disc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(d == disc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set new disc */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(dcca) /* insert the discipline with cached data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { dcca->disc.disc = f->disc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin disc->disc = &dcca->disc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else disc->disc = f->disc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->disc = disc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rdisc = disc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(f->flags&SF_STRING) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* this stream may have to be reinitialized */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg int reinit = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DISCF(dst,iof,type) (dst ? dst->iof : NIL(type))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define REINIT(oiof,iof,type) \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!reinit) \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { for(d = f->disc; d && !d->iof; d = d->disc) ; \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(DISCF(d,iof,type) != oiof) \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reinit = 1; \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin REINIT(oreadf,readf,Sfread_f);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin REINIT(owritef,writef,Sfwrite_f);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin REINIT(oseekf,seekf,Sfseek_f);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(reinit)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { SETLOCAL(f);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->bits &= ~SF_NULL; /* turn off /dev/null handling */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->bits&SF_MMAP) || (f->mode&SF_INIT))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsetbuf(f,NIL(Void_t*),(size_t)SF_UNBOUND);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(f->data == f->tiny)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsetbuf(f,NIL(Void_t*),0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { int flags = f->flags;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsetbuf(f,(Void_t*)f->data,f->size);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->flags |= (flags&SF_MALLOC);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chindone :
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFOPEN(f,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFMTXRETURN(f, rdisc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}