Initial revision
This commit is contained in:
parent
478844dad8
commit
cfdd81a919
10 changed files with 6728 additions and 0 deletions
98
lbtt/src/BuchiProduct.cc
Normal file
98
lbtt/src/BuchiProduct.cc
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
|
||||
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "BuchiProduct.h"
|
||||
|
||||
namespace Graph
|
||||
{
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Static member definitions for class BuchiProduct.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
map< ::Ltl::LtlFormula*, BuchiProduct::SatisfiabilityMapping,
|
||||
less< ::Ltl::LtlFormula*>, ALLOC(BuchiProduct::SatisfiabilityMapping) >
|
||||
BuchiProduct::sat_cache;
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Function definitions for class BuchiProduct.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/* ========================================================================= */
|
||||
bool BuchiProduct::synchronizable
|
||||
(const Graph<GraphEdgeContainer>::Edge& transition_1,
|
||||
const Graph<GraphEdgeContainer>::Edge& transition_2)
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Tests whether two transitions of two Büchi automata are
|
||||
* synchronizable by checking whether the conjunction of their
|
||||
* guard formulas is satisfiable.
|
||||
*
|
||||
* Arguments: transition_1, -- Constant references to the transitions.
|
||||
* transition_2
|
||||
*
|
||||
* Returns: true iff the transitions are synchronizable. The result is
|
||||
* also stored into `this->sat_cache' for later reference.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
using ::Ltl::LtlFormula;
|
||||
using ::Ltl::And;
|
||||
|
||||
LtlFormula* guard_1 = &static_cast<const BuchiAutomaton::BuchiTransition&>
|
||||
(transition_1).guard();
|
||||
LtlFormula* guard_2 = &static_cast<const BuchiAutomaton::BuchiTransition&>
|
||||
(transition_2).guard();
|
||||
|
||||
if (guard_2 > guard_1)
|
||||
{
|
||||
LtlFormula* swap_guard = guard_2;
|
||||
guard_2 = guard_1;
|
||||
guard_1 = swap_guard;
|
||||
}
|
||||
|
||||
map<LtlFormula*, SatisfiabilityMapping, less<LtlFormula*>,
|
||||
ALLOC(SatisfiabilityMapping) >::iterator
|
||||
sat_cache_element = sat_cache.find(guard_1);
|
||||
|
||||
if (sat_cache_element == sat_cache.end())
|
||||
sat_cache_element = sat_cache.insert
|
||||
(make_pair(guard_1, SatisfiabilityMapping())).first;
|
||||
else
|
||||
{
|
||||
SatisfiabilityMapping::const_iterator sat_result
|
||||
= sat_cache_element->second.find(guard_2);
|
||||
if (sat_result != sat_cache_element->second.end())
|
||||
return sat_result->second;
|
||||
}
|
||||
|
||||
LtlFormula* f = &And::construct(*guard_1, *guard_2);
|
||||
const bool result = f->satisfiable();
|
||||
LtlFormula::destruct(f);
|
||||
sat_cache_element->second.insert(make_pair(guard_2, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
512
lbtt/src/BuchiProduct.h
Normal file
512
lbtt/src/BuchiProduct.h
Normal file
|
|
@ -0,0 +1,512 @@
|
|||
/*
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
|
||||
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef BUCHIPRODUCT_H
|
||||
#define BUCHIPRODUCT_H
|
||||
|
||||
#include <config.h>
|
||||
#include <deque>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "BitArray.h"
|
||||
#include "BuchiAutomaton.h"
|
||||
#include "EdgeContainer.h"
|
||||
#include "Graph.h"
|
||||
#include "LtlFormula.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Graph
|
||||
{
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* A class with operations for checking the intersection of two Büchi automata
|
||||
* (represented as two BuchiAutomaton objects) for emptiness.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
class BuchiProduct
|
||||
{
|
||||
public:
|
||||
BuchiProduct /* Constructor. */
|
||||
(const Graph<GraphEdgeContainer>& a1,
|
||||
const Graph<GraphEdgeContainer>& a2);
|
||||
|
||||
/* default copy constructor */
|
||||
|
||||
~BuchiProduct(); /* Destructor. */
|
||||
|
||||
/* default assignment operator */
|
||||
|
||||
bool empty() const; /* Tells whether the
|
||||
* intersection of the
|
||||
* Büchi automata
|
||||
* associated with the
|
||||
* product object is
|
||||
* (trivially) empty.
|
||||
*/
|
||||
|
||||
unsigned long int numberOfAcceptanceSets() const; /* Tells the number of
|
||||
* acceptance sets in the
|
||||
* intersection of the
|
||||
* automata associated with
|
||||
* the object.
|
||||
*/
|
||||
|
||||
const BuchiAutomaton::BuchiState& firstComponent /* Mappings between an */
|
||||
(const Graph<GraphEdgeContainer>::size_type /* intersection state */
|
||||
state_id) const; /* identifier and states */
|
||||
const BuchiAutomaton::BuchiState& secondComponent /* of the underlying */
|
||||
(const Graph<GraphEdgeContainer>::size_type /* automata. */
|
||||
state_id) const;
|
||||
|
||||
void mergeAcceptanceInformation /* Merges the acceptance */
|
||||
(const Graph<GraphEdgeContainer>::Node& state1, /* sets associated with */
|
||||
const Graph<GraphEdgeContainer>::Node& state2, /* a pair of states into */
|
||||
BitArray& acceptance_sets) const; /* a collection of sets. */
|
||||
|
||||
void mergeAcceptanceInformation /* Merges the acceptance */
|
||||
(const Graph<GraphEdgeContainer>::Edge& /* sets associated with */
|
||||
transition1, /* a pair of */
|
||||
const Graph<GraphEdgeContainer>::Edge& /* transitions into a */
|
||||
transition2, /* collection of sets. */
|
||||
BitArray& acceptance_sets) const;
|
||||
|
||||
void validateEdgeIterators /* Ensures that a pair */
|
||||
(const Graph<GraphEdgeContainer>::Node& /* of transition */
|
||||
state_1, /* iterators points to a */
|
||||
const Graph<GraphEdgeContainer>::Node& /* transition beginning */
|
||||
state_2, /* from a given state in */
|
||||
GraphEdgeContainer::const_iterator& /* the intersection of */
|
||||
transition_1, /* two Büchi automata. */
|
||||
GraphEdgeContainer::const_iterator&
|
||||
transition_2);
|
||||
|
||||
void incrementEdgeIterators /* Updates a pair of */
|
||||
(const Graph<GraphEdgeContainer>::Node& /* transition iterators */
|
||||
state_1, /* to make them point to */
|
||||
const Graph<GraphEdgeContainer>::Node& /* the "next" transition */
|
||||
state_2, /* starting from a given */
|
||||
GraphEdgeContainer::const_iterator& /* state in the */
|
||||
transition_1, /* intersection of two */
|
||||
GraphEdgeContainer::const_iterator& /* Büchi automata. */
|
||||
transition_2);
|
||||
|
||||
static void clearSatisfiabilityCache(); /* Clears information about
|
||||
* the satisfiability of
|
||||
* the guards of product
|
||||
* transitions.
|
||||
*/
|
||||
private:
|
||||
void mergeAcceptanceInformation /* Bitwise or between */
|
||||
(const BitArray& sets1, const BitArray& sets2, /* two "component" */
|
||||
BitArray& result) const; /* acceptance set
|
||||
* vectors and a result
|
||||
* vector.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
bool synchronizable /* Tests whether a pair */
|
||||
(const Graph<GraphEdgeContainer>::Edge& /* of transitions of two */
|
||||
transition_1, /* Büchi automata is */
|
||||
const Graph<GraphEdgeContainer>::Edge& /* synchronizable. */
|
||||
transition_2);
|
||||
|
||||
const BuchiAutomaton& automaton_1; /* Automata associated */
|
||||
const BuchiAutomaton& automaton_2; /* with the BuchiProduct */
|
||||
/* object. */
|
||||
|
||||
const unsigned long int /* Number of acceptance */
|
||||
number_of_acceptance_sets; /* sets in the
|
||||
* intersection of the
|
||||
* automata.
|
||||
*/
|
||||
|
||||
typedef map< ::Ltl::LtlFormula*, bool, /* Type definition for */
|
||||
less< ::Ltl::LtlFormula*>, /* storing information */
|
||||
ALLOC(bool) > /* about the */
|
||||
SatisfiabilityMapping; /* satisfiability of the
|
||||
* guards of product
|
||||
* transitions.
|
||||
*/
|
||||
|
||||
static map< ::Ltl::LtlFormula*, /* Result cache for */
|
||||
SatisfiabilityMapping, /* satisfiability tests. */
|
||||
less< ::Ltl::LtlFormula*>,
|
||||
ALLOC(SatisfiabilityMapping) >
|
||||
sat_cache;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Inline function definitions for class BuchiProduct.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/* ========================================================================= */
|
||||
inline BuchiProduct::BuchiProduct
|
||||
(const Graph<GraphEdgeContainer>& a1, const Graph<GraphEdgeContainer>& a2) :
|
||||
automaton_1(static_cast<const BuchiAutomaton&>(a1)),
|
||||
automaton_2(static_cast<const BuchiAutomaton&>(a2)),
|
||||
number_of_acceptance_sets(static_cast<const BuchiAutomaton&>(a1)
|
||||
.numberOfAcceptanceSets()
|
||||
+ static_cast<const BuchiAutomaton&>(a2)
|
||||
.numberOfAcceptanceSets())
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Constructor for class BuchiProduct. Initializes a new object
|
||||
* with operations for checking the emptiness of two Büchi
|
||||
* automata.
|
||||
*
|
||||
* Arguments: a1, a2 -- Constant references to two
|
||||
* Graph<GraphEdgeContainer> objects, assumed to be
|
||||
* BüchiAutomaton objects to which to apply the
|
||||
* operations.
|
||||
*
|
||||
* Returns: Nothing.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline BuchiProduct::~BuchiProduct()
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Destructor for class BuchiProduct.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: Nothing.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline bool BuchiProduct::empty() const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Tells whether the intersection of the Büchi automata
|
||||
* associated with a BuchiProduct object is (trivially) empty.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: true iff either of the automata associated with the
|
||||
* BuchiProduct object is (trivially) empty (i.e., whether
|
||||
* either of the automata has no states).
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
return (automaton_1.empty() || automaton_2.empty());
|
||||
}
|
||||
|
||||
|
||||
/* ========================================================================= */
|
||||
inline unsigned long int BuchiProduct::numberOfAcceptanceSets() const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Tells the number of acceptance sets in the intersection of
|
||||
* the two Büchi automata associated with a BuchiProduct object.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: The number of acceptance sets in the intersection.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
return number_of_acceptance_sets;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline const BuchiAutomaton::BuchiState& BuchiProduct::firstComponent
|
||||
(const Graph<GraphEdgeContainer>::size_type state_id) const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Function for accessing states of the "first" component
|
||||
* automaton in the intersection of two Büchi automata.
|
||||
*
|
||||
* Argument: state_id -- Identifier of a state in the component
|
||||
* automaton.
|
||||
*
|
||||
* Returns: A constant reference to a state in the component automaton.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
return automaton_1[state_id];
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline const BuchiAutomaton::BuchiState& BuchiProduct::secondComponent
|
||||
(const Graph<GraphEdgeContainer>::size_type state_id) const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Function for accessing states of the "second" component
|
||||
* automaton in the intersection of two Büchi automata.
|
||||
*
|
||||
* Argument: state_id -- Identifier of a state in the component
|
||||
* automaton.
|
||||
*
|
||||
* Returns: A constant reference to a state in the component automaton.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
return automaton_2[state_id];
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline void BuchiProduct::mergeAcceptanceInformation
|
||||
(const Graph<GraphEdgeContainer>::Node& state1,
|
||||
const Graph<GraphEdgeContainer>::Node& state2,
|
||||
BitArray& acceptance_sets) const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Merges the acceptance sets associated with a pair of states
|
||||
* of two Büchi automata into a collection of sets.
|
||||
*
|
||||
* Arguments: state1, state2 -- Constant references to the states of the
|
||||
* automata.
|
||||
* acceptance_sets -- A reference to a BitArray for storing
|
||||
* the result. The BitArray is assumed to
|
||||
* have capacity for
|
||||
* `this->number_of_acceptance_sets' bits.
|
||||
*
|
||||
* Returns: Nothing. Let n=`this->automaton_1.numberOfAcceptanceSets()';
|
||||
* after the operation, `acceptance_sets[i] = true' holds if
|
||||
* either
|
||||
* 0 <= i < n and
|
||||
* `state1.acceptanceSets().test(i) == true'
|
||||
* or 0 <= i - n < `this->automaton_2.numberOfAcceptanceSets()'
|
||||
* and `state2.acceptanceSets().test(i - n) == true'.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
mergeAcceptanceInformation
|
||||
(static_cast<const BuchiAutomaton::BuchiState&>(state1).acceptanceSets(),
|
||||
static_cast<const BuchiAutomaton::BuchiState&>(state2).acceptanceSets(),
|
||||
acceptance_sets);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline void BuchiProduct::mergeAcceptanceInformation
|
||||
(const Graph<GraphEdgeContainer>::Edge& transition1,
|
||||
const Graph<GraphEdgeContainer>::Edge& transition2,
|
||||
BitArray& acceptance_sets) const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Merges the acceptance sets associated with a pair of
|
||||
* transitions of two Büchi automata into a collection of
|
||||
* acceptance sets.
|
||||
*
|
||||
* Arguments: transition1, -- Constant references to the transitions
|
||||
* transition2 of the automata.
|
||||
* acceptance_sets -- A reference to a BitArray for storing
|
||||
* the result. The BitArray is assumed to
|
||||
* have capacity for
|
||||
* `this->number_of_acceptance_sets' bits.
|
||||
*
|
||||
* Returns: Nothing. Let n=`this->automaton_1.numberOfAcceptanceSets()';
|
||||
* after the operation, `acceptance_sets[i] = true' holds if
|
||||
* either
|
||||
* 0 <= i < n and
|
||||
* `transition1.acceptanceSets().test(i) == true'
|
||||
* or 0 <= i - n < `this->automaton_2.numberOfAcceptanceSets()'
|
||||
* and `transition2.acceptanceSets().test(i - n) == true'.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
mergeAcceptanceInformation
|
||||
(static_cast<const BuchiAutomaton::BuchiTransition&>(transition1)
|
||||
.acceptanceSets(),
|
||||
static_cast<const BuchiAutomaton::BuchiTransition&>(transition2)
|
||||
.acceptanceSets(),
|
||||
acceptance_sets);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline void BuchiProduct::mergeAcceptanceInformation
|
||||
(const BitArray& sets1, const BitArray& sets2, BitArray& result) const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Bitwise or between two acceptance set vectors and a result
|
||||
* vector.
|
||||
*
|
||||
* Arguments: sets1, -- Constant references to two BitArrays having (at
|
||||
* sets2 least) capacities
|
||||
* `automaton_1.numberOfAcceptanceSets()' and
|
||||
* `automaton_2.numberOfAcceptanceSets()',
|
||||
* respectively.
|
||||
* result -- A BitArray for storing the result, assumed to
|
||||
* have room for at least
|
||||
* `this->number_of_acceptance_sets' bits.
|
||||
*
|
||||
* Returns: Nothing. Let n=`this->automaton_1.numberOfAcceptanceSets()';
|
||||
* after the operation, `result[i] = true' holds if
|
||||
* either
|
||||
* 0 <= i < n and `sets1[i] == true'
|
||||
* or 0 <= i - n < `this->automaton_2.numberOfAcceptanceSets()'
|
||||
* and `sets2[i - n] == true'.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
const unsigned long int shift
|
||||
= automaton_1.numberOfAcceptanceSets();
|
||||
unsigned long int acceptance_set;
|
||||
for (acceptance_set = 0; acceptance_set < shift; ++acceptance_set)
|
||||
{
|
||||
if (sets1[acceptance_set])
|
||||
result.setBit(acceptance_set);
|
||||
}
|
||||
for ( ; acceptance_set < number_of_acceptance_sets; ++acceptance_set)
|
||||
{
|
||||
if (sets2[acceptance_set - shift])
|
||||
result.setBit(acceptance_set);
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline void BuchiProduct::validateEdgeIterators
|
||||
(const Graph<GraphEdgeContainer>::Node& state_1,
|
||||
const Graph<GraphEdgeContainer>::Node& state_2,
|
||||
GraphEdgeContainer::const_iterator& transition_1,
|
||||
GraphEdgeContainer::const_iterator& transition_2)
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Checks whether a pair of transition iterators corresponds to
|
||||
* a transition beginning from a state in the intersection of
|
||||
* two Büchi automata; if this is not the case, increments the
|
||||
* iterators to make them point to a valid transition beginning
|
||||
* from the state in the intersection (or to the "end" of the
|
||||
* collection of transitions beginning from the state if no
|
||||
* valid transition can be found by incrementing the iterators).
|
||||
*
|
||||
* Arguments: state_1, -- These variables determine the state in
|
||||
* state_2 the intersection automaton; `state_1' and
|
||||
* `state_2' should both be references to
|
||||
* BuchiAutomaton::BuchiState objects.
|
||||
* transition_1, -- References to the transition iterators.
|
||||
* transition_2 Initially, `transition_1' and
|
||||
* `transition_2' should point to two
|
||||
* transitions starting from `state_1' and
|
||||
* `state_2', respectively.
|
||||
*
|
||||
* Returns: Nothing. Upon return, `transition_1' and `transition_2' will
|
||||
* either equal `state_1.edges().end()' and
|
||||
* `state_2.edges().end()', respectively, or they will point to
|
||||
* a pair of transitions beginning from `state_1' and `state_2'
|
||||
* such that this pair of transitions corresponds to a
|
||||
* transition starting from the intersection state determined by
|
||||
* `state_1' and `state_2'.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
const GraphEdgeContainer& transitions_1 = state_1.edges();
|
||||
const GraphEdgeContainer& transitions_2 = state_2.edges();
|
||||
|
||||
if (transition_1 == transitions_1.end())
|
||||
{
|
||||
transition_2 = transitions_2.end();
|
||||
return;
|
||||
}
|
||||
if (transition_2 == transitions_2.end())
|
||||
{
|
||||
transition_1 = transitions_1.end();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!synchronizable(**transition_1, **transition_2))
|
||||
incrementEdgeIterators(state_1, state_2, transition_1, transition_2);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline void BuchiProduct::incrementEdgeIterators
|
||||
(const Graph<GraphEdgeContainer>::Node& state_1,
|
||||
const Graph<GraphEdgeContainer>::Node& state_2,
|
||||
GraphEdgeContainer::const_iterator& transition_1,
|
||||
GraphEdgeContainer::const_iterator& transition_2)
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Increments a pair of transition iterators to point to the
|
||||
* "next" transition beginning from a state in the intersection
|
||||
* of two Büchi automata. If no "next" transition exists, makes
|
||||
* the iterators point to the "end" of the collection of
|
||||
* transitions beginning from the state.
|
||||
*
|
||||
* Arguments: state_1, -- These variables determine the state in
|
||||
* state_2 the intersection automaton; `state_1' and
|
||||
* `state_2' should both be references to
|
||||
* BuchiAutomaton::BuchiState objects.
|
||||
* transition_1, -- References to the transition iterators.
|
||||
* transition_2 Initially, `transition_1' and
|
||||
* `transition_2' should point to two
|
||||
* transitions starting from `state_1' and
|
||||
* `state_2', respectively.
|
||||
*
|
||||
* Returns: Nothing. Upon return, `transition_1' and `transition_2' will
|
||||
* either equal `state_1.edges().end()' and
|
||||
* `state_2.edges().end()', respectively, or they will point to
|
||||
* a pair of transitions beginning from `state_1' and `state_2'
|
||||
* such that this pair of transitions corresponds to a
|
||||
* transition starting from the intersection state determined by
|
||||
* `state_1' and `state_2'.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
const GraphEdgeContainer& transitions_1 = state_1.edges();
|
||||
const GraphEdgeContainer& transitions_2 = state_2.edges();
|
||||
|
||||
do
|
||||
{
|
||||
++transition_2;
|
||||
if (transition_2 == transitions_2.end())
|
||||
{
|
||||
++transition_1;
|
||||
if (transition_1 == transitions_1.end())
|
||||
return;
|
||||
transition_2 = transitions_2.begin();
|
||||
}
|
||||
}
|
||||
while (!synchronizable(**transition_1, **transition_2));
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline void BuchiProduct::clearSatisfiabilityCache()
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Clears information about the satisfiability of the guard
|
||||
* formulas of product transitions.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: Nothing.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
sat_cache.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* !BUCHIPRODUCT_H */
|
||||
187
lbtt/src/IntervalList.cc
Normal file
187
lbtt/src/IntervalList.cc
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* Copyright (C) 2004
|
||||
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "IntervalList.h"
|
||||
#include "StringUtil.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Function definitions for class IntervalList.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/* ========================================================================= */
|
||||
void IntervalList::merge(unsigned long int min, unsigned long int max)
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Merges a new interval with a list of intervals.
|
||||
*
|
||||
* Arguments: min, max -- Upper and lower bound of the new interval.
|
||||
*
|
||||
* Returns: Nothing.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
if (min > max)
|
||||
return;
|
||||
|
||||
list<Interval, ALLOC(Interval) >::iterator interval;
|
||||
for (interval = intervals.begin();
|
||||
interval != intervals.end() && interval->second + 1 < min;
|
||||
++interval)
|
||||
;
|
||||
|
||||
if (interval == intervals.end())
|
||||
{
|
||||
intervals.insert(interval, make_pair(min, max));
|
||||
return;
|
||||
}
|
||||
|
||||
if (interval->first <= min && max <= interval->second)
|
||||
return;
|
||||
|
||||
if (max + 1 < interval->first)
|
||||
{
|
||||
intervals.insert(interval, make_pair(min, max));
|
||||
return;
|
||||
}
|
||||
|
||||
if (min < interval->first)
|
||||
interval->first = min;
|
||||
|
||||
if (interval->second < max)
|
||||
{
|
||||
interval->second = max;
|
||||
list<Interval, ALLOC(Interval) >::iterator interval2 = interval;
|
||||
++interval2;
|
||||
while (interval2 != intervals.end()
|
||||
&& interval2->first <= interval->second + 1)
|
||||
{
|
||||
if (interval->second < interval2->second)
|
||||
interval->second = interval2->second;
|
||||
list<Interval, ALLOC(Interval) >::iterator interval_to_erase = interval2;
|
||||
++interval2;
|
||||
intervals.erase(interval_to_erase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
void IntervalList::remove(unsigned long int min, unsigned long int max)
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Removes a closed interval from an interval list.
|
||||
*
|
||||
* Arguments: min, max -- Bounds for the interval to remove.
|
||||
*
|
||||
* Returns: Nothing.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
if (min > max)
|
||||
return;
|
||||
|
||||
list<Interval, ALLOC(Interval) >::iterator interval;
|
||||
for (interval = intervals.begin();
|
||||
interval != intervals.end() && interval->second < min;
|
||||
++interval)
|
||||
;
|
||||
|
||||
while (interval != intervals.end())
|
||||
{
|
||||
if (max < interval->first) /* min <= max < imin <= imax */
|
||||
return;
|
||||
|
||||
if (interval->first < min)
|
||||
{
|
||||
if (max < interval->second) /* imin < min <= max < imax */
|
||||
{
|
||||
intervals.insert(interval, make_pair(interval->first, min - 1));
|
||||
interval->first = max + 1;
|
||||
return;
|
||||
}
|
||||
interval->second = min - 1; /* imin < min <= imax <= max */
|
||||
++interval;
|
||||
}
|
||||
else if (max < interval->second) /* min <= imin <= max < imax */
|
||||
{
|
||||
interval->first = max + 1;
|
||||
return;
|
||||
}
|
||||
else /* min <= imin <= imax <= max */
|
||||
{
|
||||
list<Interval, ALLOC(Interval) >::iterator interval_to_erase = interval;
|
||||
++interval;
|
||||
intervals.erase(interval_to_erase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
bool IntervalList::covers(unsigned long int min, unsigned long int max) const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Test whether an interval list covers a given interval.
|
||||
*
|
||||
* Arguments: min, max -- Upper and lower bound for the interval to test.
|
||||
*
|
||||
* Returns: True if the IntervalList covers the given interval.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
if (min > max)
|
||||
return true; /* empty interval is always covered */
|
||||
|
||||
list<Interval, ALLOC(Interval) >::const_iterator interval;
|
||||
for (interval = intervals.begin();
|
||||
interval != intervals.end() && min > interval->second;
|
||||
++interval)
|
||||
;
|
||||
|
||||
if (interval == intervals.end())
|
||||
return false;
|
||||
|
||||
return (min >= interval->first && max <= interval->second);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
string IntervalList::toString() const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Converts the interval list to a string.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: A string listing the intervals in the interval list.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
string s;
|
||||
for (list<Interval, ALLOC(Interval) >::const_iterator
|
||||
interval = intervals.begin();
|
||||
interval != intervals.end();
|
||||
++interval)
|
||||
{
|
||||
if (interval != intervals.begin())
|
||||
s += ',';
|
||||
s += StringUtil::toString(interval->first) + "..."
|
||||
+ StringUtil::toString(interval->second);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
499
lbtt/src/IntervalList.h
Normal file
499
lbtt/src/IntervalList.h
Normal file
|
|
@ -0,0 +1,499 @@
|
|||
/*
|
||||
* Copyright (C) 2004
|
||||
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef INTERVALLIST_H
|
||||
#define INTERVALLIST_H
|
||||
|
||||
#include <config.h>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include "LbttAlloc.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* The IntervalList class represents a list of disjoint closed intervals
|
||||
* formed from pairs of unsigned long integers. The class supports merging
|
||||
* a new interval with a list of intervals, removing an interval from a list
|
||||
* of intervals and checking whether the interval list covers a given element
|
||||
* (or a given interval). The elements of the intervals can also be accessed
|
||||
* in increasing order via IntervalList::const_iterator.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
class IntervalList
|
||||
{
|
||||
private:
|
||||
typedef pair<unsigned long int,
|
||||
unsigned long int>
|
||||
Interval;
|
||||
|
||||
public:
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
class const_iterator /* A class for iterating */
|
||||
{ /* over the elements of */
|
||||
/* an IntervalList. */
|
||||
public:
|
||||
const_iterator(); /* Constructor. */
|
||||
|
||||
/* default copy constructor */
|
||||
|
||||
~const_iterator(); /* Destructor. */
|
||||
|
||||
/* default assignment operator */
|
||||
|
||||
bool operator==(const const_iterator& it) /* Comparison operators. */
|
||||
const;
|
||||
|
||||
bool operator!=(const const_iterator& it)
|
||||
const;
|
||||
|
||||
unsigned long int operator*() const; /* Dereference operator. */
|
||||
|
||||
unsigned long int operator++(); /* Prefix increment. */
|
||||
|
||||
unsigned long int operator++(int); /* Postfix increment. */
|
||||
|
||||
private:
|
||||
const list<Interval, ALLOC(Interval) >* /* The interval list */
|
||||
interval_list; /* associated with the */
|
||||
/* iterator. */
|
||||
|
||||
list<Interval, ALLOC(Interval) > /* An iterator pointing */
|
||||
::const_iterator interval; /* at the current */
|
||||
/* interval list. */
|
||||
|
||||
unsigned long int element; /* Element currently
|
||||
* pointed to by the
|
||||
* iterator.
|
||||
*/
|
||||
|
||||
friend class IntervalList;
|
||||
};
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
IntervalList(); /* Constructor. */
|
||||
|
||||
~IntervalList(); /* Destructor. */
|
||||
|
||||
/* default copy constructor */
|
||||
|
||||
/* default assignment operator */
|
||||
|
||||
void merge(unsigned long int element); /* Merges a point interval
|
||||
* with the list of
|
||||
* intervals.
|
||||
*/
|
||||
|
||||
void merge /* Merges a new interval */
|
||||
(unsigned long int min, unsigned long int max); /* with the list of
|
||||
* intervals.
|
||||
*/
|
||||
|
||||
void remove(unsigned long int element); /* Removes an element from
|
||||
* the list of intervals.
|
||||
*/
|
||||
|
||||
void remove /* Removes an interval */
|
||||
(unsigned long int min, unsigned long int max); /* from the list of
|
||||
* intervals.
|
||||
*/
|
||||
|
||||
bool covers(unsigned long int element) const; /* Tests whether the
|
||||
* interval list covers an
|
||||
* element.
|
||||
*/
|
||||
|
||||
bool covers /* Tests whether the */
|
||||
(unsigned long int min, unsigned long int max) /* interval list covers */
|
||||
const; /* an interval. */
|
||||
|
||||
const_iterator begin() const; /* Returns an iterator to
|
||||
* the beginning of the
|
||||
* interval list.
|
||||
*/
|
||||
|
||||
const_iterator end() const; /* Returns an iterator to
|
||||
* the end of the interval
|
||||
* list.
|
||||
*/
|
||||
|
||||
typedef const_iterator iterator; /* The interval list
|
||||
* cannot be modified with
|
||||
* iterators.
|
||||
*/
|
||||
|
||||
typedef list<Interval, ALLOC(Interval) > /* Size type. */
|
||||
::size_type size_type;
|
||||
|
||||
size_type size() const; /* Tell the number of
|
||||
* disjoint intervals in
|
||||
* the interval list.
|
||||
*/
|
||||
|
||||
size_type max_size() const; /* Tell the maximum
|
||||
* allowable number of
|
||||
* disjoint intervals in
|
||||
* the interval list.
|
||||
*/
|
||||
|
||||
bool empty() const; /* Tell whether the
|
||||
* interval list is empty.
|
||||
*/
|
||||
|
||||
void clear(); /* Makes the interval list
|
||||
* empty.
|
||||
*/
|
||||
|
||||
string toString() const; /* Converts the interval
|
||||
* list to a string.
|
||||
*/
|
||||
|
||||
private:
|
||||
list<Interval, ALLOC(Interval) > intervals; /* List of intervals. */
|
||||
|
||||
friend class const_iterator;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Inline function definitions for class IntervalList.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/* ========================================================================= */
|
||||
inline IntervalList::IntervalList()
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Constructor for class IntervalList. Creates an empty list of
|
||||
* intervals.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: Nothing.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline IntervalList::~IntervalList()
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Destructor for class IntervalList.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: Nothing.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline void IntervalList::merge(unsigned long int element)
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Merges an element (a point interval) with an IntervalList.
|
||||
*
|
||||
* Arguments: element -- Element to merge.
|
||||
*
|
||||
* Returns: Nothing.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
merge(element, element);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline bool IntervalList::covers(unsigned long int element) const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Tests whether an interval list covers an element.
|
||||
*
|
||||
* Arguments: element -- Element to test.
|
||||
*
|
||||
* Returns: True if the IntervalList covers the element.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
return covers(element, element);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline IntervalList::size_type IntervalList::size() const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Tells the number of disjoint intervals in an IntervalList.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: Number of disjoint intervals in the IntervalList.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
return intervals.size();
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline IntervalList::size_type IntervalList::max_size() const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Tells the maximum allowable number of disjoint intervals in
|
||||
* an IntervalList.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: Maximum allowable number of disjoint intervals in the
|
||||
* IntervalList.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
return intervals.max_size();
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline bool IntervalList::empty() const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Tells whether an IntervalList is empty.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: True if the IntervalList is empty.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
return intervals.empty();
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline void IntervalList::clear()
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Makes an IntervalList empty.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: Nothing.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
intervals.clear();
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline IntervalList::const_iterator IntervalList::begin() const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Returns an IntervalList::const_iterator pointing to the
|
||||
* beginning of an IntervalList.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: An IntervalList::const_iterator pointing to the beginning of
|
||||
* the IntervalList.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
const_iterator it;
|
||||
it.interval_list = &this->intervals;
|
||||
it.interval = intervals.begin();
|
||||
if (it.interval != intervals.end())
|
||||
it.element = it.interval->first;
|
||||
else
|
||||
it.element = 0;
|
||||
return it;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline IntervalList::const_iterator IntervalList::end() const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Returns an IntervalList::const_iterator pointing to the end
|
||||
* of an IntervalList.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: An IntervalList::const_iterator pointing to the end of the
|
||||
* IntervalList.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
const_iterator it;
|
||||
it.interval_list = &this->intervals;
|
||||
it.interval = intervals.end();
|
||||
it.element = 0;
|
||||
return it;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Inline function definitions for class IntervalList::const_iterator.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/* ========================================================================= */
|
||||
inline IntervalList::const_iterator::const_iterator()
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Constructor for class IntervalList::const_iterator.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: Nothing.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline IntervalList::const_iterator::~const_iterator()
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Destructor for class IntervalList::const_iterator.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: Nothing.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline bool IntervalList::const_iterator::operator==
|
||||
(const const_iterator& it) const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Equality test for two IntervalList::const_iterators. Two
|
||||
* IntervalList::const_iterators are equal if and only if they
|
||||
* point to the same interval of an interval list and the same
|
||||
* element in the interval.
|
||||
*
|
||||
* Argument: it -- A constant reference to another
|
||||
* IntervalList::const_iterator.
|
||||
*
|
||||
* Returns: Result of the equality test (a truth value).
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
return (interval_list == it.interval_list && interval == it.interval
|
||||
&& element == it.element);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline bool IntervalList::const_iterator::operator!=
|
||||
(const const_iterator& it) const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Inequality test for two IntervalList::const_iterators. Two
|
||||
* IntervalList::const_iterators are not equal if and only if
|
||||
* they point to different intervals of an interval list or to
|
||||
* different elements of the same interval in the list.
|
||||
*
|
||||
* Argument: it -- A constant reference to another
|
||||
* IntervalList::const_iterator.
|
||||
*
|
||||
* Returns: Result of the inequality test (a truth value).
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
return (interval_list != it.interval_list || interval != it.interval
|
||||
|| element != it.element);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline unsigned long int IntervalList::const_iterator::operator*() const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Dereferencing operator for IntervalList::const_iterator.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: The element currently pointed to by the iterator.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
return element;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline unsigned long int IntervalList::const_iterator::operator++()
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Prefix increment operator for IntervalList::const_iterator.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: The element following the "current" element in the interval
|
||||
* list.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
if (element == interval->second)
|
||||
{
|
||||
++interval;
|
||||
if (interval != interval_list->end())
|
||||
element = interval->first;
|
||||
else
|
||||
element = 0;
|
||||
}
|
||||
else
|
||||
++element;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline unsigned long int IntervalList::const_iterator::operator++(int)
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Postfix increment operator for IntervalList::const_iterator.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: The "current" element in the interval list.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
unsigned long int current_element = element;
|
||||
if (element == interval->second)
|
||||
{
|
||||
++interval;
|
||||
if (interval != interval_list->end())
|
||||
element = interval->first;
|
||||
else
|
||||
element = 0;
|
||||
}
|
||||
else
|
||||
++element;
|
||||
|
||||
return current_element;
|
||||
}
|
||||
|
||||
#endif /* INTERVALLIST_H */
|
||||
610
lbtt/src/Ltl-parse.yy
Normal file
610
lbtt/src/Ltl-parse.yy
Normal file
|
|
@ -0,0 +1,610 @@
|
|||
/*
|
||||
* Copyright (C) 2004
|
||||
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
%{
|
||||
#include <config.h>
|
||||
#include <cctype>
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
#include <istream>
|
||||
#include <set>
|
||||
#include "Exception.h"
|
||||
#include "LbttAlloc.h"
|
||||
#include "LtlFormula.h"
|
||||
|
||||
using namespace Ltl;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Variables and functions used for parsing an LTL formula.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static Exceptional_istream* estream; /* Pointer to input stream.
|
||||
*/
|
||||
|
||||
static LtlFormula* result; /* This variable stores the
|
||||
* result after a call to
|
||||
* ltl_parse.
|
||||
*/
|
||||
|
||||
static std::set<LtlFormula*, less<LtlFormula*>, /* Intermediate results. */
|
||||
ALLOC(LtlFormula*) > /* (This set is used */
|
||||
intermediate_results; /* for keeping track of
|
||||
* the subformulas of a
|
||||
* partially constructed
|
||||
* formula in case the
|
||||
* memory allocated for
|
||||
* the subformulas needs
|
||||
* to be freed because
|
||||
* of a parse error.)
|
||||
*/
|
||||
|
||||
static int ltl_lex(); /* The lexical scanner. */
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Function for reporting parse errors.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static void ltl_error(const char*)
|
||||
{
|
||||
throw LtlFormula::ParseErrorException("error parsing LTL formula");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Function for updating the set of intermediate results.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
inline LtlFormula* newFormula(LtlFormula& f)
|
||||
{
|
||||
intermediate_results.insert(&f);
|
||||
return &f;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
|
||||
|
||||
%name-prefix="ltl_"
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Declarations for terminal and nonterminal symbols used in the grammar rules
|
||||
* below.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
%union {
|
||||
class LtlFormula* formula;
|
||||
}
|
||||
|
||||
/* Uninterpreted symbols. */
|
||||
|
||||
%token LTLPARSE_LPAR LTLPARSE_RPAR LTLPARSE_FALSE LTLPARSE_TRUE
|
||||
LTLPARSE_UNKNOWN
|
||||
|
||||
/* Atomic propositions. */
|
||||
|
||||
%token <formula> LTLPARSE_ATOM
|
||||
|
||||
/* Operators. */
|
||||
|
||||
%nonassoc LTLPARSE_UNTIL LTLPARSE_RELEASE LTLPARSE_WEAK_UNTIL
|
||||
LTLPARSE_STRONG_RELEASE LTLPARSE_BEFORE
|
||||
%left LTLPARSE_IMPLY LTLPARSE_EQUIV LTLPARSE_XOR
|
||||
%left LTLPARSE_OR
|
||||
%left LTLPARSE_AND
|
||||
%nonassoc LTLPARSE_NOT LTLPARSE_NEXT LTLPARSE_FINALLY LTLPARSE_GLOBALLY
|
||||
%nonassoc LTLPARSE_EQUALS
|
||||
|
||||
/* Compound formulas. */
|
||||
|
||||
%type <formula> formula atomic_formula unary_formula prefix_op_formula
|
||||
binary_formula prefix_b_formula infix_b_formula
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Grammar rule definitions.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
%%
|
||||
|
||||
ltl_formula: formula
|
||||
{ result = $1; }
|
||||
;
|
||||
|
||||
formula: atomic_formula
|
||||
{ $$ = $1; }
|
||||
|
||||
| unary_formula
|
||||
{ $$ = $1; }
|
||||
|
||||
| binary_formula
|
||||
{ $$ = $1; }
|
||||
|
||||
| LTLPARSE_LPAR formula LTLPARSE_RPAR
|
||||
{ $$ = $2; }
|
||||
;
|
||||
|
||||
atomic_formula: LTLPARSE_ATOM
|
||||
{ $$ = $1; }
|
||||
|
||||
| LTLPARSE_ATOM LTLPARSE_EQUALS LTLPARSE_FALSE
|
||||
{
|
||||
intermediate_results.erase($1);
|
||||
$$ = newFormula(Not::construct($1));
|
||||
}
|
||||
|
||||
| LTLPARSE_ATOM LTLPARSE_EQUALS LTLPARSE_TRUE
|
||||
{ $$ = $1; }
|
||||
|
||||
| LTLPARSE_FALSE
|
||||
{ $$ = newFormula(False::construct()); }
|
||||
|
||||
| LTLPARSE_TRUE
|
||||
{ $$ = newFormula(True::construct()); }
|
||||
;
|
||||
|
||||
unary_formula: LTLPARSE_NOT formula
|
||||
{
|
||||
intermediate_results.erase($2);
|
||||
$$ = newFormula(Not::construct($2));
|
||||
}
|
||||
|
||||
| LTLPARSE_NEXT formula
|
||||
{
|
||||
intermediate_results.erase($2);
|
||||
$$ = newFormula(Next::construct($2));
|
||||
}
|
||||
|
||||
| LTLPARSE_FINALLY formula
|
||||
{
|
||||
intermediate_results.erase($2);
|
||||
$$ = newFormula(Finally::construct($2));
|
||||
}
|
||||
|
||||
| LTLPARSE_GLOBALLY formula
|
||||
{
|
||||
intermediate_results.erase($2);
|
||||
$$ = newFormula(Globally::construct($2));
|
||||
}
|
||||
;
|
||||
|
||||
prefix_op_formula: atomic_formula
|
||||
{ $$ = $1; }
|
||||
|
||||
| unary_formula
|
||||
{ $$ = $1; }
|
||||
|
||||
| prefix_b_formula
|
||||
{ $$ = $1; }
|
||||
|
||||
| LTLPARSE_LPAR formula LTLPARSE_RPAR
|
||||
{ $$ = $2; }
|
||||
;
|
||||
|
||||
binary_formula: prefix_b_formula
|
||||
{ $$ = $1; }
|
||||
| infix_b_formula
|
||||
{ $$ = $1; }
|
||||
;
|
||||
|
||||
prefix_b_formula: LTLPARSE_AND prefix_op_formula prefix_op_formula
|
||||
{
|
||||
intermediate_results.erase($2);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(And::construct($2, $3));
|
||||
}
|
||||
|
||||
| LTLPARSE_OR prefix_op_formula prefix_op_formula
|
||||
{
|
||||
intermediate_results.erase($2);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(Or::construct($2, $3));
|
||||
}
|
||||
|
||||
| LTLPARSE_IMPLY prefix_op_formula prefix_op_formula
|
||||
{
|
||||
intermediate_results.erase($2);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(Imply::construct($2, $3));
|
||||
}
|
||||
|
||||
| LTLPARSE_EQUIV prefix_op_formula prefix_op_formula
|
||||
{
|
||||
intermediate_results.erase($2);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(Equiv::construct($2, $3));
|
||||
}
|
||||
|
||||
| LTLPARSE_XOR prefix_op_formula prefix_op_formula
|
||||
{
|
||||
intermediate_results.erase($2);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(Xor::construct($2, $3));
|
||||
}
|
||||
|
||||
| LTLPARSE_UNTIL prefix_op_formula prefix_op_formula
|
||||
{
|
||||
intermediate_results.erase($2);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(Until::construct($2, $3));
|
||||
}
|
||||
|
||||
| LTLPARSE_RELEASE prefix_op_formula prefix_op_formula
|
||||
{
|
||||
intermediate_results.erase($2);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(V::construct($2, $3));
|
||||
}
|
||||
|
||||
| LTLPARSE_WEAK_UNTIL prefix_op_formula prefix_op_formula
|
||||
{
|
||||
intermediate_results.erase($2);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(WeakUntil::construct($2, $3));
|
||||
}
|
||||
|
||||
| LTLPARSE_STRONG_RELEASE prefix_op_formula
|
||||
prefix_op_formula
|
||||
{
|
||||
intermediate_results.erase($2);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(StrongRelease::construct($2, $3));
|
||||
}
|
||||
|
||||
| LTLPARSE_BEFORE prefix_op_formula prefix_op_formula
|
||||
{
|
||||
intermediate_results.erase($2);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(Before::construct($2, $3));
|
||||
}
|
||||
;
|
||||
|
||||
infix_b_formula: formula LTLPARSE_AND formula
|
||||
{
|
||||
intermediate_results.erase($1);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(And::construct($1, $3));
|
||||
}
|
||||
|
||||
| formula LTLPARSE_OR formula
|
||||
{
|
||||
intermediate_results.erase($1);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(Or::construct($1, $3));
|
||||
}
|
||||
|
||||
| formula LTLPARSE_IMPLY formula
|
||||
{
|
||||
intermediate_results.erase($1);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(Imply::construct($1, $3));
|
||||
}
|
||||
|
||||
| formula LTLPARSE_EQUIV formula
|
||||
{
|
||||
intermediate_results.erase($1);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(Equiv::construct($1, $3));
|
||||
}
|
||||
|
||||
| formula LTLPARSE_XOR formula
|
||||
{
|
||||
intermediate_results.erase($1);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(Xor::construct($1, $3));
|
||||
}
|
||||
|
||||
| formula LTLPARSE_UNTIL formula
|
||||
{
|
||||
intermediate_results.erase($1);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(Until::construct($1, $3));
|
||||
}
|
||||
|
||||
| formula LTLPARSE_RELEASE formula
|
||||
{
|
||||
intermediate_results.erase($1);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(V::construct($1, $3));
|
||||
}
|
||||
|
||||
| formula LTLPARSE_WEAK_UNTIL formula
|
||||
{
|
||||
intermediate_results.erase($1);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(WeakUntil::construct($1, $3));
|
||||
}
|
||||
|
||||
| formula LTLPARSE_STRONG_RELEASE formula
|
||||
{
|
||||
intermediate_results.erase($1);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(StrongRelease::construct($1, $3));
|
||||
}
|
||||
|
||||
| formula LTLPARSE_BEFORE formula
|
||||
{
|
||||
intermediate_results.erase($1);
|
||||
intermediate_results.erase($3);
|
||||
$$ = newFormula(Before::construct($1, $3));
|
||||
}
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Helper function for reading lexical tokens from a stream.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static inline size_t matchCharactersFromStream
|
||||
(istream& stream, char* chars)
|
||||
{
|
||||
size_t num_matched;
|
||||
for (num_matched = 0; *chars != '\0' && stream.peek() == *chars; ++chars)
|
||||
{
|
||||
stream.ignore(1);
|
||||
++num_matched;
|
||||
}
|
||||
return num_matched;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Main interface to the parser.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
namespace Ltl
|
||||
{
|
||||
|
||||
/* ========================================================================= */
|
||||
LtlFormula* parseFormula(istream& stream)
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Parses an LTL formula from a stream. The formula should be
|
||||
* in one of the formats used by the tools lbtt 1.0.x (both
|
||||
* prefix and infix form), Spin/Temporal Massage Parlor/LTL2BA,
|
||||
* LTL2AUT or Wring 1.1.0 (actually, the grammar is basically
|
||||
* a combination of the grammars of the above tools with the
|
||||
* exception that propositions should always be written in the
|
||||
* form `pN' for some integer N; in principle, it is possible to
|
||||
* use a mixed syntax for the formula). The input should be
|
||||
* terminated with a newline.
|
||||
*
|
||||
* Argument: stream -- A reference to the input stream.
|
||||
*
|
||||
* Returns: A pointer to the formula. The function throws an
|
||||
* LtlFormula::ParseErrorException if the syntax is incorrect,
|
||||
* or an IOException in case of an end-of-file or another I/O
|
||||
* error.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
Exceptional_istream es(&stream, ios::badbit | ios::failbit | ios::eofbit);
|
||||
estream = &es;
|
||||
intermediate_results.clear();
|
||||
|
||||
try
|
||||
{
|
||||
ltl_parse();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
for (std::set<LtlFormula*, less<LtlFormula*>, ALLOC(LtlFormula*) >
|
||||
::const_iterator f = intermediate_results.begin();
|
||||
f != intermediate_results.end();
|
||||
++f)
|
||||
LtlFormula::destruct(*f);
|
||||
throw;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* The lexical scanner.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static int ltl_lex()
|
||||
{
|
||||
char c;
|
||||
std::istream& stream = static_cast<istream&>(*estream);
|
||||
|
||||
do
|
||||
{
|
||||
estream->get(c);
|
||||
}
|
||||
while (isspace(c) && c != '\n');
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\n' : return 0;
|
||||
|
||||
case '(' :
|
||||
return (matchCharactersFromStream(stream, ")") == 1
|
||||
? LTLPARSE_NEXT
|
||||
: LTLPARSE_LPAR);
|
||||
|
||||
case ')' : return LTLPARSE_RPAR;
|
||||
|
||||
case 'f' :
|
||||
switch (matchCharactersFromStream(stream, "alse"))
|
||||
{
|
||||
case 0 : case 4 :
|
||||
return LTLPARSE_FALSE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return LTLPARSE_UNKNOWN;
|
||||
|
||||
case '0' : return LTLPARSE_FALSE;
|
||||
|
||||
case 't' :
|
||||
switch (matchCharactersFromStream(stream, "rue"))
|
||||
{
|
||||
case 0 : case 3 :
|
||||
return LTLPARSE_TRUE;
|
||||
default :
|
||||
return LTLPARSE_UNKNOWN;
|
||||
}
|
||||
|
||||
case 'T' :
|
||||
return (matchCharactersFromStream(stream, "RUE") == 3
|
||||
? LTLPARSE_TRUE
|
||||
: LTLPARSE_UNKNOWN);
|
||||
|
||||
case '1' : return LTLPARSE_TRUE;
|
||||
|
||||
case '!' : case '~' : return LTLPARSE_NOT;
|
||||
|
||||
case '&' :
|
||||
matchCharactersFromStream(stream, "&");
|
||||
return LTLPARSE_AND;
|
||||
|
||||
case '/' :
|
||||
return (matchCharactersFromStream(stream, "\\") == 1
|
||||
? LTLPARSE_AND
|
||||
: LTLPARSE_UNKNOWN);
|
||||
|
||||
case '*' : return LTLPARSE_AND;
|
||||
|
||||
case '|' :
|
||||
matchCharactersFromStream(stream, "|");
|
||||
return LTLPARSE_OR;
|
||||
|
||||
case '\\' :
|
||||
return (matchCharactersFromStream(stream, "/") == 1
|
||||
? LTLPARSE_OR
|
||||
: LTLPARSE_UNKNOWN);
|
||||
|
||||
case '+' : return LTLPARSE_OR;
|
||||
|
||||
case '=' :
|
||||
return (matchCharactersFromStream(stream, ">") == 1
|
||||
? LTLPARSE_IMPLY
|
||||
: LTLPARSE_EQUALS);
|
||||
|
||||
case '-' :
|
||||
return (matchCharactersFromStream(stream, ">") == 1
|
||||
? LTLPARSE_IMPLY
|
||||
: LTLPARSE_UNKNOWN);
|
||||
|
||||
case 'i' : return LTLPARSE_IMPLY;
|
||||
|
||||
case '<' :
|
||||
if (matchCharactersFromStream(stream, ">") == 1)
|
||||
return LTLPARSE_FINALLY;
|
||||
return (matchCharactersFromStream(stream, "->") == 2
|
||||
|| matchCharactersFromStream(stream, "=>") == 2
|
||||
? LTLPARSE_EQUIV
|
||||
: LTLPARSE_UNKNOWN);
|
||||
|
||||
case 'e' : return LTLPARSE_EQUIV;
|
||||
|
||||
case 'x' :
|
||||
return (matchCharactersFromStream(stream, "or") == 2
|
||||
? LTLPARSE_XOR
|
||||
: LTLPARSE_UNKNOWN);
|
||||
|
||||
case '^' : return LTLPARSE_XOR;
|
||||
|
||||
case 'X' : return LTLPARSE_NEXT;
|
||||
|
||||
case 'U' : return LTLPARSE_UNTIL;
|
||||
|
||||
case 'V' : case 'R' : return LTLPARSE_RELEASE;
|
||||
|
||||
case 'W' : return LTLPARSE_WEAK_UNTIL;
|
||||
|
||||
case 'M' : return LTLPARSE_STRONG_RELEASE;
|
||||
|
||||
case 'B' : return LTLPARSE_BEFORE;
|
||||
|
||||
case 'F' :
|
||||
switch (matchCharactersFromStream(stream, "ALSE"))
|
||||
{
|
||||
case 0 :
|
||||
return LTLPARSE_FINALLY;
|
||||
case 4 :
|
||||
return LTLPARSE_FALSE;
|
||||
default :
|
||||
return LTLPARSE_UNKNOWN;
|
||||
}
|
||||
|
||||
case '[' :
|
||||
return (matchCharactersFromStream(stream, "]") == 1
|
||||
? LTLPARSE_GLOBALLY
|
||||
: LTLPARSE_UNKNOWN);
|
||||
|
||||
case 'G' : return LTLPARSE_GLOBALLY;
|
||||
|
||||
case 'p' :
|
||||
{
|
||||
long int id = 0;
|
||||
bool id_ok = false;
|
||||
int ch = stream.peek();
|
||||
while (ch >= '0' && ch <= '9')
|
||||
{
|
||||
id_ok = true;
|
||||
estream->get(c);
|
||||
if (LONG_MAX / 10 < id)
|
||||
throw LtlFormula::ParseErrorException
|
||||
("error parsing LTL formula (proposition identifier out of "
|
||||
"range)");
|
||||
id *= 10;
|
||||
id += (c - '0');
|
||||
ch = stream.peek();
|
||||
}
|
||||
|
||||
if (id_ok)
|
||||
{
|
||||
ltl_lval.formula = newFormula(Atom::construct(id));
|
||||
return LTLPARSE_ATOM;
|
||||
}
|
||||
return LTLPARSE_UNKNOWN;
|
||||
}
|
||||
|
||||
default : return LTLPARSE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
2936
lbtt/src/Product.h
Normal file
2936
lbtt/src/Product.h
Normal file
File diff suppressed because it is too large
Load diff
1174
lbtt/src/SccCollection.h
Normal file
1174
lbtt/src/SccCollection.h
Normal file
File diff suppressed because it is too large
Load diff
430
lbtt/src/StateSpaceProduct.h
Normal file
430
lbtt/src/StateSpaceProduct.h
Normal file
|
|
@ -0,0 +1,430 @@
|
|||
/*
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
|
||||
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef STATESPACEPRODUCT_H
|
||||
#define STATESPACEPRODUCT_H
|
||||
|
||||
#include <config.h>
|
||||
#include "BitArray.h"
|
||||
#include "BuchiAutomaton.h"
|
||||
#include "EdgeContainer.h"
|
||||
#include "Graph.h"
|
||||
#include "StateSpace.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Graph
|
||||
{
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* A class with operations for checking the product of a Büchi automaton and
|
||||
* a state space for emptiness.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
class StateSpaceProduct
|
||||
{
|
||||
public:
|
||||
StateSpaceProduct /* Constructor. */
|
||||
(const Graph<GraphEdgeContainer>& a,
|
||||
const Graph<GraphEdgeContainer>& s);
|
||||
|
||||
/* default copy constructor */
|
||||
|
||||
~StateSpaceProduct(); /* Destructor. */
|
||||
|
||||
/* default assignment operator */
|
||||
|
||||
bool empty() const; /* Tells whether the
|
||||
* product of a Büchi
|
||||
* automaton and a state
|
||||
* space is (trivially)
|
||||
* empty.
|
||||
*/
|
||||
|
||||
unsigned long int numberOfAcceptanceSets() const; /* Tells the number of
|
||||
* acceptance sets in a
|
||||
* Büchi automaton in its
|
||||
* product with a state
|
||||
* space.
|
||||
*/
|
||||
|
||||
const BuchiAutomaton::BuchiState& firstComponent /* Mappings between a */
|
||||
(const Graph<GraphEdgeContainer>::size_type /* product state */
|
||||
state_id) const; /* identifier and */
|
||||
const StateSpace::State& secondComponent /* states of the Büchi */
|
||||
(const Graph<GraphEdgeContainer>::size_type /* automaton and the */
|
||||
state_id) const; /* state space forming
|
||||
* the product.
|
||||
*/
|
||||
|
||||
void mergeAcceptanceInformation /* Merges the acceptance */
|
||||
(const Graph<GraphEdgeContainer>::Node& state, /* sets associated with */
|
||||
const Graph<GraphEdgeContainer>::Node&, /* a state in the Büchi */
|
||||
BitArray& acceptance_sets) const; /* automaton into a
|
||||
* collection of sets.
|
||||
*/
|
||||
|
||||
void mergeAcceptanceInformation /* Merges the acceptance */
|
||||
(const Graph<GraphEdgeContainer>::Edge& /* sets associated with */
|
||||
buchi_transition, /* a transition in the */
|
||||
const Graph<GraphEdgeContainer>::Edge&, /* Büchi automaton into */
|
||||
BitArray& acceptance_sets) const; /* a collection of sets. */
|
||||
|
||||
void validateEdgeIterators /* Ensures that a pair */
|
||||
(const Graph<GraphEdgeContainer>::Node& /* of transition */
|
||||
buchi_state, /* iterators points to a */
|
||||
const Graph<GraphEdgeContainer>::Node& /* transition beginning */
|
||||
system_state, /* from a given state in */
|
||||
GraphEdgeContainer::const_iterator& /* the product of a */
|
||||
buchi_transition, /* Büchi automaton and */
|
||||
GraphEdgeContainer::const_iterator& /* a state space. */
|
||||
system_transition) const;
|
||||
|
||||
void incrementEdgeIterators /* Updates a pair of */
|
||||
(const Graph<GraphEdgeContainer>::Node& /* transition iterators */
|
||||
buchi_state, /* to make them point to */
|
||||
const Graph<GraphEdgeContainer>::Node& /* the "next" transition */
|
||||
system_state, /* starting from a given */
|
||||
GraphEdgeContainer::const_iterator& /* state in the product */
|
||||
buchi_transition, /* of a Büchi automaton */
|
||||
GraphEdgeContainer::const_iterator& /* and a state space. */
|
||||
system_transition) const;
|
||||
|
||||
private:
|
||||
const BuchiAutomaton& buchi_automaton; /* Büchi automaton
|
||||
* associated with the
|
||||
* product.
|
||||
*/
|
||||
|
||||
const StateSpace& statespace; /* State space associated
|
||||
* with the product.
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Inline function definitions for class StateSpaceProduct.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/* ========================================================================= */
|
||||
inline StateSpaceProduct::StateSpaceProduct
|
||||
(const Graph<GraphEdgeContainer>& a, const Graph<GraphEdgeContainer>& s) :
|
||||
buchi_automaton(static_cast<const BuchiAutomaton&>(a)),
|
||||
statespace(static_cast<const StateSpace&>(s))
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Constructor for class StateSpaceProduct. Initializes a new
|
||||
* object with operations for checking the emptiness of the
|
||||
* product of a Büchi automaton and a state space.
|
||||
*
|
||||
* Arguments: a -- A constant reference to a Graph<GraphEdgeContainer>
|
||||
* object, assumed to be a BuchiAutomaton.
|
||||
* s -- A constant reference to a Graph<GraphEdgeContainer>
|
||||
* object, assumed to be a StateSpace.
|
||||
*
|
||||
* Returns: Nothing.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline StateSpaceProduct::~StateSpaceProduct()
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Destructor for class StateSpaceProduct.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: Nothing.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline bool StateSpaceProduct::empty() const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Tells whether the product of `this->buchi_automaton' and
|
||||
* `this->statespace' is (trivially) empty.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: true iff either the Büchi automaton or the state space has
|
||||
* no states.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
return (buchi_automaton.empty() || statespace.empty());
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline unsigned long int StateSpaceProduct::numberOfAcceptanceSets() const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Tells the number of acceptance sets in the Büchi automaton
|
||||
* associated with a StateSpaceProduct object.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: The number of acceptance sets in the automaton.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
return buchi_automaton.numberOfAcceptanceSets();
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline const BuchiAutomaton::BuchiState& StateSpaceProduct::firstComponent
|
||||
(const Graph<GraphEdgeContainer>::size_type state_id) const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Function for accessing states in the Büchi automaton
|
||||
* associated with a StateSpaceProduct object.
|
||||
*
|
||||
* Argument: state_id -- Identifier of a state in the automaton.
|
||||
*
|
||||
* Returns: A constant reference to a state in the automaton.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
return buchi_automaton[state_id];
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline const StateSpace::State& StateSpaceProduct::secondComponent
|
||||
(const Graph<GraphEdgeContainer>::size_type state_id) const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Function for accessing states in the state space associated
|
||||
* with a StateSpaceProduct object.
|
||||
*
|
||||
* Argument: state_id -- Identifier of a state in the state space.
|
||||
*
|
||||
* Returns: A constant reference to a state in the state space.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
return statespace[state_id];
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline void StateSpaceProduct::mergeAcceptanceInformation
|
||||
(const Graph<GraphEdgeContainer>::Node& state,
|
||||
const Graph<GraphEdgeContainer>::Node&, BitArray& acceptance_sets) const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Merges the acceptance sets associated with a state of a Büchi
|
||||
* automaton into a collection of sets.
|
||||
*
|
||||
* Arguments: state -- A constant reference to a state in the
|
||||
* automaton.
|
||||
* acceptance_sets -- A reference to a BitArray for storing
|
||||
* the result. The BitArray should have
|
||||
* capacity for (at least)
|
||||
* `this->buchi_automaton
|
||||
* .numberOfAcceptanceSets()' bits.
|
||||
* (The second argument is needed to allow the class
|
||||
* StateSpaceProduct to be used for instantiating the Product
|
||||
* template; see file Product.h.)
|
||||
*
|
||||
* Returns: Nothing. After the operation, `acceptance_sets[i] == true'
|
||||
* holds if `state.acceptanceSets().test(i) == true' for all
|
||||
* 0 <= i < `this->buchi_automaton.numberOfAcceptanceSets()'.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
acceptance_sets.bitwiseOr
|
||||
(static_cast<const BuchiAutomaton::BuchiState&>(state).acceptanceSets(),
|
||||
numberOfAcceptanceSets());
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline void StateSpaceProduct::mergeAcceptanceInformation
|
||||
(const Graph<GraphEdgeContainer>::Edge& buchi_transition,
|
||||
const Graph<GraphEdgeContainer>::Edge&, BitArray& acceptance_sets) const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Merges the acceptance sets associated with a transition of a
|
||||
* Büchi automaton into a collection of sets.
|
||||
*
|
||||
* Arguments: transition -- A constant reference to a transition in
|
||||
* the automaton.
|
||||
* acceptance_sets -- A reference to a BitArray for storing
|
||||
* the result. The BitArray should have
|
||||
* capacity for (at least)
|
||||
* `this->buchi_automaton
|
||||
* .numberOfAcceptanceSets()' bits.
|
||||
* (The second argument is needed to allow the class
|
||||
* StateSpaceProduct to be used for instantiating the Product
|
||||
* template; see file Product.h.)
|
||||
*
|
||||
* Returns: Nothing. After the operation, `acceptance_sets[i] == true'
|
||||
* holds if `transition.acceptanceSets().test(i) == true' for
|
||||
* all
|
||||
* 0 <= i < `this->buchi_automaton.numberOfAcceptanceSets()'.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
acceptance_sets.bitwiseOr
|
||||
(static_cast<const BuchiAutomaton::BuchiTransition&>(buchi_transition)
|
||||
.acceptanceSets(),
|
||||
numberOfAcceptanceSets());
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline void StateSpaceProduct::validateEdgeIterators
|
||||
(const Graph<GraphEdgeContainer>::Node& buchi_state,
|
||||
const Graph<GraphEdgeContainer>::Node& system_state,
|
||||
GraphEdgeContainer::const_iterator& buchi_transition,
|
||||
GraphEdgeContainer::const_iterator& system_transition) const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Checks whether a pair of transition iterators corresponds to
|
||||
* a transition beginning from a state in the product of a Büchi
|
||||
* automaton and a state space; if this is not the case, makes
|
||||
* the iterators point to a valid transition beginning from the
|
||||
* product state (or to the "end" of the collection of
|
||||
* transitions beginning from the product state if no valid
|
||||
* transition can be found by incrementing the iterators).
|
||||
*
|
||||
* Arguments: buchi_state, -- These variables determine the state
|
||||
* system_state, in the product; `buchi_state' and
|
||||
* `system_state' should be references to
|
||||
* states in `this->buchi_automaton' and
|
||||
* `this->statespace', respectively.
|
||||
* buchi_transition, -- References to the transition
|
||||
* system_transition iterators. It is assumed that
|
||||
* `buchi_transition' and
|
||||
* `system_transition' initially point to
|
||||
* two transitions starting from
|
||||
* `buchi_state' and `system_state',
|
||||
* respectively.
|
||||
*
|
||||
* Returns: Nothing. Upon return, `buchi_transition' and
|
||||
* `system_transition' will either equal
|
||||
* `buchi_state.edges().end()' and `system_state.edges().end()',
|
||||
* respectively, or they will point to a pair of transitions
|
||||
* beginning from `buchi_state' and `system_state' such that
|
||||
* this pair of transitions corresponds to a transition starting
|
||||
* from the product state determined by `buchi_state' and
|
||||
* `system_state'.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
const GraphEdgeContainer& buchi_transitions = buchi_state.edges();
|
||||
const GraphEdgeContainer& system_transitions = system_state.edges();
|
||||
|
||||
if (buchi_transition == buchi_transitions.end())
|
||||
{
|
||||
system_transition = system_transitions.end();
|
||||
return;
|
||||
}
|
||||
if (system_transition == system_transitions.end())
|
||||
{
|
||||
buchi_transition = buchi_transitions.end();
|
||||
return;
|
||||
}
|
||||
|
||||
while (!static_cast<const BuchiAutomaton::BuchiTransition*>
|
||||
(*buchi_transition)->enabled
|
||||
(static_cast<const StateSpace::State&>(system_state)
|
||||
.positiveAtoms(),
|
||||
statespace.numberOfPropositions()))
|
||||
{
|
||||
++buchi_transition;
|
||||
if (buchi_transition == buchi_transitions.end())
|
||||
{
|
||||
system_transition = system_transitions.end();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
system_transition = system_transitions.begin();
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline void StateSpaceProduct::incrementEdgeIterators
|
||||
(const Graph<GraphEdgeContainer>::Node& buchi_state,
|
||||
const Graph<GraphEdgeContainer>::Node& system_state,
|
||||
GraphEdgeContainer::const_iterator& buchi_transition,
|
||||
GraphEdgeContainer::const_iterator& system_transition) const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Increments a pair of transition iterators to point to the
|
||||
* "next" transition beginning from a state in the product of a
|
||||
* Büchi automaton and a state space. If no "next" transition
|
||||
* exists, makes the iterators point to the "end" of the
|
||||
* collection of transitions beginning from the product state.
|
||||
*
|
||||
* Arguments: buchi_state, -- These variables determine the state
|
||||
* system_state, in the product; `buchi_state' and
|
||||
* `system_state' should be references to
|
||||
* states in `this->buchi_automaton' and
|
||||
* `this->statespace', respectively.
|
||||
* buchi_transition, -- References to the transition
|
||||
* system_transition iterators. It is assumed that
|
||||
* `buchi_transition' and
|
||||
* `system_transition' initially point to
|
||||
* two transitions starting from
|
||||
* `buchi_state' and `system_state',
|
||||
* respectively.
|
||||
*
|
||||
* Returns: Nothing. Upon return, `buchi_transition' and
|
||||
* `system_transition' will either equal
|
||||
* `buchi_state.edges().end()' and `system_state.edges().end()',
|
||||
* respectively, or they will point to a pair of transitions
|
||||
* beginning from `buchi_state' and `system_state' such that
|
||||
* this pair of transitions corresponds to a transition starting
|
||||
* from the product state determined by `buchi_state' and
|
||||
* `system_state'.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
const GraphEdgeContainer& buchi_transitions = buchi_state.edges();
|
||||
const GraphEdgeContainer& system_transitions = system_state.edges();
|
||||
|
||||
++system_transition;
|
||||
if (system_transition == system_transitions.end())
|
||||
{
|
||||
do
|
||||
{
|
||||
++buchi_transition;
|
||||
if (buchi_transition == buchi_transitions.end())
|
||||
return;
|
||||
}
|
||||
while (!static_cast<const BuchiAutomaton::BuchiTransition*>
|
||||
(*buchi_transition)->enabled
|
||||
(static_cast<const StateSpace::State&>(system_state)
|
||||
.positiveAtoms(),
|
||||
statespace.numberOfPropositions()));
|
||||
|
||||
system_transition = system_transitions.begin();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* !STATESPACEPRODUCT_H */
|
||||
125
lbtt/src/TempFsysName.cc
Normal file
125
lbtt/src/TempFsysName.cc
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright (C) 2004
|
||||
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif /* HAVE_FCNTL_H */
|
||||
#include <string>
|
||||
#include "Exception.h"
|
||||
#include "StringUtil.h"
|
||||
#include "TempFsysName.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Number of generated temporary names.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
unsigned long int TempFsysName::number_of_allocated_names = 0;
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Function definitions for class TempFsysName.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/* ========================================================================= */
|
||||
const char* TempFsysName::allocate
|
||||
(const char* prefix, const NameType t, const bool literal)
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Associates a TempFsysName object with a temporary name. (As
|
||||
* a side effect, the function actually creates an empty
|
||||
* temporary file or a directory to reserve the name in the file
|
||||
* system. The file or directory should never be removed
|
||||
* explicitly; it is removed automatically when the TempFsysName
|
||||
* object is destroyed or another call is made to
|
||||
* `this->allocate'.)
|
||||
*
|
||||
* Arguments: prefix -- Pointer to a C-style string containing a prefix
|
||||
* for the temporary name (empty by default). If
|
||||
* `literal == true', `prefix' (if nonempty) is
|
||||
* assumed to contain the full path for the
|
||||
* temporary file or directory; otherwise the
|
||||
* function will reserve a temporary name in the
|
||||
* `P_tmpdir' directory. This name will consist
|
||||
* of the value of `prefix' (if nonempty), followed
|
||||
* by the current value of
|
||||
* `TempFsysName::number_of_allocated_names' and
|
||||
* the current process id, separated by dots.
|
||||
* t -- Determines the type of the name (file or a
|
||||
* directory).
|
||||
* literal -- See above.
|
||||
*
|
||||
* Returns: A pointer to a constant C-style string containing the
|
||||
* temporary name. The function throws an IOException if the
|
||||
* name allocation or the file or directory creation fails.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
releaseName();
|
||||
|
||||
using ::StringUtil::toString;
|
||||
string tempname;
|
||||
|
||||
try
|
||||
{
|
||||
if (!literal || strlen(prefix) == 0)
|
||||
{
|
||||
tempname = toString(P_tmpdir) + "/";
|
||||
if (strlen(prefix))
|
||||
tempname += string(prefix) + ".";
|
||||
tempname += toString(number_of_allocated_names) + "."
|
||||
+ toString(getpid());
|
||||
++number_of_allocated_names;
|
||||
}
|
||||
else
|
||||
tempname = prefix;
|
||||
|
||||
name = new char[tempname.length() + 1];
|
||||
strcpy(name, tempname.c_str());
|
||||
}
|
||||
catch (const bad_alloc&)
|
||||
{
|
||||
name = 0;
|
||||
throw IOException
|
||||
("unable to allocate a temporary name in the file system");
|
||||
}
|
||||
|
||||
type = t;
|
||||
if (t == FILE)
|
||||
{
|
||||
int fd = open(name, O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
|
||||
if (fd == -1)
|
||||
throw IOException("unable to create a temporary file");
|
||||
close(fd);
|
||||
}
|
||||
else if (mkdir(name, S_IRWXU) == -1)
|
||||
throw IOException("unable to create a temporary directory");
|
||||
|
||||
return name;
|
||||
}
|
||||
157
lbtt/src/TempFsysName.h
Normal file
157
lbtt/src/TempFsysName.h
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright (C) 2004
|
||||
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef TEMPFSYSNAME_H
|
||||
#define TEMPFSYSNAME_H
|
||||
|
||||
#include <config.h>
|
||||
#include <cstdio>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* A class for temporary file system names.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
class TempFsysName
|
||||
{
|
||||
public:
|
||||
TempFsysName(); /* Constructor. */
|
||||
|
||||
~TempFsysName(); /* Destructor. */
|
||||
|
||||
enum NameType { FILE, DIRECTORY }; /* Types of temporary
|
||||
* file system names.
|
||||
*/
|
||||
|
||||
const char* allocate /* Allocates a name */
|
||||
(const char* prefix = "", /* in the file system. */
|
||||
const NameType t = FILE,
|
||||
const bool literal = false);
|
||||
|
||||
const char* get() const; /* Tells the name. */
|
||||
|
||||
private:
|
||||
TempFsysName(const TempFsysName&); /* Prevent copying and */
|
||||
TempFsysName& operator=(const TempFsysName&); /* assignment of
|
||||
* TempFsysName objects.
|
||||
*/
|
||||
|
||||
void releaseName(); /* Frees a name in the file
|
||||
* system.
|
||||
*/
|
||||
|
||||
char* name; /* Temporary name. */
|
||||
|
||||
NameType type; /* Tells whether the name
|
||||
* refers to a file or a
|
||||
* directory.
|
||||
*/
|
||||
|
||||
static unsigned long int /* Counter for the */
|
||||
number_of_allocated_names; /* number of generated
|
||||
* temporary names.
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Inline function definitions for class TempFsysName.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/* ========================================================================= */
|
||||
inline TempFsysName::TempFsysName() : name(static_cast<char*>(0))
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Constructor for class TempFsysName.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: Nothing.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline TempFsysName::~TempFsysName()
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Destructor for class TempFsysName.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: Nothing.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
releaseName();
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline const char* TempFsysName::get() const
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Tells the name associated with the TempFsysName object.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: A pointer to a constant C-style string containing the name
|
||||
* associated with the TempFsysName object. If the TempFsysName
|
||||
* object has not yet been (successfully) associated with a file
|
||||
* using TempFsysName::allocate, this pointer has the value 0.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
inline void TempFsysName::releaseName()
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Description: Deallocates the memory reserved for `this->name' and frees
|
||||
* the name also in the file system by removing the file or
|
||||
* directory associated with the object. If the name
|
||||
* is associated with a directory, the directory is assumed to
|
||||
* be empty.
|
||||
*
|
||||
* Arguments: None.
|
||||
*
|
||||
* Returns: Nothing.
|
||||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
{
|
||||
if (name == static_cast<char*>(0))
|
||||
return;
|
||||
if (type == FILE)
|
||||
remove(name);
|
||||
else
|
||||
rmdir(name);
|
||||
delete[] name;
|
||||
name = 0;
|
||||
}
|
||||
|
||||
#endif /* !TEMPFSYSNAME_H */
|
||||
Loading…
Add table
Add a link
Reference in a new issue