1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                 Glenn Fowler <gsf@research.att.com>                  *
18 *                  David Korn <dgk@research.att.com>                   *
19 *                   Phong Vo <kpv@research.att.com>                    *
20 *                                                                      *
21 ***********************************************************************/
22 #include	"sfhdr.h"
23 
24 
25 /*	Push/pop streams
26 **
27 **	Written by Kiem-Phong Vo.
28 */
29 
30 #define STKMTXLOCK(f1,f2) \
31 	{ if(f1) SFMTXLOCK(f1); \
32 	  if(f2) SFMTXLOCK(f2); \
33 	}
34 #define STKMTXRETURN(f1,f2,rv) \
35 	{ if(f1) SFMTXUNLOCK(f1); \
36 	  if(f2) SFMTXUNLOCK(f2); \
37 	  return(rv); \
38 	}
39 
40 #if __STD_C
sfstack(Sfio_t * f1,Sfio_t * f2)41 Sfio_t* sfstack(Sfio_t* f1, Sfio_t* f2)
42 #else
43 Sfio_t* sfstack(f1,f2)
44 Sfio_t*	f1;	/* base of stack	*/
45 Sfio_t*	f2;	/* top of stack	*/
46 #endif
47 {
48 	reg int		n;
49 	reg Sfio_t*	rf;
50 	reg Sfrsrv_t*	rsrv;
51 	reg Void_t*	mtx;
52 
53 	STKMTXLOCK(f1,f2);
54 
55 	if(f1 && (f1->mode&SF_RDWR) != f1->mode && _sfmode(f1,0,0) < 0)
56 		STKMTXRETURN(f1,f2, NIL(Sfio_t*));
57 	if(f2 && (f2->mode&SF_RDWR) != f2->mode && _sfmode(f2,0,0) < 0)
58 		STKMTXRETURN(f1,f2, NIL(Sfio_t*));
59 	if(!f1)
60 		STKMTXRETURN(f1,f2, f2);
61 
62 	/* give access to other internal functions */
63 	_Sfstack = sfstack;
64 
65 	if(f2 == SF_POPSTACK)
66 	{	if(!(f2 = f1->push))
67 			STKMTXRETURN(f1,f2, NIL(Sfio_t*));
68 		f2->mode &= ~SF_PUSH;
69 	}
70 	else
71 	{	if(f2->push)
72 			STKMTXRETURN(f1,f2, NIL(Sfio_t*));
73 		if(f1->pool && f1->pool != &_Sfpool && f1->pool != f2->pool &&
74 		   f1 == f1->pool->sf[0])
75 		{	/* get something else to pool front since f1 will be locked */
76 			for(n = 1; n < f1->pool->n_sf; ++n)
77 			{	if(SFFROZEN(f1->pool->sf[n]) )
78 					continue;
79 				(*_Sfpmove)(f1->pool->sf[n],0);
80 				break;
81 			}
82 		}
83 	}
84 
85 	if(f2->pool && f2->pool != &_Sfpool && f2 != f2->pool->sf[0])
86 		(*_Sfpmove)(f2,0);
87 
88 	/* swap streams */
89 	sfswap(f1,f2);
90 
91 	/* but the reserved buffer and mutex must remain the same */
92 	rsrv = f1->rsrv; f1->rsrv = f2->rsrv; f2->rsrv = rsrv;
93 	mtx = f1->mutex; f1->mutex = f2->mutex; f2->mutex = mtx;
94 
95 	SFLOCK(f1,0);
96 	SFLOCK(f2,0);
97 
98 	if(f2->push != f2)
99 	{	/* freeze the pushed stream */
100 		f2->mode |= SF_PUSH;
101 		f1->push = f2;
102 		rf = f1;
103 	}
104 	else
105 	{	/* unfreeze the just exposed stream */
106 		f1->mode &= ~SF_PUSH;
107 		f2->push = NIL(Sfio_t*);
108 		rf = f2;
109 	}
110 
111 	SFOPEN(f1,0);
112 	SFOPEN(f2,0);
113 
114 	STKMTXRETURN(f1,f2, rf);
115 }
116