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
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Push/pop streams
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin**
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Written by Kiem-Phong Vo.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define STKMTXLOCK(f1,f2) \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(f1) SFMTXLOCK(f1); \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f2) SFMTXLOCK(f2); \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define STKMTXRETURN(f1,f2,rv) \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(f1) SFMTXUNLOCK(f1); \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f2) SFMTXUNLOCK(f2); \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(rv); \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfio_t* sfstack(Sfio_t* f1, Sfio_t* f2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfio_t* sfstack(f1,f2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfio_t* f1; /* base of stack */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfio_t* f2; /* top of stack */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Sfio_t* rf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Sfrsrv_t* rsrv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Void_t* mtx;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin STKMTXLOCK(f1,f2);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f1 && (f1->mode&SF_RDWR) != f1->mode && _sfmode(f1,0,0) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin STKMTXRETURN(f1,f2, NIL(Sfio_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f2 && (f2->mode&SF_RDWR) != f2->mode && _sfmode(f2,0,0) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin STKMTXRETURN(f1,f2, NIL(Sfio_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!f1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin STKMTXRETURN(f1,f2, f2);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* give access to other internal functions */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Sfstack = sfstack;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f2 == SF_POPSTACK)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(!(f2 = f1->push))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin STKMTXRETURN(f1,f2, NIL(Sfio_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f2->mode &= ~SF_PUSH;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(f2->push)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin STKMTXRETURN(f1,f2, NIL(Sfio_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f1->pool && f1->pool != &_Sfpool && f1->pool != f2->pool &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f1 == f1->pool->sf[0])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* get something else to pool front since f1 will be locked */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(n = 1; n < f1->pool->n_sf; ++n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(SFFROZEN(f1->pool->sf[n]) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (*_Sfpmove)(f1->pool->sf[n],0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f2->pool && f2->pool != &_Sfpool && f2 != f2->pool->sf[0])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (*_Sfpmove)(f2,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* swap streams */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfswap(f1,f2);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* but the reserved buffer and mutex must remain the same */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rsrv = f1->rsrv; f1->rsrv = f2->rsrv; f2->rsrv = rsrv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mtx = f1->mutex; f1->mutex = f2->mutex; f2->mutex = mtx;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFLOCK(f1,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFLOCK(f2,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f2->push != f2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* freeze the pushed stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f2->mode |= SF_PUSH;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f1->push = f2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rf = f1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* unfreeze the just exposed stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f1->mode &= ~SF_PUSH;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f2->push = NIL(Sfio_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rf = f2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFOPEN(f1,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFOPEN(f2,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin STKMTXRETURN(f1,f2, rf);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}