diff --git a/Doxyfile b/Doxyfile index 3247d4e7150e0b50b33a9b608f46cd9bae0b228f..57cdd8de3ee384abf072b9da95cb847d9af88486 100644 --- a/Doxyfile +++ b/Doxyfile @@ -5,6 +5,7 @@ OUTPUT_DIRECTORY = doc INPUT = . FILE_PATTERNS = *.dox IMAGE_PATH = . +EXAMPLE_PATH = Sniffer HTML_HEADER = doclib/doxy-header-overview.html HTML_FOOTER = doclib/doxy-footer.html GENERATE_LATEX = NO diff --git a/Mainpage.dox b/Mainpage.dox index 51f251561ed585a69b87212cd835aea8e5fad3bd..2ded00706362e7ede21c325cbe3b5cb3ccd88508 100644 --- a/Mainpage.dox +++ b/Mainpage.dox @@ -30,6 +30,7 @@ \see \ref usage\n \ref example\n + <a href="xref.html">Current status: Cross reference of action points</a>\n <a class="ext" href="http://developer.berlios.de/projects/senf">The BerliOS project page</a>\n <a class="ext" href="http://openfacts.berlios.de/index-en.phtml?title=SENF+Network+Framework">The SENF Wiki at BerliOS</a> */ diff --git a/Packets/EthernetPacket.cc b/Packets/EthernetPacket.cc index 60c122e04f95a2fdc2188d5865ec0b7c60a86097..4727474ac46e7dec47be9cd4a42290ef6520c26e 100644 --- a/Packets/EthernetPacket.cc +++ b/Packets/EthernetPacket.cc @@ -40,8 +40,8 @@ namespace { prefix_ void senf::EthernetPacket::v_nextInterpreter() const { - // TODO: Add LLC/SNAP support -> only use the registry - // for type() values >=1536, otherwise expect an LLC header + /** \todo Add LLC/SNAP support -> only use the registry + for type() values >=1536, otherwise expect an LLC header */ registerInterpreter(type(),begin()+bytes(),end()); } @@ -85,8 +85,7 @@ prefix_ void senf::EthernetPacket::v_finalize() prefix_ void senf::EthVLanPacket::v_nextInterpreter() const { - // TODO: Add LLC/SNAP support -> only use the registry - // for type() values >=1536, otherwise expect an LLC header + /** \todo Add LLC/SNAP support (see above) */ registerInterpreter(type(),begin()+bytes(),end()); } diff --git a/Packets/GenericPacket.ct b/Packets/GenericPacket.ct index 0a9768c10e16ae2f6647eadb58164973a336effc..bfc4c53d42c9681404c3372ad8f85213edf3398e 100644 --- a/Packets/GenericPacket.ct +++ b/Packets/GenericPacket.ct @@ -44,7 +44,7 @@ template <unsigned HEADER, unsigned TRAILER> prefix_ void senf::GenericPacket<HEADER,TRAILER>::v_dump(std::ostream & os) const { - // TODO: implement v_dump() + /// \todo implement v_dump() } ///////////////////////////////ct.e//////////////////////////////////////// diff --git a/Packets/Packet.cc b/Packets/Packet.cc index ef5752f34c41f98df4d5606598eaca296e8f15f8..828e530f8688ed58e0ec87d550397816e784b5f9 100644 --- a/Packets/Packet.cc +++ b/Packets/Packet.cc @@ -187,8 +187,8 @@ prefix_ senf::Packet::ptr senf::Packet::next() if (n == this->impl_->interpreters_.end()) { if (this->parsed_) return ptr(0); - // FIXME: v_nextInterpreter return bool? new Interpreter to be - // added ? hmm ... this however is quite suboptimal ... + /* \fixme v_nextInterpreter return bool? new Interpreter to be + added ? hmm ... this however is quite suboptimal ... */ this->v_nextInterpreter(); this->parsed_ = true; n = boost::next(this->self_); @@ -270,8 +270,8 @@ prefix_ void senf::Packet::erase(iterator first, iterator last) size_type index(first-impl_->data_.begin()); size_type sz(last-first); BOOST_ASSERT( index >= begin_ && index < end_ && sz <= end_-index ); - // FIXME: Here we should assert, that no bytes belonging to the - // next iterator are deleted ... + /** \fixme Here we should assert, that no bytes belonging to the + next iterator are deleted ... */ impl_->data_.erase(first,last); impl_->updateIterators(index,-sz,self_,INSIDE); } diff --git a/Packets/Packet.cci b/Packets/Packet.cci index 5a299df9dc9d318fdf8e23fe62ed23f350592ece..ea63a0704b692ae0218ee8a9e7603a9028905baa 100644 --- a/Packets/Packet.cci +++ b/Packets/Packet.cci @@ -154,10 +154,10 @@ prefix_ senf::Packet::ptr senf::Packet::head() prefix_ senf::Packet::~Packet() { - // FIXME: This is bad ... we cannot check this since this - // assertion fails at the moment if the Packet constructor throws - // ... hrmpf ... we really need to initialize refcount_ to 0 and - // remove the 'false' argument to the ptr constructor in ::create + /** \fixme This is bad ... we cannot check this since this + assertion fails at the moment if the Packet constructor throws + ... hrmpf ... we really need to initialize refcount_ to 0 and + remove the 'false' argument to the ptr constructor in create */ // BOOST_ASSERT( !this->refcount_ && !this->impl_ ); SATCOM_PKF_REFC_MSG("] Packet::~Packet (" << this << ")\n"); } diff --git a/Packets/Packet.ct b/Packets/Packet.ct index ecb2fde09707e6d4e09e83b8c892e22425596dc2..948698da80bd345919bb2547c2a79991b7ec10a0 100644 --- a/Packets/Packet.ct +++ b/Packets/Packet.ct @@ -56,8 +56,8 @@ template <class OuterPacket> prefix_ typename senf::Packet::ptr_t<OuterPacket>::ptr senf::Packet::create(Packet::ptr payload) { - // TODO: should I instead of using head() throw away all - // interpreters before payload? ... probably yes ... + /** \todo should I instead of using head() throw away all + interpreters before payload? ... probably yes ... */ payload->insert(payload->head()->begin(),min_bytes<OuterPacket>(),0); typename ptr_t<OuterPacket>::ptr p (new OuterPacket(PacketOp_set(payload->impl_))); p->init(); diff --git a/Packets/Packet.cti b/Packets/Packet.cti index 79c32fa711f7a560eb7e3fdf6ab0f951d9faf7e3..163b931789d5bbef747a88e93dca0a137a3013ae 100644 --- a/Packets/Packet.cti +++ b/Packets/Packet.cti @@ -50,9 +50,9 @@ prefix_ senf::Packet::Packet(Operation const & arg) parsed_(false), refcount_(1) { SATCOM_PKF_REFC_MSG("] Packet::Packet (" << this << "): refcount_ = 1\n"); - // FIXME: This is not exception safe, if an exception is thrown in - // the derived class constuctor, the effects of this call must be - // undone which is not possible in a simple way. + /** \fixme This is not exception safe, if an exception is thrown in + the derived class constuctor, the effects of this call must be + undone which is not possible in a simple way. */ arg(this); } diff --git a/Packets/Packet.hh b/Packets/Packet.hh index 2511c8a974da73a1c153acf3a6556987ad744507..bcf5c5ec7d4145a8de7e41fc2d60a725853c8ddb 100644 --- a/Packets/Packet.hh +++ b/Packets/Packet.hh @@ -20,25 +20,25 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// TODO: Implement assign() method akin to reinterpret(). However, -// instead of using the data already present, assign() will replace -// the date of the current packet with the given Packet. +/** \file + \brief Main packet interface -// TODO: Implement wrapping-constructor. Somehow we want to have a -// constructor, which allows creating a chain of packet interpreters -// with as little overhead as possible. + \todo Implement assign() method akin to reinterpret(). However, + instead of using the data already present, assign() will replace + the date of the current packet with the given Packet. -// TODO: Document the additional concrete Packet facade requirements -// explicitly and not only within the Parser requirements (check(), -// bytes() and min_bytes() members ...) + \todo Implement wrapping-constructor. Somehow we want to have a + constructor, which allows creating a chain of packet interpreters + with as little overhead as possible. -// TODO: Implement special container replacing vector which manages -// some headroom to allow efficient insertion of elements at the -// beginning. This really is just another type of deque -// implementation. + \todo Document the additional concrete Packet facade requirements + explicitly and not only within the Parser requirements (check(), + bytes() and min_bytes() members ...) -/** \file - \brief Main packet interface + \todo Implement special container replacing vector which manages + some headroom to allow efficient insertion of elements at the + beginning. This really is just another type of deque + implementation. */ #ifndef HH_Packet_ @@ -76,7 +76,7 @@ namespace senf { counted smart pointer, so resource management is quasi automatic. - \image html "../../structure.png" Overview + \image html structure.png Overview Internally, every Packet references a PacketImpl instance which manages the raw packet data and the interpreter list. This raw @@ -260,6 +260,8 @@ namespace senf { intrusive_ptr is only the size of an ordinary pointer, a smart_ptr has the size of two pointers). + \fixme Make all data mutators protected + \nosubgrouping */ class Packet : boost::noncopyable @@ -395,8 +397,8 @@ namespace senf { OtherPacket. \attention This invalidates the packet instance \e - this</b>. You must ensure, not to use the Packet instance - any further after this call + this. You must ensure, not to use the Packet instance any + further after this call \return smart pointer to a \e new packet facade \throws TruncatedPacketException there is not enough data @@ -439,8 +441,6 @@ namespace senf { // Modifying the raw packet data - // FIXME: Make all data mutators protected - typedef enum { AUTO, BEFORE, INSIDE, OUTSIDE, AFTER } Whence; /** \brief insert single byte \a v before pos diff --git a/Packets/PacketRegistry.hh b/Packets/PacketRegistry.hh index 96370a1b32c7c1dee3ff5e55b04fc0002dc7baf6..49c086e486ce5a7b30cc609da97a241960902432 100644 --- a/Packets/PacketRegistry.hh +++ b/Packets/PacketRegistry.hh @@ -20,7 +20,6 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// TODO: Add parameterless create() method #ifndef HH_PacketRegistryImpl_ #define HH_PacketRegistryImpl_ 1 @@ -79,17 +78,20 @@ namespace senf { constructor during global construction time. The PacketRegistry's purpose is mostly to assist in - implementing the \v v_nextInterpreter() member of packet + implementing the v_nextInterpreter() member of packet facades. This is further supported by the PacketRegistryMixin class. + + \todo Add parameterless create() method */ template <class Tag> class PacketRegistry { public: - // TODO: This fails to work within a library since the linker will - // remove all unused object files ... /** \brief Statically register a packet type in a PacketRegistry + + \fixme This fails to work within a library since the linker will + remove all unused object files ... */ template <class OtherPacket> struct RegistrationProxy diff --git a/Packets/ParseListS.ct b/Packets/ParseListS.ct index 297f2c4a02c1b32e3590968cae9bdcd2eb942b2a..53e3d8a974f2eda560047b049b08ddaac7b0975a 100644 --- a/Packets/ParseListS.ct +++ b/Packets/ParseListS.ct @@ -82,7 +82,7 @@ prefix_ void senf::Parse_ListS_wrapper<Parser,Sentinel,Container>::insert(iterator pos, Value const & t) { - // FIXME: What, if pos == end() / default constructed iterator ? + /** \fixme What, if pos == end() / default constructed iterator ? */ size_type ix (pos.raw()-container_.begin()); container_.insert(pos.raw(),t.bytes(),0); Parser(container_.begin()+ix).value(t); diff --git a/Packets/ParseVec.ct b/Packets/ParseVec.ct index 51ad0be28e767b745c731858cf1c374457d5ed57..b8368abfc5305941487a40da71c0eee588a61ca7 100644 --- a/Packets/ParseVec.ct +++ b/Packets/ParseVec.ct @@ -61,8 +61,9 @@ senf::Parse_Vector_wrapper<Parser,SizeParser,Container>::insert(iterator pos, InputIterator f, InputIterator l) { - // FIXME: This is HORRIBLY inefficient ... we need to specialize - // for random_aPacketRegistry.ess and forward iterators, where we can count the distance + /** \fixme This might be horribly inefficient ... we need to + specialize for random_access and forward iterators, where we + can count the distance */ size_type ix(pos.raw()-container_.begin()); for (;f!=l;++f) { diff --git a/Packets/ParserBase.test.cc b/Packets/ParserBase.test.cc index f0e410a7977abfb560f2d26bcec9c859e2b825e3..916da235ef1f5267ba5f6ec38a41dfc540bba1a6 100644 --- a/Packets/ParserBase.test.cc +++ b/Packets/ParserBase.test.cc @@ -40,7 +40,7 @@ BOOST_AUTO_UNIT_TEST(parserBase_inherited) { - // TODO: Implement + /** \todo Implement */ } namespace { diff --git a/Packets/RTCPPacket.test.cc b/Packets/RTCPPacket.test.cc index 3e168f64f81a0a5f57909adae02841842a8723e9..f5705a4c117d9bf13752b059140e15d713077bcf 100644 --- a/Packets/RTCPPacket.test.cc +++ b/Packets/RTCPPacket.test.cc @@ -69,7 +69,7 @@ BOOST_AUTO_UNIT_TEST(rtcpPacket_parser) BOOST_CHECK_EQUAL(p_1.rr().socount(), 0x0dc8u ); - // TODO RTCP RR + /// \todo RTCP RR unsigned char data_2[] = { 0x82, 0xc8, 0x00, 0x06, 0xe5, 0x70, 0xaa, 0x18, @@ -201,7 +201,7 @@ BOOST_AUTO_UNIT_TEST(rtcpPacket_parser) BOOST_CHECK_EQUAL( j->DLSR(), 0x20212223u ); #endif - // TODO RTCP SDES + /// \todo RTCP SDES unsigned char data_4[] = { 0x81, 0xca, 0x00, 0x04, @@ -225,7 +225,7 @@ BOOST_AUTO_UNIT_TEST(rtcpPacket_parser) #if 0 Parse_RTCP_SDES::Parse_itemList::iterator j_4 (p_4.sdes().chunkVec().begin()); -// TODO -> ask Stefan +/// \todo ask Stefan // BOOST_CHECK_EQUAL( p_4.sdes().chunkList()[0].ssrc(), 0xe570aa18u); // BOOST_CHECK_EQUAL( p_4.sdes().chunkList()[0].itemList().size(), 0x01u); diff --git a/SConstruct b/SConstruct index 3b389040c53f0ea59dabb94f1c91a58c85b21fe0..3d8d8a1a2492a68025dfed983e55b573054fb339 100644 --- a/SConstruct +++ b/SConstruct @@ -13,8 +13,6 @@ env = SENFSCons.MakeEnvironment() env.Append( CPPPATH = [ '#' ], LIBS = [ 'iberty' ], - DOXYFILES = [ '#/doclib/doxy-header.html', '#/doclib/doxy-footer.html', - '#/doclib/Doxyfile.global' ] ) Export('env') @@ -24,5 +22,10 @@ SConscript(glob.glob("*/SConscript")) SENFSCons.StandardTargets(env) SENFSCons.GlobalTargets(env) SENFSCons.Doxygen(env) +SENFSCons.DoxyXRef(env, + TYPES = ('bug','fixme','todo','idea'), + HTML_HEADER = '#/doclib/doxy-header-overview.html', + HTML_FOOTER = '#/doclib/doxy-footer.html') -if not os.path.exists("Doxyfile.local") : Execute(Touch("Doxyfile.local")) +if not env.GetOption('clean') and not os.path.exists("Doxyfile.local"): + Execute(Touch("Doxyfile.local")) diff --git a/Scheduler/ReadHelper.hh b/Scheduler/ReadHelper.hh index 8fb80bf7edeb53d92317e098511a7da4f2163e55..39ea4808fee96120dc7af8dc7e4767566af317c4 100644 --- a/Scheduler/ReadHelper.hh +++ b/Scheduler/ReadHelper.hh @@ -2,7 +2,6 @@ // // Copyright (C) 2006 -// TODO: Move all not Handle dependent members to a ReadHandleBase class #ifndef HH_ReadHelper_ #define HH_ReadHelper_ 1 @@ -22,6 +21,10 @@ namespace senf { + /** \brief + + \todo Move all not Handle dependent members to a ReadHandleBase class + */ template <class Handle> class ReadHelper : public senf::intrusive_refcount diff --git a/Scheduler/Scheduler.cc b/Scheduler/Scheduler.cc index 62a5dfecf55bdb2ac3f8a2ef315786dee5ff4c47..01e33c89b6c2390a63c659af273509ceee02d370 100644 --- a/Scheduler/Scheduler.cc +++ b/Scheduler/Scheduler.cc @@ -20,7 +20,19 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// TODO: Implement signal handling +/** \file + + \idea Implement signal handling (See source for more discussion + about this) + + \idea Multithreading support: To support multithreading, the + static member Scheduler::instance() must return a thread-local + value (that is Scheduler::instance() must allocate one Scheduler + instance per thread) + + \fixme Test2 + */ + // Here a basic concept of how to add signal support to the scheduler: // // Every signal to be reported by the scheduler will be asigned a @@ -57,11 +69,6 @@ // scheduler must be blocked as soon as it is registered with the // scheduler. -// TODO: Multithreading support -// To support multithreading, the static member Scheduler::instance() -// must return a thread-local value (that is Scheduler::instance() -// must allocate one Scheduler instance per thread) - // Definition of non-inline non-template functions #include "Scheduler.hh" diff --git a/Scheduler/Scheduler.hh b/Scheduler/Scheduler.hh index a54bed8444ff949e0702d3bfc05eca6aa3bf8c9f..819d70e78d88cb06a23df47f2bc74366434600ca 100644 --- a/Scheduler/Scheduler.hh +++ b/Scheduler/Scheduler.hh @@ -20,9 +20,6 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// TODO: Fix EventId parameter (probably to int) to allow |-ing without casting ... - - /** \mainpage The SENF Scheduler library */ @@ -52,6 +49,9 @@ namespace senf { descriptiors with this class and pass callback functions to be called on input, output or error. This functions are specified using boost::function objects + + \todo Fix EventId parameter (probably to int) to allow |-ing + without casting ... */ class Scheduler : boost::noncopyable diff --git a/Socket/BSDSocketProtocol.cc b/Socket/BSDSocketProtocol.cc index bb595ac3ce7dac166cd82bd6dc373130bad1a584..d8f5163f8d0cdf2704cd42ebc7c18857887d20da 100644 --- a/Socket/BSDSocketProtocol.cc +++ b/Socket/BSDSocketProtocol.cc @@ -59,8 +59,8 @@ prefix_ void senf::BSDSocketProtocol::linger(bool enable, unsigned timeout) prefix_ struct timeval senf::BSDSocketProtocol::timestamp() const { - // BUG: Check, why this fails with ENOFILE (!!!!) at least when - // called from a tcp socket. Further investigation necessary ... + /** \bug Check, why this fails with ENOFILE (!!!!) at least when + called from a tcp socket. Further investigation necessary ... */ struct timeval tv; if (::ioctl(body().fd(), SIOCGSTAMP, &tv) < 0) throw SystemException(errno); diff --git a/Socket/BufferingPolicy.hh b/Socket/BufferingPolicy.hh index 6eb705c30f535b3ef69ff20e4343dfe649512356..0260dbb4ad2938e3c15cf00b9e49bd4fde2c56bc 100644 --- a/Socket/BufferingPolicy.hh +++ b/Socket/BufferingPolicy.hh @@ -33,7 +33,10 @@ namespace senf { - // TODO: Should this be dependent on Read / WritePolicy ? + /** \brief + + \todo Shouldn't this be dependent on Read / WritePolicy ? + */ struct SocketBufferingPolicy : public BufferingPolicyBase { static unsigned rcvbuf(FileHandle handle); diff --git a/Socket/ClientSocketHandle.ct b/Socket/ClientSocketHandle.ct index acd736b59d5fc0974df7f715e4eaa499b46bb3d1..0c6b61b86a710820e3410dbca00cb5552ee3a88d 100644 --- a/Socket/ClientSocketHandle.ct +++ b/Socket/ClientSocketHandle.ct @@ -43,7 +43,7 @@ prefix_ void senf::ClientSocketHandle<Policy>::read(std::string & buffer, unsign unsigned nread = available(); if (limit>0 && nread>limit) nread = limit; - // FIXME: This is not necessary correct and more or less a hack ... + /** \fixme This is not necessary correct and more or less a hack ... */ buffer.assign(nread,0); unsigned rv = this->read(const_cast<char *>(buffer.data()),nread); if (rv < nread) @@ -65,7 +65,7 @@ prefix_ void senf::ClientSocketHandle<Policy>:: readfrom(std::string & buffer, typename Policy::AddressingPolicy::Address & from) { unsigned nread = available(); - // FIXME: This is not necessary correct and more or less a hack ... + /** \fixme This is not necessary correct and more or less a hack ... */ buffer.assign(nread,0); unsigned rv = this->readfrom(const_cast<char *>(buffer.data()), nread, from); if (rv < nread) diff --git a/Socket/ClientSocketHandle.hh b/Socket/ClientSocketHandle.hh index a4280e89589dc1996fabdf54862b8ed873de4699..1a120b763f0e1deadc5cbc850dd7dd050be8159d 100644 --- a/Socket/ClientSocketHandle.hh +++ b/Socket/ClientSocketHandle.hh @@ -20,9 +20,6 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// TODO: Move all not template-parameter dependent code into a -// non-template base class - #ifndef HH_ClientSocketHandle_ #define HH_ClientSocketHandle_ 1 @@ -39,6 +36,9 @@ namespace senf { template <class Policy> class ServerSocketHandle; /** \brief + + \todo Move all not template-parameter dependent code into a + non-template base class */ template <class Policy> class ClientSocketHandle diff --git a/Socket/FileHandle.hh b/Socket/FileHandle.hh index d11f2eea4df56210db82624ec6479eb0df7b941b..9a8c7e7d5b7d015353e74589b9f57094729cc40b 100644 --- a/Socket/FileHandle.hh +++ b/Socket/FileHandle.hh @@ -34,7 +34,37 @@ namespace senf { - /** \brief + /** \brief Basic file handle wrapper + + senf::FileHandle provides a simple wrapper for arbitrary file handles. It exposes only a + minimal interface which does \e not include reading or writing (since some filehandles are + not readable or writable or only using special function calls like sendto). + + The FileHandle class provides handle/body handling and uses automatic reference + counting. The senf::FileHandle istance is very lightweight and should be used like a + built-in type. + + \attention You should mostly pass around senf::FileHandle objects by \e value und not by + reference. + + The FileHandle abstraction is only applicable to real filehandles. It is \e not possible to + wrap any provider or consumer into a filehandle like interface using this wrapper. The + wrapper will forward some calls directly to the underlying API without relying on virtual + methods. This allows important members to be inlined. + + It is not possible to use the senf::FileHandle class directly since it does not have any + public constructor. The FileHandle class is however the baseclass of all handle classes of + the socket library. + + \section filehandle_new Writing senf::FileHandle derived classes + + To build a new FileHandle type you need to derive from senf::FileHandle. The derived class + will have to call the protocted FileHandle constructor passing a new senf::FileBody + instance. This instance may either be a simple senf::FileBody or a class derived from + senf::FileBody. + + \todo Add public default constructor to allow declaration of (empty) senf::FileHandle + variables. */ class FileHandle : public SafeBool<FileHandle> @@ -56,37 +86,54 @@ namespace senf { ///@} /////////////////////////////////////////////////////////////////////////// - - void close(); - void terminate(); - bool readable() const; - void waitReadable() const; - bool writeable() const; - void waitWriteable() const; + void close(); ///< Close filehandle + /**< \throws senf::SystemException */ + void terminate(); ///< Close filehandle ignoring error conditions - bool blocking() const; - void blocking(bool status); + bool readable() const; ///< Check, wether a read on the handle would not block + ///< (ignoring blocking state) + void waitReadable() const; ///< Wait, until read on the handle would not block (ignoring + ///< blocking state) + bool writeable() const; ///< Check, wether a write on the handle would not block + ///< (ignoring blocking state) + void waitWriteable() const; ///< Wait, until a write on the handle would not block + ///< (ignoring blocking state) - bool eof() const; - bool valid() const; + bool blocking() const; ///< Return current blocking state + void blocking(bool status); ///< Set blocking state - bool boolean_test() const; + bool eof() const; ///< Check EOF condition + /**< Depending on the socket type, this might never return \p + true */ + bool valid() const; ///< Check filehandle validity + /**< Any operation besides valid() will fail on an invalid + FileHandle */ - int fd() const; + bool boolean_test() const; ///< Short for valid() && ! eof() + /**< This is called when using a FileHandle instance in a boolen + context */ - static FileHandle cast_static(FileHandle handle); - static FileHandle cast_dynamic(FileHandle handle); + int fd() const; ///< Return the raw FileHandle + + static FileHandle cast_static(FileHandle handle); ///< \internal + static FileHandle cast_dynamic(FileHandle handle); ///< \internal protected: explicit FileHandle(std::auto_ptr<FileBody> body); + ///< create new FileHandle instance + /**< The FileHandle instance will take over ownership over the + given FileBody instance which must have been allocated using + \c new. To configure the FileHandle behavior, A derived class + may provide any class derived from FileBody here. */ - FileBody & body(); - FileBody const & body() const; - static FileBody & body(FileHandle & handle); - static FileBody const & body(FileHandle const & handle); + FileBody & body(); ///< Access body + FileBody const & body() const; ///< Access body in const context + static FileBody & body(FileHandle & handle); ///< Access body of another FileHandle instance + static FileBody const & body(FileHandle const & handle); ///< Access body of another + ///< FileHandle instance in const context - void fd(int fd); + void fd(int fd); ///< Set raw filehandle private: FileBody::ptr body_; @@ -106,4 +153,5 @@ namespace senf { // Local Variables: // mode: c++ // c-file-style: "senf" +// fill-column: 100 // End: diff --git a/Socket/INetAddressing.cc b/Socket/INetAddressing.cc index 404f865123b6dff9d03b96747604ba461e4dc060..3081cc59e34256f22c4206a98e991321409f9f39 100644 --- a/Socket/INetAddressing.cc +++ b/Socket/INetAddressing.cc @@ -38,7 +38,7 @@ prefix_ senf::INet4Address::INet4Address(std::string host, unsigned port) { clear(); - // TODO: gethostbyname einbauen + /** \todo gethostbyname support */ if (::inet_aton(host.c_str(), &addr_.sin_addr) == 0) throw InvalidINetAddressException(); addr_.sin_port = htons(port); @@ -61,7 +61,7 @@ prefix_ void senf::INet4Address::clear() prefix_ void senf::INet4Address::assignString(std::string address) { clear(); - // TODO: gethostbyname einbauen + /** \todo gethostbyname support */ unsigned i = address.find(':'); if (i == std::string::npos) throw InvalidINetAddressException(); diff --git a/Socket/INetAddressing.cci b/Socket/INetAddressing.cci index 7089881c55fbd0d9bf31b3eda39cb3f4c01c8bf8..81ac9f1fc356b43b4651dc1d32847437d0160253 100644 --- a/Socket/INetAddressing.cci +++ b/Socket/INetAddressing.cci @@ -53,7 +53,7 @@ prefix_ bool senf::INet4Address::operator==(INet4Address const & other) prefix_ std::string senf::INet4Address::host() const { - // FIXME: thread safety? + /** \fixme thread safety? */ return std::string(::inet_ntoa(addr_.sin_addr)); } diff --git a/Socket/INetAddressing.hh b/Socket/INetAddressing.hh index 60a71a22f2d9da57f17e7b0b733ce7566027fb94..9b8b160aaae7f1d067a2d6ee63ac7e36ac80adac 100644 --- a/Socket/INetAddressing.hh +++ b/Socket/INetAddressing.hh @@ -38,9 +38,13 @@ namespace senf { - // TODO: Implement real INet4Address datatype and - // rename this one to INet4SockAddress ... + /** \brief + + \todo Implement real INet4Address datatype and + rename this one to INet4SockAddress ... + \todo Implement more complete interface + */ class INet4Address { public: @@ -55,8 +59,6 @@ namespace senf { std::string host() const; unsigned port() const; - // TODO: Interface - void clear(); struct sockaddr * sockaddr_p(); @@ -71,9 +73,12 @@ namespace senf { std::ostream & operator<<(std::ostream & os, INet4Address const & addr); + /** \brief + + \todo Implement + */ class INet6Address { - // TODO: Implement }; struct INet4AddressingPolicy @@ -88,11 +93,13 @@ namespace senf { using GenericAddressingPolicy<INet4Address>::bind; }; + /** \brief + + \todo Implement + */ struct INet6AddressingPolicy : public AddressingPolicyBase { typedef INet6Address Address; - - // TODO: Implement }; struct InvalidINetAddressException : public std::exception diff --git a/Socket/INetProtocol.hh b/Socket/INetProtocol.hh index 5c6bc7afab795a49cd8f4aff932b4cf8450c2a40..79a514c55669e00bbabc02c74df86abdbfc2bc54 100644 --- a/Socket/INetProtocol.hh +++ b/Socket/INetProtocol.hh @@ -20,11 +20,14 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// TODO: what about OOB data? das OOB Data block receipt of normal data ? +/** \file -// TODO: Implement IP_RECVERR / MSG_ERRQUEUE. This should be placed -// into an additional protocol class since IP_RECVERR is only valid -// for SOCK_DGRAM (UDP) and not SOCK_STREAM (TCP) sockets + \todo what about OOB data? + + \todo Implement IP_RECVERR / MSG_ERRQUEUE. This should be placed + into an additional protocol class since IP_RECVERR is only valid + for SOCK_DGRAM (UDP) and not SOCK_STREAM (TCP) sockets + */ #ifndef HH_INetProtocol_ #define HH_INetProtocol_ 1 @@ -41,6 +44,15 @@ namespace senf { + /** \brief + + \todo Is it safe, not to allow setting the interface index on + add/drop? what does it do (especially if the local addres is + given ?). What have I been thinking here ??? + + \todo move all multicast-methods into an extra + IPv4MulticastProtocol class + */ class IPv4Protocol : public virtual SocketProtocol { @@ -54,13 +66,6 @@ namespace senf { bool mcLoop() const; void mcLoop(bool value) const; - // TODO: Is it safe, not to allow setting the interface - // index on add/drop? what does it do (especially if - // the local addres is given ?) - - // TODO: move all multicast-methods into an extra - // IPv4MulticastProtocol class - void mcAddMembership(INet4Address const & mcAddr) const; void mcAddMembership(INet4Address const & mcAddr, INet4Address const & localAddr) const; diff --git a/Socket/LLAddressing.cci b/Socket/LLAddressing.cci index f7dfdf997bc45135874857175580e80dd574775d..228b474b7b9af12df421c486dee05745ada30646 100644 --- a/Socket/LLAddressing.cci +++ b/Socket/LLAddressing.cci @@ -62,16 +62,16 @@ prefix_ unsigned senf::LLSocketAddress::protocol() prefix_ unsigned senf::LLSocketAddress::arptype() const { - // TODO: Check, wether this is returned in network or host byte - // order + /** \todo make sure, that the value really is in network byte + order */ return ntohs(addr_.sll_hatype); } prefix_ unsigned senf::LLSocketAddress::pkttype() const { - // TODO: Check, wether this is returned in network or host byte - // order + /** \todo make sure, that the value really is in network byte + order */ return ntohs(addr_.sll_pkttype); } diff --git a/Socket/Mainpage.dox b/Socket/Mainpage.dox index 30e9f0793179fa709789d77e5309923f0aad1375..2721d3696778685f2e6d12b66b802baf87efeabb 100644 --- a/Socket/Mainpage.dox +++ b/Socket/Mainpage.dox @@ -218,7 +218,7 @@ information on how to implement that policy. <table class="senf"> - <tr><th>SocketHandle member</th><th>Policy member</th></tr> + <tr><th>SocketHandle member</th> <th>Policy member</th></tr> <tr><td>senf::ClientSocketHandle::read</td> <td>ReadPolicy::read (\ref senf::ReadPolicyBase)</td></tr> <tr><td>senf::ClientSocketHandle::readfrom</td> <td>ReadPolicy::readfrom (\ref senf::ReadPolicyBase)</td></tr> <tr><td>senf::ClientSocketHandle::write</td> <td>WritePolicy::write (\ref senf::WritePolicyBase)</td></tr> diff --git a/Socket/PacketSocketHandle.cc b/Socket/PacketSocketHandle.cc index 59bbab0da36a3897120cf08b27d099fcafe21790..b995959a12026e6942ab130e9f4c74ff8b82e44f 100644 --- a/Socket/PacketSocketHandle.cc +++ b/Socket/PacketSocketHandle.cc @@ -78,6 +78,8 @@ prefix_ bool senf::PacketProtocol::eof() prefix_ void senf::PacketProtocol::promisc(std::string interface, PromiscMode mode) const { + /** \bug There are some failures here ... need to investigate */ + // The interface is really stupid: as far as i understand, it is possible to // enable PROMISC and ALLMULTI seperately, however PROMISC is really a superset // of ALLMULTI ... grmpf ... therefore we allways set/reset both to implement sane diff --git a/Socket/PacketSocketHandle.test.cc b/Socket/PacketSocketHandle.test.cc index 4e8ca91bd1724484d417e8bce81557f678a7d637..61d47a17e9524161289dd128fd0d9511c2725020 100644 --- a/Socket/PacketSocketHandle.test.cc +++ b/Socket/PacketSocketHandle.test.cc @@ -55,8 +55,7 @@ BOOST_AUTO_UNIT_TEST(packetSocketHandle) // How am I supposed to test read and write .. grmpf .. - // BUG: There are some failures here ... need to investigate - /* + /* BOOST_CHECK_NO_THROW( sock.protocol().promisc( "lo",senf::PacketProtocol::Promiscuous) ); BOOST_CHECK_NO_THROW( sock.protocol().promisc( diff --git a/Socket/ReadWritePolicy.hh b/Socket/ReadWritePolicy.hh index e5203aeaf6827f486af329d23cd057028b300642..644ad879297f9cf0e036bfe1f563fc5481cc31f2 100644 --- a/Socket/ReadWritePolicy.hh +++ b/Socket/ReadWritePolicy.hh @@ -20,6 +20,11 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +/** \file + + \todo ReadWritePolicy.test.cc + */ + #ifndef HH_ReadWritePolicy_ #define HH_ReadWritePolicy_ 1 @@ -31,7 +36,6 @@ //#include "ReadWritePolicy.mpp" ///////////////////////////////hh.p//////////////////////////////////////// -// TODO: ReadWritePolicy.test.cc ... struct sockaddr; diff --git a/Socket/SocketHandle.cc b/Socket/SocketHandle.cc index 1400d35d7fbbaa5ac92b3abad5db8990e7154d28..3f8a0ce87b1baf9a66f12a2da7e4e813aca59db8 100644 --- a/Socket/SocketHandle.cc +++ b/Socket/SocketHandle.cc @@ -99,14 +99,14 @@ prefix_ bool senf::detail::StateMapOrdering::operator()(std::string a1, std::str return false; if (contains(i2,i2_end,'.')) // the longer string is a sub-'directory' of the shorter - // FIXME: shouldn't this be *i2 == '.' ? + /** \fixme shouldn't this be *i2 == '.' ? */ return true; return *i1 < *i2; } else if (i2 == i2_end) { // && i1 != i1_end if (contains(i1,i1_end,'.')) // the longer string is a sub-'directory' of the shorter - // FIXME: shouldn't this be *i1 == '.' ? + /** \fixme shouldn't this be *i1 == '.' ? */ return false; return *i1 < *i2; } diff --git a/Socket/SocketHandle.hh b/Socket/SocketHandle.hh index 9c1fd1c4dbad4051b525ba0b53da55c96e03bfab..7304ff1f5bd7fb74b7988fef08e3a1ba8b1435a9 100644 --- a/Socket/SocketHandle.hh +++ b/Socket/SocketHandle.hh @@ -20,10 +20,6 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// TODO: Create a SocketHandleBase class and move some non-Policy -// dependent code there - - #ifndef HH_SocketHandle_ #define HH_SocketHandle_ 1 @@ -41,7 +37,10 @@ namespace senf { /** \brief - */ + + \todo Create a SocketHandleBase class and move some non-Policy + dependent code there + */ template <class SocketPolicy> class SocketHandle : public FileHandle diff --git a/Socket/SocketProtocol.hh b/Socket/SocketProtocol.hh index 008716ed3c0efe5afebd4fc0a68c2d6fcd0c8ec3..fe42ee805093ec3caff9d5fb6428f6f2af6ccb17 100644 --- a/Socket/SocketProtocol.hh +++ b/Socket/SocketProtocol.hh @@ -25,7 +25,7 @@ // Custom includes #include <boost/utility.hpp> -// FIXME: this is really bad. The includes and predefs should be restructured +/** \fixme this is not nice. The includes and predefs should be restructured */ #include "SocketHandle.ih" //#include "SocketProtocol.mpp" diff --git a/Socket/TCPSocketHandle.hh b/Socket/TCPSocketHandle.hh index 01819813bb3820bd0d957d212e3d98cd73487d6d..b8354ca41826aaf8ce0b75feb4dc016ac5df9bba 100644 --- a/Socket/TCPSocketHandle.hh +++ b/Socket/TCPSocketHandle.hh @@ -20,8 +20,11 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// TODO: Implement possibly non-blocking connect and SO_ERROR in the -// protocol interface +/** \file + + \todo Implement possibly non-blocking connect and SO_ERROR in the + protocol interface + */ #ifndef HH_TCPSocketHandle_ #define HH_TCPSocketHandle_ 1 @@ -86,7 +89,7 @@ namespace senf { public BSDSocketProtocol, public AddressableBSDSocketProtocol { - // TODO: Implement + /** \todo Implement */ }; typedef ProtocolClientSocketHandle<TCPv6SocketProtocol> TCPv6ClientSocketHandle; diff --git a/doclib/Doxyfile.global b/doclib/Doxyfile.global index 31a0c0f21b455ba2f352fef1f3369b4f3878caa9..5b9b918cb3b89c7375212b72b5d2cff2aae67426 100644 --- a/doclib/Doxyfile.global +++ b/doclib/Doxyfile.global @@ -3,10 +3,11 @@ INPUT = . FILE_PATTERNS = *.c *.cc *.cci *.ct *.cti *.h *.hh *.ih *.mmc *.dox EXCLUDE_PATTERNS = *.test.cc .* IMAGE_PATH = . -HTML_HEADER = ../doclib/doxy-header.html -HTML_FOOTER = ../doclib/doxy-footer.html -REPEAT_BRIEF = NO +ALIASES = "fixme=\xrefitem fixme \"Fixme\" \"Fixmes\"" \ + "idea=\xrefitem idea \"Idea\" \"Ideas\"" +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = YES MULTILINE_CPP_IS_BRIEF = YES DETAILS_AT_TOP = YES BUILTIN_STL_SUPPORT = YES @@ -15,16 +16,21 @@ EXTRACT_PRIVATE = YES EXTRACT_STATIC = YES INTERNAL_DOCS = YES SOURCE_BROWSER = YES +STRIP_CODE_COMMENTS = NO ALPHABETICAL_INDEX = YES COLS_IN_ALPHA_INDEX = 3 -GENERATE_LATEX = NO -GENERATE_MAN = NO MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES PREDEFINED = DOXYGEN EXPAND_AS_DEFINED = prefix_ +HTML_HEADER = ../doclib/doxy-header.html +HTML_FOOTER = ../doclib/doxy-footer.html +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_XML = YES + HAVE_DOT = YES CLASS_GRAPH = YES COLLABORATION_GRAPH = YES diff --git a/doclib/senf.css b/doclib/senf.css index 8a72a5712309f4cff9c7324fb697f2fe19d9bba8..19e5b111f7d56b50d1d6ce97ebae543e3d728172 100644 --- a/doclib/senf.css +++ b/doclib/senf.css @@ -186,3 +186,32 @@ table.senf th { text-align: center; font-weight: bold; } + +dl.bug { + border: 1px solid #EE0000; + border-left-width: 4px; + background-color: #FFDDDD; + padding: 0 10px; +} + +dl.fixme { + border: 1px solid #EEEE00; + border-left-width: 4px; + background-color: #FFFFDD; + padding: 0 10px; +} + +dl.todo { + border: 1px solid #00AA00; + border-left-width: 4px; + background-color: #DDFFDD; + padding: 0 10px; +} + +dl.idea { + border: 1px solid #AAAAAA; + border-left-width: 4px; + background-color: #EEEEEE; + padding: 0 10px; +} + diff --git a/senfscons/Doxygen.py b/senfscons/Doxygen.py index f379f91effd8164468080ed563895acd6fdcb5af..705e22a44cfe0d43471781bea714076f99154c8c 100644 --- a/senfscons/Doxygen.py +++ b/senfscons/Doxygen.py @@ -40,7 +40,7 @@ def DoxyfileParse_(file, data): lex = shlex.shlex(instream=open(file), posix=True) lex.wordchars += "*+./-:@~" lex.whitespace = lex.whitespace.replace("\n", "") - lex.escape = "" + lex.escape = "\\" lineno = lex.lineno token = lex.get_token() @@ -161,7 +161,13 @@ def DoxyEmitter(source, target, env): data = DoxyfileParse(source[0].abspath) targets = [] - out_dir = data.get("OUTPUT_DIRECTORY", ".") + if data.has_key("OUTPUT_DIRECTORY"): + out_dir = data["OUTPUT_DIRECTORY"] + dir = env.Dir( os.path.join(source[0].dir.abspath, out_dir) ) + dir.sources = source + targets.append(dir) + else: + out_dir = '.' # add our output locations for (k, v) in output_formats.iteritems(): @@ -169,13 +175,16 @@ def DoxyEmitter(source, target, env): # Grmpf ... need to use a File object here. The problem is, that # Dir.scan() is implemented to just return the directory entries # and does *not* invoke the source-file scanners .. ARGH !! - dir = env.Dir( os.path.join(str(source[0].dir), out_dir, data.get(k + "_OUTPUT", v[1])) ) - node = env.File( os.path.join(str(dir), ".stamp" ) ) - env.Clean(node, dir) - targets.append( node ) + dir = env.Dir( os.path.join(source[0].dir.abspath, out_dir, data.get(k + "_OUTPUT", v[1])) ) + # This is needed to silence the (wrong) 'Multiple ways to + # build the same target' message + dir.sources = source + node = env.File( os.path.join(dir.abspath, ".stamp" ) ) + targets.append(node) + targets.append(dir) if data.has_key("GENERATE_TAGFILE"): - targets.append(env.File( os.path.join(str(source[0].dir), data["GENERATE_TAGFILE"]) )) + targets.append(env.File( os.path.join(source[0].dir.abspath, data["GENERATE_TAGFILE"]) )) # don't clobber targets for node in targets: diff --git a/senfscons/SENFSCons.py b/senfscons/SENFSCons.py index 7308c0e75c370099910db6540cc30d5811022c4f..34604142a6037a239f66e33daced5c1f3329f2e4 100644 --- a/senfscons/SENFSCons.py +++ b/senfscons/SENFSCons.py @@ -1,4 +1,5 @@ -import os.path, SCons.Options, SCons.Environment, SCons.Script.SConscript, glob +import os.path, glob +import SCons.Options, SCons.Environment, SCons.Script.SConscript, SCons.Node.FS, SCons.Defaults SCONS_TOOLS = [ "Doxygen", @@ -117,12 +118,7 @@ def StandardTargets(env): env.Depends(all, '.') def GlobalTargets(env): - command = "find -name .svn -prune -o \( -name '*.hh' -o -name '*.ih' -o -name '*.cc' -o -name '*.cci' -o -name '*.ct' -o -name '*.cti' -o -name '*.mpp' \) -print " \ - "| xargs -r awk -F '//' '/%s/{print ARGV[ARGIND] \":\" FNR \":\" $2}' > $TARGET" - env.AlwaysBuild(env.Command('TODOS',None,[ command % 'TODO' ])) - env.AlwaysBuild(env.Command('FIXMES',None,[ command % ' FIXME' ])) - env.AlwaysBuild(env.Command('BUGS',None,[ command % 'BUG' ] )) - env.Alias('status',[ 'TODOS', 'FIXMES', 'BUGS' ]) + pass def LibPath(lib): return '$LOCALLIBDIR/lib%s.a' % lib @@ -152,20 +148,88 @@ def Objects(env, sources, testSources = None, LIBS = []): def Doxygen(env, doxyfile = "Doxyfile", extra_sources = []): docs = env.Doxygen(doxyfile) - # The last target is the (optional) tagfile - if os.path.basename(str(docs[-1])) != '.stamp': + for doc in docs: + if isinstance(doc,SCons.Node.FS.Dir): continue + if os.path.basename(str(doc)) == '.stamp' : continue # file stamp + # otherwise it must be the tag file + break + else: + doc = None + if doc: # Postprocess the tag file to remove the (broken) namespace # references env.AddPostAction( - docs, - env.Action([ "xsltproc -o ${TARGETS[-1]}.temp %s ${TARGETS[-1]}" + doc, + env.Action([ "xsltproc -o TARGET.temp %s TARGET" % os.path.join(basedir,"tagmunge.xsl"), - "mv ${TARGETS[-1]}.temp ${TARGETS[-1]}" ])) - env.Clean(docs[-1],"$TARGET.temp") + "mv TARGET.temp TARGET" ])) + env.Clean(doc,"$TARGET.temp") env.Depends(docs,extra_sources) - env.Alias('all_docs', *docs) + for doc in docs : + env.Alias('all_docs', doc) + env.Clean('all_docs', doc) + env.Clean('all', doc) return docs +def DoxyXRef(env, + TYPES = ('bug','todo'), + HTML_HEADER = None, HTML_FOOTER = None, + TITLE = "Cross-reference of action points"): + # Hmm .. this looks a bit scary :-) ... + xrefis = [] + + # This iterates over all doc targets. These are all .stamp and .tag files + for node in env.Alias('all_docs')[0].sources: + # We are only interested in the xml targets. This is Doxyfile dependent :-( + if node.abspath.endswith('/xml/.stamp'): + # This is the list of xref categories + for type in TYPES: + # Here we construct the pathname of the xml file for the category + xref = os.path.join(node.dir.abspath,type+'.xml') + # And now apply the xrefxtract.xslt tempalte to it. However, we must + # only call xsltproc if the source xml file is not empty (therefore the + # 'test') + xrefi = env.Command(xref+'i', [ xref, '%s/xrefxtract.xslt' % basedir, node ], + [ "test -s $SOURCE && xsltproc -o $TARGET" + + " --stringparam module $MODULE" + + " --stringparam type $TYPE" + + " ${SOURCES[1]} $SOURCE || touch $TARGET" ], + MODULE = node.dir.dir.dir.name, + TYPE = type) + # If the xref xml file does not exist we create it here as an empty + # file since doxygen will only create it if it is non-empty. + if not env.GetOption('clean') and not os.path.exists(xref): + if not os.path.exists(node.dir.abspath): + env.Execute(SCons.Defaults.Mkdir(node.dir.abspath)) + env.Execute(SCons.Defaults.Touch(xref)) + xrefis.append(xrefi) + + # And here we can now simply combine all the xrefi files + xref = env.Command("doc/html/xref.xml", xrefis, + [ "echo -e '<?xml version=\"1.0\"?>\\n<xref>' >$TARGET", + "cat $SOURCES >> $TARGET", + "echo '</xref>' >>$TARGET" ]) + + # Lastly we create the html file + sources = [ xref, "%s/xrefhtml.xslt" % basedir ] + if HTML_HEADER : sources.append(HTML_HEADER) + if HTML_FOOTER : sources.append(HTML_FOOTER) + + commands = [] + if HTML_HEADER: + commands.append( + "sed -e 's/\\$$title/$TITLE/g' -e 's/\\$$projectname/Overview/g' ${SOURCES[2]} > $TARGET") + commands.append("xsltproc --stringparam title '$TITLE' ${SOURCES[1]} $SOURCE >> $TARGET") + if HTML_FOOTER: + commands.append( + "sed -e 's/\\$$title/$TITLE/g' -e 's/\\$$projectname/Overview/g' ${SOURCES[%d]} >> $TARGET" + % (HTML_HEADER and 3 or 2)) + + xref = env.Command("doc/html/xref.html", sources, commands) + + env.Alias('all_docs',xref) + return xref + def Lib(env, library, sources, testSources = None, LIBS = []): objects = Objects(env,sources,testSources,LIBS=LIBS) lib = None diff --git a/senfscons/functions.xsl b/senfscons/functions.xsl new file mode 100644 index 0000000000000000000000000000000000000000..f8e22f48e06bdbf050c341f359c4ecf02354d7ca --- /dev/null +++ b/senfscons/functions.xsl @@ -0,0 +1,114 @@ +<?xml version="1.0"?> +<xsl:stylesheet + version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:str="http://exslt.org/strings" + xmlns:func="http://exslt.org/functions" + xmlns:exsl="http://exslt.org/common" + extension-element-prefixes="str exsl func"> + + <!-- ==================================================================== --> + <!-- node-set str:replace(string,object,object) --> + <!-- --> + <!-- This implements the EXSLT str:replace function --> + <!-- --> + <!-- Copyright Jeni Tenison --> + <!-- ==================================================================== --> + + <func:function name="str:replace"> + <xsl:param name="string" select="''" /> + <xsl:param name="search" select="/.." /> + <xsl:param name="replace" select="/.." /> + <xsl:choose> + <xsl:when test="not($string)"> + <func:result select="/.." /> + </xsl:when> + <xsl:when test="function-available('exsl:node-set')"> + <!-- this converts the search and replace arguments to node sets + if they are one of the other XPath types --> + <xsl:variable name="search-nodes-rtf"> + <xsl:copy-of select="$search" /> + </xsl:variable> + <xsl:variable name="replace-nodes-rtf"> + <xsl:copy-of select="$replace" /> + </xsl:variable> + <xsl:variable name="replacements-rtf"> + <xsl:for-each select="exsl:node-set($search-nodes-rtf)/node()"> + <xsl:variable name="pos" select="position()" /> + <replace search="{.}"> + <xsl:copy-of select="exsl:node-set($replace-nodes-rtf)/node()[$pos]" /> + </replace> + </xsl:for-each> + </xsl:variable> + <xsl:variable name="sorted-replacements-rtf"> + <xsl:for-each select="exsl:node-set($replacements-rtf)/replace"> + <xsl:sort select="string-length(@search)" data-type="number" order="descending" /> + <xsl:copy-of select="." /> + </xsl:for-each> + </xsl:variable> + <xsl:variable name="result"> + <xsl:choose> + <xsl:when test="not($search)"> + <xsl:value-of select="$string" /> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="str:_replace"> + <xsl:with-param name="string" select="$string" /> + <xsl:with-param name="replacements" select="exsl:node-set($sorted-replacements-rtf)/replace" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <func:result select="exsl:node-set($result)/node()" /> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + ERROR: function implementation of str:replace() relies on exsl:node-set(). + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </func:function> + + <xsl:template name="str:_replace"> + <xsl:param name="string" select="''" /> + <xsl:param name="replacements" select="/.." /> + <xsl:choose> + <xsl:when test="not($string)" /> + <xsl:when test="not($replacements)"> + <xsl:value-of select="$string" /> + </xsl:when> + <xsl:otherwise> + <xsl:variable name="replacement" select="$replacements[1]" /> + <xsl:variable name="search" select="$replacement/@search" /> + <xsl:choose> + <xsl:when test="not(string($search))"> + <xsl:value-of select="substring($string, 1, 1)" /> + <xsl:copy-of select="$replacement/node()" /> + <xsl:call-template name="str:_replace"> + <xsl:with-param name="string" select="substring($string, 2)" /> + <xsl:with-param name="replacements" select="$replacements" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="contains($string, $search)"> + <xsl:call-template name="str:_replace"> + <xsl:with-param name="string" select="substring-before($string, $search)" /> + <xsl:with-param name="replacements" select="$replacements[position() > 1]" /> + </xsl:call-template> + <xsl:copy-of select="$replacement/node()" /> + <xsl:call-template name="str:_replace"> + <xsl:with-param name="string" select="substring-after($string, $search)" /> + <xsl:with-param name="replacements" select="$replacements" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="str:_replace"> + <xsl:with-param name="string" select="$string" /> + <xsl:with-param name="replacements" select="$replacements[position() > 1]" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + +</xsl:stylesheet> \ No newline at end of file diff --git a/senfscons/xrefhtml.xslt b/senfscons/xrefhtml.xslt new file mode 100644 index 0000000000000000000000000000000000000000..3d4dcbccc0758b5cbc5a945653639f19480a08cb --- /dev/null +++ b/senfscons/xrefhtml.xslt @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<xsl:stylesheet + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:fn="http://senf.berlios.de/xml/Extensions" + xmlns:exsl="http://exslt.org/common" + xmlns:str="http://exslt.org/strings" + extension-element-prefixes="str fn exsl" + version="1.0"> + + <xsl:include href="functions.xsl"/> + + <xsl:output method="html"/> + <xsl:strip-space elements="*"/> + <xsl:param name="title" select="''"/> + + <xsl:template match="/"> + <h1><xsl:value-of select="$title"/></h1> + <xsl:apply-templates/> + </xsl:template> + + <xsl:template match="xreflist"> + <xsl:if test="string(preceding::xreflist[1]/@module)!=string(@module)"> + <xsl:if test="preceding::xreflist"> + <hr/> + </xsl:if> + <h2>The <xsl:element name="a"> + <xsl:attribute name="href">../../<xsl:value-of select="@module"/>/doc/html/index.html</xsl:attribute> + <xsl:value-of select="@module"/> + </xsl:element> module</h2> + </xsl:if> + <xsl:element name="dl"> + <xsl:attribute name="class"><xsl:value-of select="@type"/></xsl:attribute> + <dt><h3><xsl:value-of select="translate(@type,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/> items</h3></dt> + <xsl:apply-templates/> + </xsl:element> + </xsl:template> + + <fn:nsquote> + <fn:replacement> + <fn:match>_1_1</fn:match> + <fn:replace>_2</fn:replace> + </fn:replacement> + </fn:nsquote> + + <xsl:variable name="nsquote" select="document('')//fn:nsquote/fn:replacement"/> + + <xsl:template match="compound"> + <!-- Yuck ... I HATE this .. why doesn't xsltproc support XPath 2.0 ... grmpf --> + <xsl:variable name="quoted"> + <xsl:apply-templates select="str:replace(@id,$nsquote/fn:match,$nsquote/fn:replace)"/> + </xsl:variable> + <xsl:variable name="anchor" select="substring-after($quoted,'_1')"/> + <xsl:variable name="file"> + <xsl:apply-templates select="str:replace(substring($quoted,1,string-length($quoted) - number(boolean($anchor))*2 - string-length($anchor)),$nsquote/fn:replace,$nsquote/fn:match)"/> + </xsl:variable> + <xsl:variable name="sep" select="substring('#',2-number(boolean($anchor)))"/> + <dt> + <xsl:element name="a"> + <xsl:attribute name="href">../../<xsl:value-of select="ancestor::xreflist/@module"/>/doc/html/<xsl:value-of select="$file"/>.html<xsl:value-of select="$sep"/><xsl:value-of select="$anchor"/></xsl:attribute> + <b><xsl:value-of select="@name"/></b> + </xsl:element> + </dt> + <dd> + <xsl:apply-templates/> + </dd> + </xsl:template> + + <xsl:template match="item"> + <p><xsl:apply-templates/></p> + </xsl:template> + +</xsl:stylesheet> diff --git a/senfscons/xrefxtract.xslt b/senfscons/xrefxtract.xslt new file mode 100644 index 0000000000000000000000000000000000000000..e09ff4fc5a0930eac92544bd1d836e05c49e6ca7 --- /dev/null +++ b/senfscons/xrefxtract.xslt @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="utf-8"?> +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + version="1.0"> + + <xsl:output method="xml" omit-xml-declaration="yes"/> + <xsl:param name="module" select="''"/> + <xsl:param name="type" select="'todo'"/> + <xsl:strip-space elements="*"/> + + <xsl:template match="variablelist"> + <xsl:if test="string(preceding::variablelist[1]/varlistentry/term/ref/@refid)!=string(varlistentry/term/ref/@refid)"> + <xsl:element name="compound"> + <xsl:attribute name="id"> + <xsl:value-of select="varlistentry/term/ref/@refid"/> + </xsl:attribute> + <xsl:attribute name="name"> + <xsl:value-of select="string(varlistentry/term)"/> + </xsl:attribute> + <xsl:text>
</xsl:text> + <xsl:variable name="curid" select="varlistentry/term/ref/@refid"/> + <xsl:apply-templates + select="//variablelist[varlistentry/term/ref/@refid=$curid]" + mode="inlist"/> + </xsl:element> + <xsl:text>
</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="variablelist" mode="inlist"> + <item> + <xsl:value-of select="string(listitem)"/> + </item> + <xsl:text>
</xsl:text> + </xsl:template> + + <xsl:template match="/"> + <xsl:element name="xreflist"> + <xsl:attribute name="type"> + <xsl:value-of select="$type"/> + </xsl:attribute> + <xsl:attribute name="module"> + <xsl:value-of select="$module"/> + </xsl:attribute> + <xsl:text>
</xsl:text> + <xsl:apply-templates/> + </xsl:element> + </xsl:template> + + <xsl:template match="compoundname"/> + <xsl:template match="title"/> + <xsl:template match="anchor"/> + +</xsl:stylesheet>