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