Source: classlib/include/classlib/dlistimp.h
|
|
|
|
/***************************************************************************
dlistimp.h - liste e doppie liste
-------------------
begin : ven dic 7 17:40:01 CET 2001
copyright : (C) 2001 by Nicola De Nisco
email : nicola@winada.it
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#if !defined( __CLASSLIB_DLISTIMP_H )
#define __CLASSLIB_DLISTIMP_H
#if !defined( __LIMITS_H )
#include
#endif // __LIMITS_H
#if !defined( __CHECKS_H )
#include
#endif // __CHECKS_H
#if !defined( __CLASSLIB_DEFS_H )
#include "classlib/defs.h"
#endif // __CLASSLIB_DEFS_H
#if !defined( __CLASSLIB_MEMMGR_H )
#include "classlib/memmgr.h"
#endif // __CLASSLIB_MEMMGR_H
#if !defined( __CLASSLIB_ALLOCTR_H )
#include "classlib/alloctr.h"
#endif // __CLASSLIB_ALLOCTR_H
#if !defined( __CLASSLIB_VOIDP_H )
#include "classlib/voidp.h"
#endif // __CLASSLIB_VOIDP_H
template class TMDoubleListImp;
template class TMDoubleListElement;
/**
template class TMDoubleListBlockInitializer
Implements base opertion for memory block allocation
used by list items.
*/
template class TMDoubleListBlockInitializer
{
typedef TMDoubleListElement Element;
protected:
TMDoubleListBlockInitializer();
~TMDoubleListBlockInitializer();
static unsigned Count;
};
template
TMDoubleListBlockInitializer::TMDoubleListBlockInitializer()
{
PRECONDITION( Count != UINT_MAX );
if( Count++ == 0 )
Element::Mgr =
new TMMemBlocks( sizeof(TMDoubleListElement), 20 );
}
template
TMDoubleListBlockInitializer::~TMDoubleListBlockInitializer()
{
PRECONDITION( Count != 0 );
if( --Count == 0 )
{
delete (Element::Mgr);
Element::Mgr = 0;
}
}
template
unsigned TMDoubleListBlockInitializer::Count = 0;
/**
template class TMDoubleListElement
Node for templates TMDoubleListImp and
TMIDoubleListImp
*/
template class TMDoubleListElement
{
public:
TMDoubleListElement( const T& t, TMDoubleListElement *p ) :
Data(t)
{
Next = p->Next;
Prev = p;
p->Next = this;
Next->Prev = this;
}
TMDoubleListElement();
TMDoubleListElement *Next;
TMDoubleListElement *Prev;
T Data;
private:
friend class TMDoubleListBlockInitializer;
static TMMemBlocks *Mgr;
};
template
TMMemBlocks *TMDoubleListElement::Mgr = 0;
template
inline TMDoubleListElement::TMDoubleListElement()
{
Next = Prev = 0;
}
template class TMDoubleListIteratorImp;
/**
template class TMDoubleListImp
Implements a managed double-linked list of objects of type T.
Assumes that T has meaningful copy semantics and a default
constructor.
*/
template class TMDoubleListImp :
private TMDoubleListBlockInitializer
{
typedef TMDoubleListBlockInitializer Parent;
public:
typedef void (*IterFunc)(T&, void *);
typedef int (*CondFunc)(const T&, void *);
friend class TMDoubleListIteratorImp;
TMDoubleListImp()
{
InitList();
}
virtual ~TMDoubleListImp()
{
Flush();
}
const T& PeekHead() const
{
return Head.Next->Data;
}
const T& PeekTail() const
{
return Tail.Prev->Data;
}
int Add( const T& t )
{
return AddElement(t,&Head);
}
int AddAtHead( const T& t )
{
return AddElement(t,&Head);
}
int AddAtTail( const T& t )
{
return AddElement(t,Tail.Prev);
}
int Detach( const T& t )
{
return DoDetach(t,0);
}
int DetachAtHead()
{
return DoDetachAtHead(0);
}
int DetachAtTail()
{
return DoDetachAtTail(0);
}
T *Find( const T& t );
void Flush()
{
DoFlush(0);
}
int IsEmpty() const
{
return ItemsInContainer == 0;
}
int GetItemsInContainer() const
{
return ItemsInContainer;
}
void ForEach( IterFunc iter, void *args );
T *FirstThat( CondFunc cond, void *args ) const;
T *LastThat( CondFunc cond, void *args ) const;
protected:
int DoDetach( const T& t, int del = 0 )
{
return DetachElement(FindDetach(t),del);
}
int DoDetachAtHead( int del = 0 )
{
return DetachElement(&Head,del);
}
int DoDetachAtTail( int del = 0 )
{
return DetachElement(Tail.Prev->Prev,del);
}
void DoFlush( int del = 0 );
TMDoubleListElement Head, Tail;
virtual TMDoubleListElement *FindDetach( const T& t )
{
return FindPred(t);
}
virtual TMDoubleListElement *FindPred( const T& );
int ItemsInContainer;
private:
virtual void RemoveData( TMDoubleListElement * )
{
}
void InitList();
int DetachElement( TMDoubleListElement *element, int del = 0 );
int AddElement( const T& t, TMDoubleListElement *element );
};
template void TMDoubleListImp::InitList()
{
Head.Next = &Tail;
Head.Prev = &Head;
Tail.Prev = &Head;
Tail.Next = &Tail;
ItemsInContainer = 0;
}
template
int TMDoubleListImp::AddElement( const T& toAdd,
TMDoubleListElement *Pos )
{
new TMDoubleListElement( toAdd, Pos );
ItemsInContainer++;
return 1;
}
template
TMDoubleListElement *TMDoubleListImp::FindPred( const T&t )
{
Tail.Data = t;
TMDoubleListElement *cursor = &Head;
while( !(t == cursor->Next->Data) )
cursor = cursor->Next;
Tail.Data = T();
return cursor;
}
template
int TMDoubleListImp::DetachElement(
TMDoubleListElement *pred, int del )
{
TMDoubleListElement *item = pred->Next;
if( item == &Tail )
return 0;
else
{
pred->Next = pred->Next->Next;
pred->Next->Prev = pred;
if( del != 0 )
RemoveData( item );
delete item;
ItemsInContainer--;
return 1;
}
}
template
T *TMDoubleListImp::Find( const T& t )
{
TMDoubleListElement *pred = FindPred(t);
if( pred->Next == &Tail )
return 0;
else
return &pred->Next->Data;
}
template
void TMDoubleListImp::DoFlush( int del )
{
TMDoubleListElement *current = Head.Next;
while( current != &Tail )
{
TMDoubleListElement *temp = current;
current = current->Next;
if( del != 0 )
RemoveData( temp );
delete temp;
}
InitList();
}
template
void TMDoubleListImp::ForEach( IterFunc f, void *args
)
{
TMDoubleListElement *cur = Head.Next;
while( cur->Next != cur )
{
f( cur->Data, args );
cur = cur->Next;
}
}
template
T *TMDoubleListImp::FirstThat( CondFunc cond, void *args ) const
{
TMDoubleListElement *cur = Head.Next;
while( cur->Next != cur )
if( cond( cur->Data, args ) != 0 )
return &(cur->Data);
else
cur = cur->Next;
return 0;
}
template
T *TMDoubleListImp::LastThat( CondFunc cond, void *args ) const
{
T *res = 0;
TMDoubleListElement *cur = Head.Next;
while( cur->Next != cur )
{
if( cond( cur->Data, args ) != 0 )
res = &(cur->Data);
cur = cur->Next;
}
return res;
}
template class TMDoubleListImp;
template class TMSDoubleListImp;
/**
template class TMDoubleListIteratorImp
Implements a double list iterator. This iterator works with any
direct double list. For indirect lists, see
TMIDoubleListIteratorImp.
*/
template class TMDoubleListIteratorImp
{
typedef TMDoubleListImp MListImp;
typedef TMSDoubleListImp MSListImp;
public:
TMDoubleListIteratorImp( const MListImp& l )
{
List = &l;
Cur = List->Head.Next;
}
TMDoubleListIteratorImp( const MSListImp& l );
operator int()
{
return Cur != &(List->Head) && Cur != &(List->Tail);
}
const T& Current()
{
PRECONDITION( int(*this) != 0 );
return Cur->Data;
}
const T& operator ++ ( int )
{
PRECONDITION( Cur != &(List->Tail) );
TMDoubleListElement *temp = Cur;
Cur = Cur->Next;
return temp->Data;
}
const T& operator ++ ()
{
PRECONDITION( Cur->Next != &(List->Tail) );
Cur = Cur->Next;
return Cur->Data;
}
const T& operator -- ( int )
{
PRECONDITION( Cur != &(List->Head) );
TMDoubleListElement *temp = Cur;
Cur = Cur->Prev;
return temp->Data;
}
const T& operator -- ()
{
PRECONDITION( Cur->Prev != &(List->Head) );
Cur = Cur->Prev;
return Cur->Data;
}
void Restart()
{
Cur = List->Head.Next;
}
void RestartAtTail()
{
Cur = List->Tail.Prev;
}
private:
const TMDoubleListImp *List;
TMDoubleListElement *Cur;
};
/**
template class TDoubleListImp
template class TDoubleListIteratorImp
Implements a double-linked list of objects of type T.
Assumes that T has meaningful copy semantics and a default constructor.
*/
template class TDoubleListImp :
public TMDoubleListImp
{
};
template class TSDoubleListImp;
template class TDoubleListIteratorImp :
public TMDoubleListIteratorImp
{
public:
TDoubleListIteratorImp( const TDoubleListImp& l ) :
TMDoubleListIteratorImp(l) {}
TDoubleListIteratorImp( const TSDoubleListImp& l ) :
TMDoubleListIteratorImp(l) {}
};
/**
template class TMSDoubleListImp
template class TMSDoubleListIteratorImp
Implements a managed sorted double-linked list of objects of type T.
Assumes that T has meaningful copy semantics, a meaningful
< operator, and a default constructor.
*/
template class TMSDoubleListImp :
private TMDoubleListImp
{
typedef TMDoubleListImp Parent;
public:
friend class TMDoubleListIteratorImp;
TMSDoubleListImp()
{
}
virtual ~TMSDoubleListImp()
{
}
int Add( const T& t );
typedef void (*IterFunc)(T&, void *);
typedef int (*CondFunc)(const T&, void *);
Parent::PeekHead;
Parent::PeekTail;
Parent::Detach;
Parent::Find;
Parent::Flush;
Parent::IsEmpty;
Parent::GetItemsInContainer;
Parent::ForEach;
Parent::FirstThat;
Parent::LastThat;
protected:
Parent::Head;
Parent::Tail;
Parent::ItemsInContainer;
Parent::DoDetach;
Parent::DoDetachAtHead;
Parent::DoDetachAtTail;
Parent::DoFlush;
virtual TMDoubleListElement *FindDetach( const T& );
virtual TMDoubleListElement *FindPred( const T& );
};
template class TMSDoubleListIteratorImp :
public TMDoubleListIteratorImp
{
public:
TMSDoubleListIteratorImp( const TMSDoubleListImp& l ) :
TMDoubleListIteratorImp(l) {}
};
template
int TMSDoubleListImp::Add( const T& t )
{
new TMDoubleListElement( t, FindPred(t) );
ItemsInContainer++;
return 1;
}
template
TMDoubleListElement*TMSDoubleListImp::FindDetach(const T&t)
{
TMDoubleListElement *res = FindPred(t);
if( res != 0 &&
res->Next->Data == t )
return res;
else
return &Tail;
}
template
TMDoubleListElement*TMSDoubleListImp::FindPred(const T& t)
{
Tail.Data = t;
TMDoubleListElement *cursor = &Head;
while( cursor->Next->Data < t )
cursor = cursor->Next;
Tail.Data = T();
return cursor;
}
// constructor for TMDoubleListIteratorImp
template
TMDoubleListIteratorImp::TMDoubleListIteratorImp(
const TMSDoubleListImp& l )
{
List = &l;
Cur = List->Head.Next;
}
/**
template class TSDoubleListImp
template class TSDoubleListIteratorImp
Implements a sorted double-linked list of objects of type T. Assumes that T has
meaningful copy semantics, a meaningful < operator, and a default
constructor.
*/
template class TSDoubleListImp :
public TMSDoubleListImp
{
};
/**
template class TSDoubleListImp
template class TSDoubleListIteratorImp
Implements a sorted double-linked list of objects of type T. Assumes that T has
meaningful copy semantics, a meaningful < operator, and a default
constructor.
*/
template class TSDoubleListIteratorImp :
public TMSDoubleListIteratorImp
{
public:
TSDoubleListIteratorImp( const TSDoubleListImp& l ) :
TMSDoubleListIteratorImp(l) {}
};
/**
template
class TMInternalIDoubleListImp
Implements a managed double-linked list of pointers to objects of
type T. This is implemented through the form of TMDoubleListImp
specified by List. Since pointers always have meaningful copy
semantics, this class can handle any type of object.
*/
template class TMInternalIDoubleListImp :
public TMDoubleListImp
{
typedef TMDoubleListImp Parent;
public:
typedef void (*IterFunc)(T&, void *);
typedef int (*CondFunc)(const T&, void *);
T *PeekHead() const
{
return STATIC_CAST(T *, STATIC_CAST(void *, Parent::PeekHead()));
}
T *PeekTail() const
{
return STATIC_CAST(T *, STATIC_CAST(void *, Parent::PeekTail()));
}
int Add( T *t )
{
return Parent::Add( t );
}
int Detach( T *t, int del = 0 )
{
return Parent::DoDetach( t, del );
}
int DetachAtHead( int del = 0 )
{
return Parent::DoDetachAtHead( del );
}
int DetachAtTail( int del = 0 )
{
return Parent::DoDetachAtTail( del );
}
void Flush( int del = 0 )
{
DoFlush( del );
}
void ForEach( IterFunc iter, void * );
T *FirstThat( CondFunc cond, void * ) const;
T *LastThat( CondFunc cond, void * ) const;
protected:
virtual TMDoubleListElement *FindPred( const TVoidPointer& ) = 0;
private:
virtual void RemoveData( TMDoubleListElement *block )
{
delete STATIC_CAST(T *,STATIC_CAST(void *,block->Data));
}
};
template
void TMInternalIDoubleListImp::ForEach( IterFunc iter,
void *args )
{
TMDoubleListElement *cur = Head.Next;
while( cur->Next != cur )
{
iter( *STATIC_CAST(T *,STATIC_CAST(void *,cur->Data)), args );
cur = cur->Next;
}
}
template T *
TMInternalIDoubleListImp::FirstThat( CondFunc cond,
void *args ) const
{
TMDoubleListElement *cur = Head.Next;
while( cur->Next != cur )
if( cond( *STATIC_CAST(T *,STATIC_CAST(void *,cur->Data)), args ) != 0 )
return STATIC_CAST(T *,STATIC_CAST(void *,cur->Data));
else
cur = cur->Next;
return 0;
}
template T *
TMInternalIDoubleListImp::LastThat( CondFunc cond,
void *args ) const
{
T *res = 0;
TMDoubleListElement *cur = Head.Next;
while( cur->Next != cur )
{
if( cond( *STATIC_CAST(T *,STATIC_CAST(void *,cur->Data)), args ) != 0 )
res = STATIC_CAST(T *,STATIC_CAST(void *,cur->Data));
cur = cur->Next;
}
return res;
}
template
class TMInternalIDoubleListIteratorImp :
public TMDoubleListIteratorImp
{
typedef TMDoubleListIteratorImp Parent;
typedef TMInternalIDoubleListImp ToIterate;
public:
TMInternalIDoubleListIteratorImp( const ToIterate& l ) :
TMDoubleListIteratorImp(l) {}
T *Current()
{
return STATIC_CAST(T *,STATIC_CAST(void *,Parent::Current()));
}
T *operator ++ (int)
{
return STATIC_CAST(T *,STATIC_CAST(void *,Parent::operator++(1)));
}
T *operator ++ ()
{
return STATIC_CAST(T *,STATIC_CAST(void *,Parent::operator++()));
}
};
/**
template
class TMSInternalIDoubleListImp
Implements a sorted managed double-linked list of pointers to objects of
type T. This is implemented through the form of TMDoubleListImp
specified by List. Since pointers always have meaningful copy
semantics, this class can handle any type of object.
*/
template class TMSInternalIDoubleListImp :
public TMSDoubleListImp
{
typedef TMSDoubleListImp Parent;
public:
typedef void (*IterFunc)(T&, void *);
typedef int (*CondFunc)(const T&, void *);
T *PeekHead() const
{
return STATIC_CAST(T *, STATIC_CAST(void *, Parent::PeekHead()));
}
T *PeekTail() const
{
return STATIC_CAST(T *, STATIC_CAST(void *, Parent::PeekTail()));
}
int Add( T *t )
{
return Parent::Add( t );
}
int Detach( T *t, int del = 0 )
{
return Parent::DoDetach( t, del );
}
int DetachAtHead( int del = 0 )
{
return Parent::DoDetachAtHead( del );
}
int DetachAtTail( int del = 0 )
{
return Parent::DoDetachAtTail( del );
}
void Flush( int del = 0 )
{
DoFlush( del );
}
void ForEach( IterFunc iter, void * );
T *FirstThat( CondFunc cond, void * ) const;
T *LastThat( CondFunc cond, void * ) const;
protected:
virtual TMDoubleListElement *FindPred( const TVoidPointer& ) = 0;
private:
virtual void RemoveData( TMDoubleListElement *block )
{
delete STATIC_CAST(T *,STATIC_CAST(void *,block->Data));
}
};
template
void TMSInternalIDoubleListImp::ForEach( IterFunc iter,
void *args )
{
TMDoubleListElement *cur = Head.Next;
while( cur->Next != cur )
{
iter( *STATIC_CAST(T *,STATIC_CAST(void *,cur->Data)), args );
cur = cur->Next;
}
}
template T *
TMSInternalIDoubleListImp::FirstThat( CondFunc cond,
void *args ) const
{
TMDoubleListElement *cur = Head.Next;
while( cur->Next != cur )
if( cond( *STATIC_CAST(T *,STATIC_CAST(void *,cur->Data)), args ) != 0 )
return STATIC_CAST(T *,STATIC_CAST(void *,cur->Data));
else
cur = cur->Next;
return 0;
}
template T *
TMSInternalIDoubleListImp::LastThat( CondFunc cond,
void *args ) const
{
T *res = 0;
TMDoubleListElement *cur = Head.Next;
while( cur->Next != cur )
{
if( cond( *STATIC_CAST(T *,STATIC_CAST(void *,cur->Data)), args ) != 0 )
res = STATIC_CAST(T *,STATIC_CAST(void *,cur->Data));
cur = cur->Next;
}
return res;
}
template
class TMSInternalIDoubleListIteratorImp :
public TMDoubleListIteratorImp
{
typedef TMDoubleListIteratorImp Parent;
typedef TMSInternalIDoubleListImp ToIterate;
public:
TMSInternalIDoubleListIteratorImp( const ToIterate& l ) :
TMDoubleListIteratorImp(l) {}
T *Current()
{
return STATIC_CAST(T *,STATIC_CAST(void *,Parent::Current()));
}
T *operator ++ (int)
{
return STATIC_CAST(T *,STATIC_CAST(void *,Parent::operator++(1)));
}
T *operator ++ ()
{
return STATIC_CAST(T *,STATIC_CAST(void *,Parent::operator++()));
}
};
template class TMIDoubleListIteratorImp;
/**
template class TMIDoubleListImp
template class TMIDoubleListIteratorImp
Implements a double-linked list of pointers to objects of
type T. This is implemented through the template
TMInternalIDoubleListImp. Since pointers always have meaningful
copy semantics, this class can handle any type of object.
*/
template class TMIDoubleListImp :
public TMInternalIDoubleListImp
{
typedef TMInternalIDoubleListImp Parent;
public:
friend class TMIDoubleListIteratorImp;
typedef void (*IterFunc)(T&, void *);
typedef int (*CondFunc)(const T&, void *);
Parent::PeekHead;
Parent::PeekTail;
Parent::Add;
Parent::AddAtHead;
Parent::AddAtTail;
Parent::Detach;
Parent::DetachAtHead;
Parent::DetachAtTail;
Parent::Find;
Parent::Flush;
Parent::IsEmpty;
Parent::GetItemsInContainer;
Parent::ForEach;
Parent::FirstThat;
Parent::LastThat;
protected:
Parent::Head;
Parent::Tail;
Parent::ItemsInContainer;
virtual TMDoubleListElement *FindPred(const TVoidPointer&);
};
template class TMIDoubleListIteratorImp :
public TMInternalIDoubleListIteratorImp
{
public:
TMIDoubleListIteratorImp( const TMIDoubleListImp& l ) :
TMInternalIDoubleListIteratorImp( l ) {}
};
template
TMDoubleListElement
*TMIDoubleListImp::FindPred( const TVoidPointer& t )
{
Tail.Data = t;
TMDoubleListElement *cursor = &Head;
while( !(*STATIC_CAST(T *,STATIC_CAST(void *,t)) ==
*STATIC_CAST(T *,STATIC_CAST(void *,cursor->Next->Data))) )
cursor = cursor->Next;
Tail.Data = TVoidPointer();
return cursor;
}
/**
template class TIDoubleListImp
template class TIDoubleListIteratorImp
Implements a double-linked list of pointers to objects of
type T.
This is implemented through the template
TMInternalIDoubleListImp. Since pointers always have meaningful
copy semantics, this class can handle any type of object.
*/
template class TIDoubleListImp :
public TMIDoubleListImp
{
};
template class TIDoubleListIteratorImp :
public TMIDoubleListIteratorImp
{
public:
TIDoubleListIteratorImp( const TIDoubleListImp& l ) :
TMIDoubleListIteratorImp( l ) {}
};
template class TMISDoubleListIteratorImp;
/**
template class TMISDoubleListImp
template class TMISDoubleListIteratorImp
Implements a managed sorted double-linked list of pointers to
objects of type T. This is implemented through the template
TMInternalIDoubleListImp. Since pointers always have meaningful
copy semantics, this class can handle any type of object.
*/
template class TMISDoubleListImp :
public TMSInternalIDoubleListImp
{
typedef TMSInternalIDoubleListImp Parent;
public:
friend class TMISDoubleListIteratorImp;
typedef void (*IterFunc)(T&, void *);
typedef int (*CondFunc)(const T&, void *);
Parent::PeekHead;
Parent::PeekTail;
Parent::Add;
Parent::Detach;
Parent::DetachAtHead;
Parent::DetachAtTail;
Parent::Find;
Parent::Flush;
Parent::IsEmpty;
Parent::GetItemsInContainer;
Parent::ForEach;
Parent::FirstThat;
Parent::LastThat;
protected:
Parent::Head;
Parent::Tail;
Parent::ItemsInContainer;
virtual TMDoubleListElement *FindDetach(const TVoidPointer&);
virtual TMDoubleListElement *FindPred(const TVoidPointer&);
};
template class TMISDoubleListIteratorImp :
public TMSInternalIDoubleListIteratorImp
{
public:
TMISDoubleListIteratorImp( const TMISDoubleListImp& l ) :
TMSInternalIDoubleListIteratorImp( l ) {}
};
template
TMDoubleListElement
*TMISDoubleListImp::FindDetach( const TVoidPointer& t )
{
TMDoubleListElement *res = FindPred(t);
if( res == 0 || res->Next == &Tail )
return &Tail;
else if(
*STATIC_CAST(T *,STATIC_CAST(void *,res->Next->Data)) ==
*STATIC_CAST(T *,STATIC_CAST(void *,t)) )
return res;
else
return &Tail;
}
template
TMDoubleListElement
*TMISDoubleListImp::FindPred( const TVoidPointer& t )
{
Tail.Data = t;
TMDoubleListElement *cursor = &Head;
while( *STATIC_CAST(T *,STATIC_CAST(void *,cursor->Next->Data)) <
*STATIC_CAST(T *,STATIC_CAST(void *,t)) )
cursor = cursor->Next;
Tail.Data = TVoidPointer();
return cursor;
}
/**
template class TISDoubleListImp
template class TISDoubleListIteratorImp
Implements a managed sorted double-linked list of pointers to
objects of type T.
This is implemented through the template
TMInternalIDoubleListImp. Since pointers always have meaningful
copy semantics, this class can handle any type of object.
*/
template class TISDoubleListImp :
public TMISDoubleListImp
{
};
template class TISDoubleListIteratorImp :
public TMISDoubleListIteratorImp
{
public:
TISDoubleListIteratorImp( const TISDoubleListImp& l ) :
TMISDoubleListIteratorImp( l ) {}
};
#endif // __CLASSLIB_DLISTIMP_H
Generated by: nicola on gulliver.wadahome.it on Sun May 25 13:54:34 2003, using kdoc 2.0a53. |