--- /dev/null
+KERNELDOC=scripts/kernel-doc
+export KERNELDOC
+
+XML_BASENAMES = ortedoc
+
+DSL_DIR = ../../../dsl
+
+XML_SRC = ${XML_BASENAMES:%=%.xml}
+
+#DSL_DEF = -d $(DSL_DIR)/ocera-print.dsl
+
+ORTE_DOC_SOURCES = \
+orte/typedefs_api.xml \
+orte/protos_api.xml \
+orte/defines_api.xml
+
+default: all
+
+all: $(ORTE_DOC_SOURCES) orteman.pdf
+
+XML_ENT_INCS = $(wildcard *.ent)
+XML_ENTITIES = $(shell cat $(XML_ENT_INCS) | \
+ sed -n -e 's/^ *<!ENTITY *[^ ]* *SYSTEM *"\([^"]*\)" *> *$$/\1/p' | \
+ sed -e 's/^\([^.]*\)$$/\1.*/p' )
+
+%.pdf: %.xml $(XML_ENTITIES) $(XML_ENT_INCS)
+ #echo "$(XML_ENTITIES) $(XML_ENT_INCS)"
+ docbook2pdf $(DSL_DEF) $<
+
+%.xml: ../../orte/include/orte/%.h
+ $(KERNELDOC) -docbook $< >$@
+
+
+clean:
+ @rm -f ${XML_BASENAMES:%=%.html}
+ @rm -f ${XML_BASENAMES:%=%.pdf}
+ @rm -f ./*.log
+ @rm -f ./*.out
+ @rm -f ./*~
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<section id="orte-api">
+ <title>ORTE API</title>
+
+ <section><!--sect1-->
+ <title>Data types</title>
+ &orte_typedefs_api;
+ </section><!--/sect1-->
+
+ <section><!--sect2-->
+ <title>Functions</title>
+ &orte_protos_api;
+ </section><!--/sect2-->
+
+ <section><!--sect3-->
+ <title>Macros</title>
+ &orte_defines_api;
+ </section><!--/sect3-->
+
+</section>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<section id="orte-examples">
+ <title>ORTE Examples</title>
+
+ <para>
+ This chapter expect that you are familiar with RTPS communication
+ architecture described in <xref linkend="orte-description"/>.
+ </para>
+ <para>
+ Publications can offer multiple reliability policies ranging from
+ best-efforts to strict (blocking) reliability. Subscription can
+ request multiple policies of desired reliability and specify the
+ relative precedence of each policy. Publications will automatically
+ select among the highest precedence requested policy that is
+ offered by the publication.
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">BestEffort:</emphasis>
+ This reliability policy is suitable for data that are sending
+ with a period. There are no message resending when a message is lost.
+ On other hand, this policy offer maximal predictable behaviour.
+ For instance, consider a publication which send data from a sensor
+ (pressure, temperature, ...).
+ </para>
+
+ <figure id="cap:orte_pub_snapshots">
+ <title>Periodic Snapshots of a BestEffort Publisher
+ </title>
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="&orte_pub_snapshots_img;"
+ format="EPS" scale="35" srccredit="OCERA CTU 2004" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">StrictReliable:</emphasis>
+ The ORTE supports the reliable delivery of issues. This kind of communication
+ is used where a publication want to be sure that all data will be delivered to
+ subscriptions. For instance, consider a publication which send commands.
+ </para>
+ <para>
+ Command data flow requires that each instruction in the sequence is
+ delivered reliably once and only once. Commands are often not time critical.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <section id="orte-example1">
+ <title>BestEffort Communication</title>
+
+ <para>
+ Before creating a Publication or Subscription is necessary to
+ create a domain by using function
+ <parameter class='function'>ORTEDomainAppCreate</parameter>.
+ The code should looks like:
+ </para>
+ <programlisting>
+int main(int argc, char *argv[])
+{
+ ORTEDomain *d = NULL;
+ ORTEBoolean suspended= ORTE_FALSE;
+
+ ORTEInit();
+
+ d = ORTEDomainAppCreate(ORTE_DEFAUL_DOMAIN, NULL, NULL, suspended);
+ if (!d)
+ {
+ printf("ORTEDomainAppCreate failed\n");
+ return -1;
+ }
+}
+ </programlisting>
+
+ <para>
+ The ORTEDomainAppCreate allocates and initializes resources that are needed
+ for communication. The parameter <parameter class='command'>suspended</parameter> says
+ if ORTEDomain takes suspend communicating threads. In
+ positive case you have to start threads manually by using
+ <parameter class='function'>ORTEDomainStart</parameter>.
+ </para>
+
+
+ <para>
+ Next step in creation of a application is registration serialization and
+ deserialization routines for the specific type. You can't specify this functions,
+ but the incoming data will be only copied to output buffer.
+ </para>
+ <programlisting>
+ORTETypeRegisterAdd(d, "HelloMsg", NULL, NULL, 64);
+ </programlisting>
+
+ <para>
+ To create a publication in specific domain use the function
+ ORTEPublicationCreate.
+ </para>
+ <programlisting>
+char instance2send[64];
+NtpTime persistence, delay;
+
+NTPTIME_BUILD(persistence, 3); /* this issue is valid for 3 seconds */
+NTPTIME_DELAY(delay, 1); /* a callback function will be called every 1 second */
+p = ORTEPublicationCreate( d,
+ "Example HelloMsg",
+ "HelloMsg",
+ &instance2Send,
+ &persistence,
+ 1,
+ sendCallBack,
+ NULL,
+ &delay);
+ </programlisting>
+
+ <para>
+ The callback function will be then called when a new issue from
+ publisher has to be sent. It's the case when you specify callback routine in
+ <parameter class='function'>ORTEPublicationCreate</parameter>. When
+ there isn't a routine you have to send data manually by call function
+ <parameter class='function'>ORTEPublicationSend</parameter>. This option
+ is useful for sending periodic data.
+ </para>
+ <programlisting>
+void sendCallBack(const ORTESendInfo *info, void *vinstance, void *sendCallBackParam)
+{
+ char *instance = (char *) vinstance;
+ switch (info->status)
+ {
+ case NEED_DATA:
+ printf("Sending publication, count %d\n", counter);
+ sprintf(instance, "Hello world (%d)", counter++);
+ break;
+
+ case CQL: //criticalQueueLevel has been reached
+ break;
+ }
+}
+ </programlisting>
+
+ <para>
+ Subscribing application needs to create a subscription with
+ publication's Topic and TypeName. A callback function will be then
+ called when a new issue from publisher will be received.
+ </para>
+ <programlisting>
+ORTESubscription *s;
+NtpTime deadline, minimumSeparation;
+
+NTPTIME_BUILD(deadline, 20);
+NTPTIME_BUILD(minimumSeparation, 0);
+p = ORTESubscriptionCreate( d,
+ IMMEDIATE,
+ BEST_EFFORTS,
+ "Example HelloMsg",
+ "HelloMsg",
+ &instance2Recv,
+ &deadline,
+ &minimumSeparation,
+ recvCallBack,
+ NULL);
+ </programlisting>
+
+ <para>
+ The callback function is shown in the following example:
+ </para>
+ <programlisting>
+void recvCallBack(const ORTERecvInfo *info, void *vinstance, void *recvCallBackParam)
+{
+ char *instance = (char *) vinstance;
+ switch (info->status)
+ {
+ case NEW_DATA:
+ printf("%s\n", instance);
+ break;
+
+ case DEADLINE: //deadline occurred
+ break;
+ }
+}
+ </programlisting>
+
+ <para>
+ Similarly examples are located in ORTE subdirectory
+ <filename>orte/examples/hello</filename>. There are
+ demonstrating programs how to create an application
+ which will publish some data and another application, which will
+ subscribe to this publication.
+ </para>
+
+ </section>
+
+ <section id="orte-example2">
+ <title>Reliable communication</title>
+
+ <para>
+ The reliable communication is used especially in situations
+ where we need guarantee data delivery. The ORTE supports the inorder
+ delivery of issues with built-in retry mechanism
+ </para>
+ <para>
+ The creation of reliable communication starts like besteffort communication.
+ Difference is in creation a subscription. Third parameter is just only changed
+ to STRICT_RELIABLE.
+ </para>
+
+ <programlisting>
+ORTESubscription *s;
+NtpTime deadline, minimumSeparation;
+
+NTPTIME_BUILD(deadline, 20);
+NTPTIME_BUILD(minimumSeparation, 0);
+p = ORTESubscriptionCreate( d,
+ IMMEDIATE,
+ STRICT_RELIABLE,
+ "Example HelloMsg",
+ "HelloMsg",
+ &instance2Recv,
+ &deadline,
+ &minimumSeparation,
+ recvCallBack,
+ NULL);
+ </programlisting>
+
+ <para><phrase role="strong">Note:</phrase></para>
+ <para>
+ Strict reliable subscription must set minimumSeparation to zero! The middleware
+ can't guarantee that the data will be delivered on first attempt (retry mechanism).
+ </para>
+
+ <para>
+ Sending of a data is blocking operation. It's strongly recommended to
+ setup sending queue to higher value. Default value is 1.
+ </para>
+ <programlisting>
+ORTEPublProp *pp;
+
+ORTEPublicationPropertiesGet(publisher,pp);
+pp->sendQueueSize=10;
+pp->criticalQueueLevel=8;
+ORTEPublicationPropertiesSet(publisher,pp);
+ </programlisting>
+
+ <para>
+ An example of reliable communication is in ORTE subdirectory
+ <filename>orte/examples/reliable</filename>. There are located
+ a strictreliable subscription and publication.
+ </para>
+
+ </section>
+
+ <section id="orte-example3">
+ <title>Serialization/Deserialization</title>
+
+ <para>
+ Actually the ORTE doesn't support any automatic creation of
+ serialization/deserializaction routines.
+ This routines have to be designed manually by the user. In next is
+ shown, how should looks both for the structure BoxType.
+ </para>
+<programlisting>
+typedef struct BoxType {
+ int32_t color;
+ int32_t shape;
+} BoxType;
+
+void
+BoxTypeSerialize(CDR_Codec *cdrCodec, void *instance) {
+ BoxType *boxType=(BoxType*)instance;
+
+ CDR_put_long(cdrCodec,boxType->color);
+ CDR_put_long(cdrCodec,boxType->shape);
+}
+
+void
+BoxTypeDeserialize(CDR_Codec *cdrCodec, void *instance) {
+ BoxType *boxType=(BoxType*)instance;
+
+ CDR_get_long(cdrCodec,&boxType->color);
+ CDR_get_long(cdrCodec,&boxType->shape);
+}
+</programlisting>
+
+ <para>
+ When we have written a serialization/deserialization routine we need to
+ register this routines to midleware by function
+ <function>ORTETypeRegisterAdd</function>
+ </para>
+
+<programlisting>
+ ORTETypeRegisterAdd(
+ domain,
+ "BoxType",
+ BoxTypeSerialize,
+ BoxTypeDeserialize,
+ sizeof(BoxType));
+</programlisting>
+
+ <para>
+ The registration must be called before creation a publication or subscription.
+ Normally is <function>ORTETypeRegisterAdd</function> called immediately after
+ creation of a domain (<function>ORTEDomainCreate</function>).
+ </para>
+
+ <para>
+ All of codes are part of the Shapedemo located in subdirectory
+ <filename>orte/contrib/shape</filename>.
+ </para>
+ </section>
+
+</section>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<section id="orte-internals">
+ <title>ORTE Implementation Issues</title>
+
+ <para>
+ ORTE is network middleware for distributed, real-time application development
+ that uses the real-time, publish-subscribe model. The middleware is available
+ for a variety of platforms including RTAI, RTLinux, Windows, and a several
+ versions of Unix. The compilation system is mainly based on autoconf.
+ </para>
+
+ <para>
+ ORTE is middleware composed of a database, and tasks.
+ On the top of ORTE architecture is application interface (API). By using API
+ users should write self application. The tasks perform all of the message
+ addressing serialization/deserialization, and transporting. The ORTE components
+ are shown in <xref linkend="cap:orte_internal_architecture"/>
+ </para>
+ <figure id="cap:orte_internal_architecture">
+ <title>ORTE Architecture
+ </title>
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="&orte_internal_architecture_img;"
+ format="EPS" scale="35" srccredit="OCERA CTU 2004" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+
+ <para>
+ The RTPS protocol defines two kinds of Applications:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">Manager:</emphasis>
+ The manager is a special Application that helps applications automatically
+ discover each other on the Network.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">ManagedApplication:</emphasis>
+ A ManagedApplication is an Application that is managed by one or more
+ Managers. Every ManagedApplication is managed by at least one Manager.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The manager is mostly designed like separate application. In RTPS architecture
+ is able to create application which contains manager and managedapplication, but
+ for easy managing is better split both. The ORTE contains a separate instance
+ of manager located in directory <filename>orte/manager</filename>.
+ </para>
+
+ <para>The manager is composed from five kinds of objects:</para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">WriterApplicationSelf:</emphasis>
+ through which the Manager provides information about its own parameters
+ to Managers on other nodes.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">ReaderManagers:</emphasis>
+ CSTReader through which the
+ Manager obtains information on the state of all other Managers on the
+ Network.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">ReaderApplications:</emphasis>
+ CSTReader which is used for the registration of local and remote
+ managedApplications.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">WriterManagers:</emphasis>
+ CSTWriter through which the Manager will send the
+ state of all Managers in the Network to all its managees.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">WriterApplications:</emphasis>
+ CSTWriter through which the Manager will
+ send information about its managees to other Managers in the Network.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ A Manager that discovers a new ManagedApplication
+ through its readerApplications must decide whether it must manage this
+ ManagedApplication or not. For this purpose, the attribute
+ managerKeyList of the Application is used. If one of the
+ ManagedApplication's keys (in the attribute managerKeyList) is equal
+ to one of the Manager's keys, the Manager accepts the Application as
+ a managee. If none of the keys are equal, the managed application is
+ ignored. At the end of this process all Managers have discovered their
+ managees and the ManagedApplications know all Managers in the Network.
+ </para>
+
+ <para>The managedApplication is composed from seven kinds of objects:</para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">WriterApplicationSelf:</emphasis>
+ a CSTWriter through which the ManagedApplication registers
+ itself with the local Manager.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">ReaderApplications:</emphasis>
+ a CSTReader through which the ManagedApplication receives
+ information about another ManagedApplications in the network.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">ReaderManagers:</emphasis>
+ a CSTReader through which the ManagedApplication receives
+ information about Managers.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">WriterPublications:</emphasis>
+ CSTWriter through which the Manager will send the
+ state of all Managers in the Network to all its managees.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">ReaderPublications:</emphasis>
+ a Reader through which the Publication receives information
+ about Subscriptions.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">WriterSubscriptions:</emphasis>
+ a Writer that provides information about Subscription to
+ Publications.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">ReaderSubscriptions:</emphasis>
+ a Reader that receives issues from one or more instances of
+ Publication, using the publish-subscribe service.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ The ManagedApplication has a special CSTWriter writerApplicationSelf. The
+ Composite State (CS) of the ManagedApplication's writerApplicationSelf
+ object contains only one NetworkObject - the application itself. The
+ writerApplicationSelf of the ManagedApplication must be configured to
+ announce its presence repeatedly and does not request nor expect
+ acknowledgments.
+ </para>
+ <para>
+ The ManagedApplications now use the CST Protocol between the
+ writerApplications of the Managers and the readerApplications of the
+ ManagedApplications in order to discover other ManagedApplications in
+ the Network. Every ManagedApplication has two special CSTWriters,
+ writerPublications and writerSubscriptions, and two special CSTReaders,
+ readerPublications and readerSubscriptions.
+ </para>
+ <para>
+ Once ManagedApplications have discovered each other, they use the
+ standard CST protocol through these special CSTReaders and CSTWriter to
+ transfer the attributes of all Publications and Subscriptions in the
+ Network.
+ </para>
+
+ <para>The ORTE stores all data in local database per application. There isn't
+ central store where are data saved. If an application comes into communication,
+ than will be created local mirror of all applications parameters.
+ Parts of internal structures are shown in <xref linkend="cap:orte_attributes"/>.
+ </para>
+ <figure id="cap:orte_attributes">
+ <title>ORTE Internal Attributes
+ </title>
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="&orte_attributes_img;"
+ format="EPS" scale="35" srccredit="OCERA CTU 2004" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ Following example shows communication between two nodes (N1, N2).
+ There are applications running on each node - MA1.2 on node
+ N1 and MA2.1, MA2.2 on node N2. Each node has it own manager (M1, M2). The
+ example shows, what's happen when a new application comes into communication
+ (MA1.1).
+ </para>
+
+ <orderedlist>
+ <listitem><para>
+ MA1.1 introduces itself to local manager M1
+ </para></listitem>
+ <listitem><para>
+ M1 sends back list of remote managers Mx and other local applications MA1.x
+ </para></listitem>
+ <listitem><para>
+ MA1.1 is introduced to all Mx by M1
+ </para></listitem>
+ <listitem><para>
+ All remote MAs are reported now to M1.1
+ </para></listitem>
+ <listitem><para>
+ MA1.1 is queried for self services (publishers and subscriberes) from others MAx.
+ </para></listitem>
+ <listitem><para>
+ MA1.1 asks for services to others MAx.
+ </para></listitem>
+ <listitem><para>
+ All MAs know information about others.
+ </para></listitem>
+ </orderedlist>
+
+ <para>
+ The corresponding publishers and subscribers with matching Topic
+ and Type are connected and starts their data communication.
+ </para>
+
+ <figure id="cap:orte_rtps_communication">
+ <title>RTPS Communication among Network Objects
+ </title>
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="&orte_rtps_communication_img;"
+ format="EPS" scale="35" srccredit="OCERA CTU 2004" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+</section>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<section id="orte-intro">
+ <title>Introduction</title>
+
+ <para id="ORTE" xreflabel="ORTE">
+ The Open Real-Time Ethernet (ORTE) is
+ open source implementation of RTPS communication protocol. This protocol
+ is being to submit to IETF as an informational RFC and has been adopted
+ by the IDA group.
+ </para>
+</section>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<section id="orte-ps">
+ <title>The Publish-Subscribe Architecture </title>
+
+ <para>
+ The publish-subscribe architecture is designed to
+ simplify one-to-many data-distribution requirements.
+ In this model, an application <quote>publishes</quote> data and
+ <quote>subscribes</quote> to data. Publishers and subscribers are
+ decoupled from each other too. That is:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>Publishers simply send data anonymously, they
+ do not need any knowledge of the number or
+ network location of subscribers.
+ </para>
+ </listitem>
+ <listitem>
+ <para>Subscribers simply receive data anonymously,
+ they do not need any knowledge of the number or
+ network location of the publisher.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ An application can be a publisher, subscriber, or both a
+ publisher and a subscriber.
+ </para>
+
+ <figure id="cap:orte_ps_model_img">
+ <title>Publish-Subscribe Architecture
+ </title>
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="&orte_ps_model_img;"
+ format="EPS" scale="45" srccredit="OCERA CTU 2004" />
+ </imageobject>
+ <caption><para>
+ <emphasis role="italic">
+ Publish-subscribe supports anonymous, event-driven
+ transfer between many nodes. The developer simply writes
+ the application to send or receive the data.
+ </emphasis>
+ </para></caption>
+ </mediaobject>
+ </figure>
+
+ <para>
+ Publish-subscribe architectures are best-suited to
+ distributed applications with complex data flows. The
+ primary advantages of publish-subscribe to
+ applications developers are:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Publish-subscribe applications are modular and
+ scalable. The data flow is easy to manage
+ regardless of the number of publishers and subscribers.
+ </para>
+ </listitem>
+ <listitem>
+ <para>The application subscribes to the data by name
+ rather than to a specific publisher or publisher
+ location. It can thus accommodate configuration
+ changes without disrupting the data flow.
+ </para>
+ </listitem>
+ <listitem>
+ <para>Redundant publishers and subscribers can be
+ supported, allowing programs to be replicated
+ (e.g. multiple control stations) and moved transparently.
+ </para>
+ </listitem>
+ <listitem>
+ <para>Publish-subscribe is much more efficient,
+ especially over client-server, with bandwidth utilization.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Publish-subscribe architectures are not good at
+ sporadic request/response traffic, such as file transfers.
+ However, this architecture offers practical advantages
+ for applications with repetitive, time-critical data
+ flows.
+ </para>
+
+ <section id="orte-ps-model">
+ <title>The Publish-Subscribe Model</title>
+
+ <para>
+ Publish-subscribe (PS) data distribution is gaining popularity in many
+ distributed applications, such as financial communications, command
+ and control systems. PS popularity can be attributed to the dramatically
+ reduced system development, deployment and maintenance effort and the
+ performance advantages for applications with one-to-many and
+ many-to-many data flows.
+ </para>
+
+ <para>
+ Several main features characterize all publish-subscribe architectures:
+ </para>
+ <para>
+ <emphasis role="bold">Distinct declaration and delivery.</emphasis>
+ Communications occur in three simple steps:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>Publisher declares intent to publish a publication.</para>
+ </listitem>
+ <listitem>
+ <para>Subscriber declares interest in a publication.</para>
+ </listitem>
+ <listitem>
+ <para>Publisher sends a publication issue.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ The publish-subscribe services are typically made available to
+ applications through middleware that sits on top of the operating
+ system s network interface and presents an application programming
+ interface.
+ </para>
+
+ <figure id="cap:orte_ps_architecture_img">
+ <title>Generic Publish-Subscribe Architecture
+ </title>
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="&orte_ps_architecture_img;"
+ format="EPS" scale="35" srccredit="OCERA CTU 2004" />
+ </imageobject>
+ <caption><para>
+ <emphasis role="italic">
+ Publish-subscribe is typically implemented through middleware that
+ sits on top of the operating system s network interface. The
+ middleware presents a publishsubscribe API so that applications
+ make just a few simple calls to send and receive publications. The
+ middleware performs the many and complex network functions that
+ physically distribute the data.
+ </emphasis>
+ </para></caption>
+ </mediaobject>
+ </figure>
+
+ <para>
+ The middleware handles three basic programming chores:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Maintain the database that maps publishers to subscribers
+ resulting in logical data channels for each publication
+ between publishers and subscribers.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Serialize (also called marshal) and deserialize (demarshal) the data
+ on its way to and from the network to reconcile publisher
+ and subscriber platform differences.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Deliver the data when it is published.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section id="orte-ps-in-RT">
+ <title>Publish-Subscribe in Real Time</title>
+
+ <para>
+ Publish-subscribe offers some clear advantages for real-time applications:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Because it is very efficient in both bandwidth and
+ latency for periodic data exchange, PS offers the
+ best transport for distributing data quickly.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Because it provides many-to-many connectivity,
+ PS is ideal for applications in which publishers
+ and subscribers are added and removed
+ dynamically.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Real-time applications require more functionality than what is provided
+ by desktop and Internet publish-subscribe semantics. For instance, real-time
+ applications often require:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">Delivery timing control:</emphasis>
+ Real-time subscribers are concerned with timing; for example, when the
+ data is delivered and how long it remains valid.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">Reliability control:</emphasis>
+ Reliable delivery conflicts with deterministic timing. Each subscriber
+ typically requires the ability to specify its own reliability
+ characteristics.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">Request-reply semantics:</emphasis>
+ Complex real-time applications often have one-time requests for
+ actions or data. These do not fit well into the PS semantics.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">Flexible delivery bandwidth:</emphasis>
+ Typical real-time applications include both real-time and
+ non-realtime subscribers. Each subscriber s bandwidth requirements - even
+ for the same publication - can be different.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">Fault tolerance:</emphasis>
+ Real-time applications often require <quote>hot standby</quote> publishers
+ and/or subscribers.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">Thread priority awareness:</emphasis>
+ Real-time communications often must work without
+ affecting publisher or subscriber threads.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">Robustness:</emphasis>
+ The communications layer should not introduce any single-node
+ points-of-failure to the application.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">Efficiency:</emphasis>
+ Real-time systems require efficient data collection and delivery.
+ Only minimal delays should be introduced into the critical
+ data-transfer path.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ </section>
+
+</section>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<section id="orte-rtps">
+ <title>The Real-Time Publish-Subscribe Model</title>
+
+ <para>
+ The Real-Time Publish-Subscribe (RTPS) communications model was developed
+ to address these limitations of PS. RTPS adds publication and subscription timing
+ parameters and properties so the developer can control the different types
+ of data flows and achieve their application s performance and
+ reliability goals.
+ </para>
+
+ <section id="orte-rtps-publication">
+ <title>Publication Parameters</title>
+
+ <para>
+ Each publication is characterized by four
+ parameters: topic, type, strength and persistence. The topic is the label
+ that identifies each data flow. The type describes the data format.
+ The strength indicates a publisher s weight relative to other publishers
+ of the same topic. The persistence indicates how long each publication
+ issue is valid. Next figure illustrates how a subscriber arbitrates
+ among publications using the strength and persistence properties.
+ </para>
+
+ <figure id="cap:orte_pub_arbitration_img">
+ <title>Publication Arbitration
+ </title>
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="&orte_pub_arbitration_img;"
+ format="EPS" scale="45" srccredit="OCERA CTU 2004" />
+ </imageobject>
+ <caption><para>
+ <emphasis role="italic">
+ Fault tolerant applications use redundant publishers sending
+ publications with the same topic to ensure continuous
+ operation. Subscribers arbitrate among the publications
+ on an issue-by-issue basis based on the strength and persistence
+ of each issue.
+ </emphasis>
+ </para></caption>
+ </mediaobject>
+ </figure>
+
+ <para>
+ When there are multiple publishers sending the same
+ publication, the subscriber accepts the issue if its strength
+ is greater than the last-received issue or if the last issue s
+ persistence has expired. Typically, a publisher that sends issues
+ with a period of length T will set its persistence to some
+ time Tp where Tp > T. Thus, while the strongest publisher is
+ functional, its issues will take precedence over publication
+ issues of lesser strength. Should the strongest publisher stop
+ sending issues (willingly or due to a failure), other publisher(s)
+ sending issues for the same publication will take over after Tp elapses. This
+ mechanism establishes an inherently robust, quasi-stateless communications
+ channel between the then-strongest publisher of a publication
+ and all its subscribers.
+ </para>
+ </section>
+
+ <section id="orte-rtps-subscription">
+ <title>Subscription Paramters</title>
+
+ <para>
+ Subscriptions are identified by four
+ parameters: topic, type, minimum separation and deadline. The topic
+ the label that identifies the data flow, and type describes the
+ data format (same as the publication properties). Minimum separation
+ defines a period during which no new issues are accepted for
+ that subscription. The deadline specifies how long the subscriber is
+ willing to wait for the next issue. Next figure illustrates the use
+ of these parameters.
+ </para>
+
+ <figure id="cap:orte_sub_issue_separation_img">
+ <title>Subscription Issue Separation
+ </title>
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="&orte_sub_issue_separation_img;"
+ format="EPS" scale="45" srccredit="OCERA CTU 2004" />
+ </imageobject>
+ <caption><para>
+ <emphasis role="italic">
+ Once the subscriber has received an issue, it will not receive
+ another issue for at least the minimum separation time. If a
+ new issue does not arrive by the deadline, the application
+ is notified.
+ </emphasis>
+ </para></caption>
+ </mediaobject>
+ </figure>
+
+ <para>
+ The minimum separation protects a slow subscriber against publishers
+ that are publishing too fast. The deadline provides a guaranteed wait
+ time that can be used to take appropriate action in case of
+ communication delays.
+ </para>
+ </section>
+
+ <section id="orte-rtps-reliability-determinism">
+ <title>Reliability and Time-Determinism</title>
+
+ <para>
+ Publish-subscribe can support a variety of message delivery reliability
+ models, not all of which are suitable to real-time applications. The
+ RTPS reliability model recognizes that the optimal balance between
+ time determinism and data-delivery reliability varies between real-time
+ applications, and often among different subscriptions within the
+ same application. For example, signal subscribers will want only
+ the most up-to-date issues and will not care about missed issues. Command
+ subscribers, on the other hand, must get every issue in
+ sequence. Therefore, RTPS provides a mechanism for the application to
+ customize the determinism versus reliability trade-off on a per subscription
+ basis.
+ </para>
+ <para>
+ The RTPS determinism vs. reliability model is subscriber-driven. Publishers
+ simply send publication issues. However, to provide message delivery
+ reliability, publishers must be prepared to resend missed issues to subscriptions
+ that require reliable delivery.
+ </para>
+ <para>
+ The RTPS reliability model uses publication buffers publisher and subscriber and
+ retries to ensure that subscribers who need each issue receive them in the proper
+ sequence. In addition, the publisher applies sequence number to each
+ publication issue.
+ </para>
+ <para>
+ The publisher uses the publication buffer to store history of the most
+ recently sent issues. The subscriber uses its publication buffer to cache the
+ most recently received issues. The subscriber acknowledges issues received in
+ order and sends a request for the missing issue when the most recent
+ issue s sequence number out of order. The publisher responds by sending the
+ missed update again.
+ </para>
+ <para>
+ Publishers remove an issue from their history buffers in two cases: the issue has been
+ acknowledged by all reliable subscribers or the publisher overflows the history buffer
+ space. Flow control can be implemented by setting high and low watermarks for
+ the buffer. These publication-specific parameters let the publisher balance
+ the subscribers need for issues against its need to
+ maintain a set publication rate.
+ </para>
+ </section>
+
+</section>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<section id="orte-summary">
+ <title>Summary</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>Name of the component</term>
+
+ <listitem>
+ <para>Open Real-Time Ethernet (ORTE)</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Author</term>
+
+ <listitem>
+ <para><author><firstname>Petr</firstname> <surname>Smolik</surname></author></para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>ORTE Internet resources</term>
+
+ <listitem>
+ <para><ulink url="http://www.ocera.org"></ulink> OCERA project home page</para>
+
+ <para><ulink url="http://sourceforge.net/projects/ocera"></ulink>
+ OCERA SourceForge project page. The OCERA CVS relative path to ORTE
+ driver sources is</para>
+ <para><ulink url="http://cvs.sourceforge.net/viewcvs.py/ocera/ocera/components/comm/eth/orte/">
+ <filename>ocera/components/comm/eth/orte</filename></ulink>.</para>
+
+ <para><ulink url="http://www.rti.com"></ulink> Real-Time Innovation home page</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Reviewer</term>
+
+ <listitem>
+ <para>not validated</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Layer</term>
+
+ <listitem>
+ <para>High-level</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Version</term>
+
+ <listitem>
+ <para>orte-0.3.1</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Status</term>
+
+ <listitem>
+ <para>Beta</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Dependencies</term>
+
+ <listitem>
+ <para>Ethernet adapter with a UDP stack.</para>
+ <para>Multi-threaded operating system OS</para>
+ <para>Memory allocator (functions malloc, free)</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Supported OS</term>
+
+ <listitem>
+ <itemizedlist>
+ <listitem>
+ <para>Unix - Linux, FreeBSD, Solaris, MacOS, PharLap</para>
+ </listitem>
+ <listitem>
+ <para>Windows</para>
+ </listitem>
+ <listitem>
+ <para>RTAI with RTNet</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Release date</term>
+
+ <listitem>
+ <para>September 2004</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+</section>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<section id="orte-tests">
+ <title>ORTE Tests</title>
+
+ <para>
+ There were not any serious tests performed yet. Current version
+ has been intensively tested against reference implementation of the
+ protocol. Results of these test indicate that ORTE is fully
+ interoperable with implementation provided by another vendor.
+ </para>
+</section>
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<section id="orte-usage">
+ <title>ORTE Usage Information</title>
+
+ <section id="orte-installation">
+ <title>Installation and Setup</title>
+
+ <para>
+ In this chapter is described basic steps how to makes installation
+ and setup process of the ORTE. The process includes next steps:
+ </para>
+
+ <para>
+ <orderedlist>
+ <listitem><para>Downloading the ORTE distribution</para></listitem>
+ <listitem><para>Compilation</para></listitem>
+ <listitem><para>Installing the ORTE library and utilities</para></listitem>
+ <listitem><para>Testing the installation</para></listitem>
+ </orderedlist>
+ </para>
+
+ <para><phrase role="strong">Note:</phrase></para>
+ <para>
+ On windows systems we are recommend to use Mingw or Cygwin systems. The
+ ORTE support also MSVC compilation, but this kind of installation is not
+ described here.
+ </para>
+ <section id="orte-installation-downloading">
+ <title>Downloading </title>
+
+ <para>
+ The ORTE component can be obtained from OCERA SourceForge web page
+ (<ulink url="http://www.sf.net/projects/ocera/"></ulink>). Here is the component
+ located also in self distribution branch as well as in OCERA distribution.
+ Before developing any application check if there is a new file release.
+ </para>
+ <para>
+ The CVS version of ORTE repository can be checked out be anonymous (pserver)
+ CVS with the following commands.
+ <programlisting>
+cvs -d:pserver:anonymous@cvs.ocera.sourceforge.net:/cvsroot/ocera login
+cvs -z3 -d:pserver:anonymous@cvs.ocera.sourceforge.net:/cvsroot/ocera co ocera/components/comm/eth/orte/
+ </programlisting>
+ Attention, there is developing version and can't be stable!
+ </para>
+ </section>
+
+ <section id="orte-installation-compilation">
+ <title>Compilation</title>
+ <para>
+ Before the compilation process is necessary to prepare the source.
+ Create a new directory for ORTE distribution. We will assume name of this
+ directory <filename>/orte</filename> for Linux case. Copy or move downloaded
+ ORTE sources to <filename>/orte</filename> (assume the name of sources
+ <filename>orte-0.2.3.tar.gz</filename>). Untar and unzip this files by using
+ next commands:
+ <programlisting>
+gunzip orte-0.2.3.tar.gz
+tar xvf orte-0.2.3.tar
+ </programlisting>
+ Now is the source prepared for compilation. Infrastructure of the ORTE is
+ designed to support GNU make (needs version 3.81) as well as autoconf compilation. In
+ next we will continue with description of autoconf compilation, which is more
+ general. The compilation can follows with commands:
+ <programlisting>
+mkdir build
+cd build
+../configure
+make
+ </programlisting>
+ This is the case of outside autoconf compilation. In directory <filename>build</filename>
+ are all changes made over ORTE project. The source can be easy move to original
+ state be removing of directory <filename>build</filename>.
+ </para>
+ </section>
+
+ <section id="orte-installation-installing">
+ <title>Installing</title>
+
+ <para>
+ The result of compilation process are binary programs and ORTE library. For the
+ next developing is necessary to install this result. It can be easy done be typing:
+ <programlisting>
+make install
+ </programlisting>
+ All developing support is transferred into directories with direct access of
+ design tools.
+ </para>
+ <informaltable frame='none'>
+ <tgroup cols='2'>
+ <colspec align="left" colwidth="1*"/>
+ <colspec align="left" colwidth="1*"/>
+ <thead>
+ <row>
+ <entry align="center">name</entry>
+ <entry align="center">target path</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row><entry>ortemanager, orteping, ortespy</entry>
+ <entry><filename>/usr/local/bin</filename></entry></row>
+ <row><entry>library</entry>
+ <entry><filename>/usr/local/lib</filename></entry></row>
+ <row><entry>include</entry>
+ <entry><filename>/usr/local/include</filename></entry></row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <para>
+ The installation prefix <filename>/usr/local/</filename> can be changed
+ during configuration. Use command <command>../configure --help</command> for
+ check more autoconf options.
+ </para>
+ </section>
+
+ <section id="orte-installation-testing">
+ <title>Testing the Installation</title>
+
+ <para>
+ To check of correct installation of ORTE open three shells.
+ </para>
+
+ <para>
+ <orderedlist>
+ <listitem>
+ <para>In first shell type</para>
+ <programlisting>ortemanager</programlisting>
+ </listitem>
+ <listitem>
+ <para>In second shell type</para>
+ <programlisting>orteping -s</programlisting>
+ <para>
+ This command will invoked creation of a subscription. You should see:
+ </para>
+ <programlisting>
+deadline occurred
+deadline occurred
+...
+ </programlisting>
+ </listitem>
+ <listitem>
+ <para>In third shell type</para>
+ <programlisting>orteping -p</programlisting>
+ <para>
+ This command will invoked creation of a publication. You should see:
+ </para>
+ <programlisting>
+sent issue 1
+sent issue 2
+sent issue 3
+sent issue 4
+...
+ </programlisting>
+ <para>
+ If the ORTE installation is properly, you will see incoming messages
+ in second shell (<command>orteping -s</command>).
+ </para>
+ <programlisting>
+received fresh issue 1
+received fresh issue 2
+received fresh issue 3
+received fresh issue 4
+...
+ </programlisting>
+ <para>
+ It's sign, that communication is working correctly.
+ </para>
+ </listitem>
+ </orderedlist>
+ </para>
+
+ </section>
+ </section>
+
+ <section id="orte-manager">
+ <title>The ORTE Manager</title>
+
+ <para>
+ A manager is special application that helps
+ applications automatically discover each other on the Network.
+ Each time an object is created or destroyed, the manager
+ propagate new information to the objects that are internally
+ registered.
+ </para>
+ <para>
+ Every application precipitate in communication is managed by least
+ one manager. The manager should be designed like separated application
+ as well as part of designed application.
+ </para>
+
+ <figure id="cap:orte_managers_img">
+ <title>Position of Managers in RTPS communication
+ </title>
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="&orte_managers_img;"
+ format="EPS" scale="35" srccredit="OCERA CTU 2004" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ The ORTE provides one instance of a manager. Name of this utility
+ is <filename>ortemanager</filename> and is located
+ in directory <filename>orte/ortemanager</filename>. Normally is necessary to
+ start <filename>ortemanager</filename> manually or use a script on
+ UNIX systems. For Mandrake and Red-hat distribution is this script created
+ in subdirectory <filename>rc</filename>. Windows
+ users can install <filename>ortemanager</filename> like service by
+ using option <parameter class='option'>/install_service</parameter>.
+ </para>
+ <para><phrase role="strong">Note:</phrase></para>
+ <para>
+ Don't forget to run a manager (ortemanager) on each RTPS participate node.
+ During live of applications is necessary to be running this manager.
+ </para>
+
+ <section id="orte-manager-example">
+ <title>Example of Usage ortemanager</title>
+
+ <para>
+ Each manager has to know where are other managers in the network.
+ Their IP addresses are therefore specified as IPAddressX parameters of
+ ortemanager. All managers participate in one kind of communication use
+ the same domain number. The domain number is transferred to port number by
+ equation defined in RTPS specification (normally domain 0 is transferred to
+ 7400 port).
+ </para>
+ <para>
+ Let's want to distribute the RTPS communication of nodes with IP addresses
+ 192.168.0.2 and 192.168.0.3. Private IP address is 192.168.0.1.
+ The ortemanager can be execute with parameters:
+ </para>
+ <programlisting>
+ortemanager -p 192.168.0.2:192.168.0.3
+ </programlisting>
+ <para>
+ To communicate in different domain use (parameter -d):
+ </para>
+ <programlisting>
+ortemanager -d 1 -p 192.168.0.2:192.168.0.3
+ </programlisting>
+ <para>
+ Very nice feature of ortemanager is use event system to inform
+ of creation/destruction objects (parameter -e).
+ </para>
+ <programlisting>
+ortemanager -e -p 192.168.0.2:192.168.0.3
+ </programlisting>
+ <para>
+ Now, you can see messages:
+ </para>
+ <programlisting>
+[smolik@localhost smolik]$ortemanager -e -p 192.168.0.2:192.168.0.3
+manager 0xc0a80001-0x123402 was accepted
+application 0xc0a80002-0x800301 was accepted
+application 0xc0a80002-0x800501 was accepted
+application 0xc0a80002-0x800501 was deleted
+manager 0xc0a80001-0x123402 was deleted
+ </programlisting>
+
+ &orte_ortemanager;
+ </section>
+ </section>
+
+ <section id="orte-utils">
+ <title>Simple Utilities</title>
+ <para>
+ The simple utilities can be found in the <filename>orte/examples</filename>
+ subdirectory of the ORTE source subtree. These utilities are useful
+ for testing and monitoring RTPS communication.
+ </para>
+
+ <para>
+ The utilities provided directly by ORTE are:
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>orteping</term>
+
+ <listitem>
+ <para>the utility for easy creating of publications and subscriptions.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>ortespy</term>
+
+ <listitem>
+ <para>monitors issues produced by other application in specific domain.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ &orte_orteping;
+ &orte_ortespy;
+
+ </section>
+</section>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<refentry>
+ <!--
+ <refentryinfo>
+ <address>
+ <email>petr.smolik@wo.cz</email>
+ </address>
+ <author>
+ <firstname>Petr</firstname>
+ <surname>Smolik</surname>
+ </author>
+ <date>2004-11-02</date>
+ </refentryinfo>
+ -->
+ <refmeta>
+ <refentrytitle>ortemanager</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>ortemanager</refname>
+ <refpurpose>the utility for discovery others applications and managers on the network</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>ortemanager</command>
+ <arg><option>-d <replaceable>domain</replaceable></option></arg>
+ <arg><option>-p <replaceable>ip addresses</replaceable></option></arg>
+ <arg><option>-k <replaceable>ip addresses</replaceable></option></arg>
+ <arg><option>-R <replaceable>refresh</replaceable></option></arg>
+ <arg><option>-P <replaceable>purge</replaceable></option></arg>
+ <arg><option>-D <replaceable></replaceable></option></arg>
+ <arg><option>-E <replaceable>expiration</replaceable></option></arg>
+ <arg><option>-e <replaceable></replaceable></option></arg>
+ <arg><option>-v <replaceable>verbosity</replaceable></option></arg>
+ <arg><option>-l <replaceable>filename</replaceable></option></arg>
+ <arg><option>-V</option></arg>
+ <arg><option>-h</option></arg>
+ <!-- <arg rep='repeat'><option><replaceable>file</replaceable></option></arg> -->
+ </cmdsynopsis>
+ </refsynopsisdiv>
+ <refsect1>
+ <title>Description</title>
+ <para>
+ Main purpose of the utility <command>ortemanager</command> is debug and
+ test ORTE communication.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>OPTIONS</title>
+ <variablelist>
+ <varlistentry>
+ <term><option>-d</option> <option>--domain</option></term>
+ <listitem>
+ <para>
+ The number of working ORTE domain. Default is 0.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-p</option> <option>--peers</option></term>
+ <listitem>
+ <para>
+ The IP addresses parsipiates in RTPS communication.
+ See <xref linkend="orte-manager"/> for example of usage.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-R</option> <option>--refresh</option></term>
+ <listitem>
+ <para>
+ The refresh time in manager. Default 60 seconds.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-P</option> <option>--purge</option></term>
+ <listitem>
+ <para>
+ The searching time in local database for finding expired application.
+ Default 60 seconds.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-E</option> <option>--expiration</option></term>
+ <listitem>
+ <para>
+ Expiration time in other applications.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-m</option> <option>--minimumSeparation</option></term>
+ <listitem>
+ <para>
+ The minimum time between two issues.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-v</option> <option>--verbosity</option></term>
+ <listitem>
+ <para>
+ Set verbosity level.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-l</option> <option>--logfile</option></term>
+ <listitem>
+ <para>
+ All debug messages can be redirect into specific file.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-V</option> <option>--version</option>
+ </term>
+ <listitem>
+ <para>
+ Print the version of <command>ortemanager</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-h</option> <option>--help</option>
+ </term>
+ <listitem>
+ <para>
+ Print usage screen.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+ <!--
+ <refsect1>
+ <title>BACKWARDS COMPATIBILITY</title>
+
+ <para>
+ This.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>ENVIRONMENT</title>
+ <para>
+ The.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>COPYRIGHT</title>
+ <para>
+ This.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>readburst</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>
+ </para>
+ </refsect1>
+ -->
+</refentry>
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<refentry>
+ <!--
+ <refentryinfo>
+ <address>
+ <email>petr.smolik@wo.cz</email>
+ </address>
+ <author>
+ <firstname>Petr</firstname>
+ <surname>Smolik</surname>
+ </author>
+ <date>2004-11-02</date>
+ </refentryinfo>
+ -->
+ <refmeta>
+ <refentrytitle>orteping</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>orteping</refname>
+ <refpurpose>the utility for debugging and testing of ORTE communication</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>orteping</command>
+ <arg><option>-d <replaceable>domain</replaceable></option></arg>
+ <arg><option>-p <replaceable></replaceable></option></arg>
+ <arg><option>-S <replaceable>strength</replaceable></option></arg>
+ <arg><option>-D <replaceable>delay</replaceable></option></arg>
+ <arg><option>-s <replaceable></replaceable></option></arg>
+ <arg><option>-R <replaceable>refresh</replaceable></option></arg>
+ <arg><option>-P <replaceable>purge</replaceable></option></arg>
+ <arg><option>-E <replaceable>expiration</replaceable></option></arg>
+ <arg><option>-m <replaceable>minimumSeparation</replaceable></option></arg>
+ <arg><option>-v <replaceable>verbosity</replaceable></option></arg>
+ <arg><option>-q <replaceable></replaceable></option></arg>
+ <arg><option>-l <replaceable>filename</replaceable></option></arg>
+ <arg><option>-V</option></arg>
+ <arg><option>-h</option></arg>
+ <!-- <arg rep='repeat'><option><replaceable>file</replaceable></option></arg> -->
+ </cmdsynopsis>
+ </refsynopsisdiv>
+ <refsect1>
+ <title>Description</title>
+ <para>
+ Main purpose of the utility <command>orteping</command> is debug and
+ test ORTE communication.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>OPTIONS</title>
+ <variablelist>
+ <varlistentry>
+ <term><option>-d</option> <option>--domain</option></term>
+ <listitem>
+ <para>
+ The number of working ORTE domain. Default is 0.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-p</option> <option>--publisher</option></term>
+ <listitem>
+ <para>
+ Create a publisher with Topic - Ping and Type - PingData.
+ The publisher will publish a issue with period by
+ parameter delay.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-s</option> <option>--strength</option></term>
+ <listitem>
+ <para>
+ Setups relative weight against other publishers. Default is 1.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-D</option> <option>--delay</option></term>
+ <listitem>
+ <para>
+ The time between two issues. Default 1 second.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-s</option> <option>--subscriber</option></term>
+ <listitem>
+ <para>
+ Create a subscriber with Topic - Ping and Type - PingData.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-R</option> <option>--refresh</option></term>
+ <listitem>
+ <para>
+ The refresh time in manager. Default 60 seconds.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-P</option> <option>--purge</option></term>
+ <listitem>
+ <para>
+ The searching time in local database for finding expired application.
+ Default 60 seconds.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-E</option> <option>--expiration</option></term>
+ <listitem>
+ <para>
+ Expiration time in other applications.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-m</option> <option>--minimumSeparation</option></term>
+ <listitem>
+ <para>
+ The minimum time between two issues.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-v</option> <option>--verbosity</option></term>
+ <listitem>
+ <para>
+ Set verbosity level.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-q</option> <option>--quite</option></term>
+ <listitem>
+ <para>
+ Nothing messages will be printed on screen. It can be useful
+ for testing maximal throughput.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-l</option> <option>--logfile</option></term>
+ <listitem>
+ <para>
+ All debug messages can be redirect into specific file.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-V</option> <option>--version</option>
+ </term>
+ <listitem>
+ <para>
+ Print the version of <command>orteping</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-h</option> <option>--help</option>
+ </term>
+ <listitem>
+ <para>
+ Print usage screen.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+ <!--
+ <refsect1>
+ <title>BACKWARDS COMPATIBILITY</title>
+
+ <para>
+ This.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>ENVIRONMENT</title>
+ <para>
+ The.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>COPYRIGHT</title>
+ <para>
+ This.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>readburst</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>
+ </para>
+ </refsect1>
+ -->
+</refentry>
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<refentry>
+ <!--
+ <refentryinfo>
+ <address>
+ <email>petr.smolik@wo.cz</email>
+ </address>
+ <author>
+ <firstname>Petr</firstname>
+ <surname>Smolik</surname>
+ </author>
+ <date>2004-11-02</date>
+ </refentryinfo>
+ -->
+ <refmeta>
+ <refentrytitle>ortespy</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>ortespy</refname>
+ <refpurpose>the utility for monitoring of ORTE issues</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>orteping</command>
+ <arg><option>-d <replaceable>domain</replaceable></option></arg>
+ <arg><option>-v <replaceable>verbosity</replaceable></option></arg>
+ <arg><option>-R <replaceable>refresh</replaceable></option></arg>
+ <arg><option>-P <replaceable>purge</replaceable></option></arg>
+ <arg><option>-e <replaceable>expiration</replaceable></option></arg>
+ <arg><option>-l <replaceable>filename</replaceable></option></arg>
+ <arg><option>-V</option></arg>
+ <arg><option>-h</option></arg>
+ <!-- <arg rep='repeat'><option><replaceable>file</replaceable></option></arg> -->
+ </cmdsynopsis>
+ </refsynopsisdiv>
+ <refsect1>
+ <title>Description</title>
+ <para>
+ Main purpose of the utility <command>ortespy</command> is monitoring data
+ traffic between publications and subscriptions.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>OPTIONS</title>
+ <variablelist>
+ <varlistentry>
+ <term><option>-d</option> <option>--domain</option></term>
+ <listitem>
+ <para>
+ The number of working ORTE domain. Default is 0.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-v</option> <option>--verbosity</option></term>
+ <listitem>
+ <para>
+ Set verbosity level.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-R</option> <option>--refresh</option></term>
+ <listitem>
+ <para>
+ The refresh time in manager. Default 60 seconds.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-P</option> <option>--purge</option></term>
+ <listitem>
+ <para>
+ Create publisher
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-e</option> <option>--expiration</option></term>
+ <listitem>
+ <para>
+ Expiration time in other applications.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-l</option> <option>--logfile</option></term>
+ <listitem>
+ <para>
+ All debug messages can be redirect into specific file.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-V</option> <option>--version</option></term>
+ <listitem>
+ <para>
+ Print the version of <command>orteping</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-h</option> <option>--help</option>
+ </term>
+ <listitem>
+ <para>
+ Print usage screen.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+ <!--
+ <refsect1>
+ <title>BACKWARDS COMPATIBILITY</title>
+
+ <para>
+ This.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>ENVIRONMENT</title>
+ <para>
+ The.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>COPYRIGHT</title>
+ <para>
+ This.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>readburst</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>
+ </para>
+ </refsect1>
+ -->
+</refentry>
+
--- /dev/null
+<!ENTITY orte SYSTEM "ortedoc.xml">
+<!--<!ENTITY % ortepath "">-->
+
+<!ENTITY orte_summary SYSTEM "orte/orte_summary.xml">
+<!ENTITY orte_intro SYSTEM "orte/orte_intro.xml">
+<!ENTITY orte_api SYSTEM "orte/orte_api.xml">
+<!ENTITY orte_typedefs_api SYSTEM "orte/typedefs_api.xml">
+<!ENTITY orte_protos_api SYSTEM "orte/protos_api.xml">
+<!ENTITY orte_defines_api SYSTEM "orte/defines_api.xml">
+<!ENTITY orte_usage SYSTEM "orte/orte_usage.xml">
+<!ENTITY orte_ortemanager SYSTEM "orte/ortemanager.xml">
+<!ENTITY orte_orteping SYSTEM "orte/orteping.xml">
+<!ENTITY orte_ortespy SYSTEM "orte/ortespy.xml">
+<!ENTITY orte_ps_model SYSTEM "orte/orte_ps_model.xml">
+<!ENTITY orte_rtps_model SYSTEM "orte/orte_rtps_model.xml">
+<!ENTITY orte_examples SYSTEM "orte/orte_examples.xml">
+<!ENTITY orte_tests SYSTEM "orte/orte_tests.xml">
+<!ENTITY orte_internals SYSTEM "orte/orte_internals.xml">
+
+<!ENTITY orte_int_fig "%ortepath;/img/orte_int">
+<!ENTITY orte_anal_fig "%ortepath;/img/orte_analyzer">
+<!ENTITY orte_ps_model_img "%ortepath;/img/orte_ps_model">
+<!ENTITY orte_pub_arbitration_img "%ortepath;/img/orte_pub_arbitration">
+<!ENTITY orte_sub_issue_separation_img "%ortepath;/img/orte_sub_issue_separation">
+<!ENTITY orte_ps_architecture_img "%ortepath;/img/orte_ps_architecture">
+<!ENTITY orte_managers_img "%ortepath;/img/orte_managers">
+<!ENTITY orte_pub_snapshots_img "%ortepath;/img/orte_pub_snapshots">
+<!ENTITY orte_architecture_img "%ortepath;/img/orte_architecture">
+<!ENTITY orte_attributes_img "%ortepath;/img/orte_attributes">
+<!ENTITY orte_internal_architecture_img "%ortepath;/img/orte_internal_architecture">
+<!ENTITY orte_rtps_communication_img "%ortepath;/img/orte_rtps_communication">
+
+
--- /dev/null
+<?xml version='1.0'?>
+<chapter>
+ <title>Open Real-Time Ethernet</title>
+
+ <para>The Open Real-Time Ethernet (ORTE) is open source implementation of
+ RTPS communication protocol. RTPS is new application layer protocol
+ targeted to real-time communication area, which is build on the top of
+ standard UDP stack. Since there are many TCP/IP stack implementations
+ under many operating systems and RTPS protocol does not have any other
+ special HW/SW requirements, it should be easily ported to many HW/SW
+ target platforms. Because it uses only UDP protocol, it retains control of
+ timing and reliability.</para>
+
+ <section>
+ <title>ORTE Summary</title>
+
+ &orte_summary;
+ </section>
+
+ <section id="orte-description">
+ <title>ORTE Description</title>
+
+ &orte_intro;
+ &orte_ps_model;
+ &orte_rtps_model;
+ </section>
+
+ &orte_api;
+ &orte_internals;
+ &orte_examples;
+ &orte_tests;
+ &orte_usage;
+
+</chapter>
--- /dev/null
+<!ENTITY % ortepath ".">
+
+<!ENTITY % orte_entities SYSTEM "orte_incl.ent">
+
+%orte_entities
+
+
--- /dev/null
+<?xml version='1.0'?>
+<!DOCTYPE book PUBLIC "-//Norman Walsh//DTD DocBk XML V4.1.2//EN"
+ "/usr/share/xml/docbook/schema/dtd/4.4/docbookx.dtd"
+ [
+ <!ENTITY % entities SYSTEM "orteman.ent">
+ %entities;
+ <!-- Add other entries here -->
+ ]
+>
+<book lang="en">
+<!--
+<bookinfo>
+ <title>D7.4_rep - Communication Components</title>
+ <authorgroup>
+ <author>
+ <firstname>Jan</firstname>
+ <surname>Krakora</surname>
+ <affiliation>
+ <orgname>CTU</orgname>
+ </affiliation>
+ </author>
+ <author>
+ <firstname>Pavel</firstname>
+ <surname>Pisa</surname>
+ <affiliation>
+ <orgname>CTU</orgname>
+ </affiliation>
+ </author>
+ <author>
+ <firstname>Frantisek</firstname>
+ <surname>Vacek</surname>
+ <affiliation>
+ <orgname>CTU</orgname>
+ </affiliation>
+ </author>
+ <author>
+ <firstname>Zdenek</firstname>
+ <surname>Sebek</surname>
+ <affiliation>
+ <orgname>CTU</orgname>
+ </affiliation>
+ </author>
+ <author>
+ <firstname>Petr</firstname>
+ <surname>Smolik</surname>
+ <affiliation>
+ <orgname>CTU</orgname>
+ </affiliation>
+ </author>
+ <author>
+ <firstname>Zdenek</firstname>
+ <surname>Hanzalek</surname>
+ <affiliation>
+ <orgname>CTU</orgname>
+ </affiliation>
+ </author>
+ </authorgroup>
+ <pubdate>February 2004</pubdate>
+ <copyright>
+ <year>2004</year>
+ <holder>Ocera</holder>
+ </copyright>
+ <legalnotice>
+ <para>
+ You can (in fact you must!) use, modify, copy and distribute
+ this document, of course free of charge, and think about the
+ appropriate license we will use for the documentation.
+ </para>
+ </legalnotice>
+</bookinfo>
+
+<preface>
+ <title>Preface</title>
+ <para>
+ This document presents elaborated version of communication component design report.
+ It is composed of three chapters. The first and second chapters deal with design of communication
+ stacks - RT Ethernet or CAN/CANopen respectively including analysis tools. The third chapter
+ presents Basic features of verification methodology of distributed systems based on standard verification tools.
+ </para>
+</preface>
+-->
+
+<bookinfo>
+ <title>ORTE - Open Real-Time Ethernet</title>
+<!-- <authorgroup>
+ <author>
+ <firstname>Petr</firstname>
+ <surname>Smolik</surname>
+ <affiliation>
+ <orgname>CTU</orgname>
+ </affiliation>
+ </author>
+ </authorgroup>
+ <pubdate>November 2005</pubdate>
+ <copyright>
+ <year>2005</year>
+ <holder>MPO</holder>
+ </copyright>
+ <legalnotice>
+ <para>
+ You can (in fact you must!) use, modify, copy and distribute
+ this document, of course free of charge, and think about the
+ appropriate license we will use for the documentation.
+ </para>
+ </legalnotice>-->
+</bookinfo>
+
+&orte;
+<!-- Add other entries here -->
+
+</book>
--- /dev/null
+#!/usr/bin/perl -w
+
+use strict;
+
+## Copyright (c) 1998 Michael Zucchi, All Rights Reserved ##
+## Copyright (C) 2000, 1 Tim Waugh <twaugh@redhat.com> ##
+## Copyright (C) 2001 Simon Huggins ##
+## ##
+## #define enhancements by Armin Kuster <akuster@mvista.com> ##
+## Copyright (c) 2000 MontaVista Software, Inc. ##
+## ##
+## This software falls under the GNU General Public License. ##
+## Please read the COPYING file for more information ##
+
+# w.o. 03-11-2000: added the '-filelist' option.
+
+# 18/01/2001 - Cleanups
+# Functions prototyped as foo(void) same as foo()
+# Stop eval'ing where we don't need to.
+# -- huggie@earth.li
+
+# 27/06/2001 - Allowed whitespace after initial "/**" and
+# allowed comments before function declarations.
+# -- Christian Kreibich <ck@whoop.org>
+
+# Still to do:
+# - add perldoc documentation
+# - Look more closely at some of the scarier bits :)
+
+# 26/05/2001 - Support for separate source and object trees.
+# Return error code.
+# Keith Owens <kaos@ocs.com.au>
+
+# 23/09/2001 - Added support for typedefs, structs, enums and unions
+# Support for Context section; can be terminated using empty line
+# Small fixes (like spaces vs. \s in regex)
+# -- Tim Jansen <tim@tjansen.de>
+
+
+#
+# This will read a 'c' file and scan for embedded comments in the
+# style of gnome comments (+minor extensions - see below).
+#
+
+# Note: This only supports 'c'.
+
+# usage:
+# kerneldoc [ -docbook | -html | -text | -man ]
+# [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile
+# or
+# [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile
+#
+# Set output format using one of -docbook -html -text or -man. Default is man.
+#
+# -function funcname
+# If set, then only generate documentation for the given function(s). All
+# other functions are ignored.
+#
+# -nofunction funcname
+# If set, then only generate documentation for the other function(s). All
+# other functions are ignored. Cannot be used with -function together
+# (yes thats a bug - perl hackers can fix it 8))
+#
+# c files - list of 'c' files to process
+#
+# All output goes to stdout, with errors to stderr.
+
+#
+# format of comments.
+# In the following table, (...)? signifies optional structure.
+# (...)* signifies 0 or more structure elements
+# /**
+# * function_name(:)? (- short description)?
+# (* @parameterx: (description of parameter x)?)*
+# (* a blank line)?
+# * (Description:)? (Description of function)?
+# * (section header: (section description)? )*
+# (*)?*/
+#
+# So .. the trivial example would be:
+#
+# /**
+# * my_function
+# **/
+#
+# If the Description: header tag is ommitted, then there must be a blank line
+# after the last parameter specification.
+# e.g.
+# /**
+# * my_function - does my stuff
+# * @my_arg: its mine damnit
+# *
+# * Does my stuff explained.
+# */
+#
+# or, could also use:
+# /**
+# * my_function - does my stuff
+# * @my_arg: its mine damnit
+# * Description: Does my stuff explained.
+# */
+# etc.
+#
+# Beside functions you can also write documentation for structs, unions,
+# enums and typedefs. Instead of the function name you must write the name
+# of the declaration; the struct/union/enum/typedef must always precede
+# the name. Nesting of declarations is not supported.
+# Use the argument mechanism to document members or constants. In
+# structs and unions you must declare one member per declaration
+# (comma-separated members are not allowed - the parser does not support
+# this).
+# e.g.
+# /**
+# * struct my_struct - short description
+# * @a: first member
+# * @b: second member
+# *
+# * Longer description
+# */
+# struct my_struct {
+# int a;
+# int b;
+# };
+#
+# All descriptions can be multiline, except the short function description.
+#
+# You can also add additional sections. When documenting kernel functions you
+# should document the "Context:" of the function, e.g. whether the functions
+# can be called form interrupts. Unlike other sections you can end it with an
+# empty line.
+# Example-sections should contain the string EXAMPLE so that they are marked
+# appropriately in DocBook.
+#
+# Example:
+# /**
+# * user_function - function that can only be called in user context
+# * @a: some argument
+# * Context: !in_interrupt()
+# *
+# * Some description
+# * Example:
+# * user_function(22);
+# */
+# ...
+#
+#
+# All descriptive text is further processed, scanning for the following special
+# patterns, which are highlighted appropriately.
+#
+# 'funcname()' - function
+# '$ENVVAR' - environmental variable
+# '&struct_name' - name of a structure (up to two words including 'struct')
+# '@parameter' - name of a parameter
+# '%CONST' - name of a constant.
+
+my $errors = 0;
+my $warnings = 0;
+
+# match expressions used to find embedded type information
+my $type_constant = '\%([-_\w]+)';
+my $type_func = '(\w+)\(\)';
+my $type_param = '\@(\w+)';
+my $type_struct = '\&((struct\s*)?[_\w]+)';
+my $type_env = '(\$\w+)';
+
+# Output conversion substitutions.
+# One for each output format
+
+# these work fairly well
+my %highlights_html = ( $type_constant, "<i>\$1</i>",
+ $type_func, "<b>\$1</b>",
+ $type_struct, "<i>\$1</i>",
+ $type_param, "<tt><b>\$1</b></tt>" );
+my $blankline_html = "<p>";
+
+# sgml, docbook format
+my %highlights_sgml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>",
+ $type_constant, "<constant>\$1</constant>",
+ $type_func, "<function>\$1</function>",
+ $type_struct, "<structname>\$1</structname>",
+ $type_env, "<envar>\$1</envar>",
+ $type_param, "<parameter>\$1</parameter>" );
+my $blankline_sgml = "</para><para>\n";
+
+# gnome, docbook format
+my %highlights_gnome = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>",
+ $type_func, "<function>\$1</function>",
+ $type_struct, "<structname>\$1</structname>",
+ $type_env, "<envar>\$1</envar>",
+ $type_param, "<parameter>\$1</parameter>" );
+my $blankline_gnome = "</para><para>\n";
+
+# these are pretty rough
+my %highlights_man = ( $type_constant, "\$1",
+ $type_func, "\\\\fB\$1\\\\fP",
+ $type_struct, "\\\\fI\$1\\\\fP",
+ $type_param, "\\\\fI\$1\\\\fP" );
+my $blankline_man = "";
+
+# text-mode
+my %highlights_text = ( $type_constant, "\$1",
+ $type_func, "\$1",
+ $type_struct, "\$1",
+ $type_param, "\$1" );
+my $blankline_text = "";
+
+
+sub usage {
+ print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ]\n";
+ print " [ -function funcname [ -function funcname ...] ]\n";
+ print " [ -nofunction funcname [ -nofunction funcname ...] ]\n";
+ print " c source file(s) > outputfile\n";
+ exit 1;
+}
+
+# read arguments
+if ($#ARGV==-1) {
+ usage();
+}
+
+my $verbose = 0;
+my $output_mode = "man";
+my %highlights = %highlights_man;
+my $blankline = $blankline_man;
+my $modulename = "Kernel API";
+my $function_only = 0;
+my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
+ 'July', 'August', 'September', 'October',
+ 'November', 'December')[(localtime)[4]] .
+ " " . ((localtime)[5]+1900);
+
+# Essentially these are globals
+# They probably want to be tidied up made more localised or summat.
+# CAVEAT EMPTOR! Some of the others I localised may not want to be which
+# could cause "use of undefined value" or other bugs.
+my ($function, %function_table,%parametertypes,$declaration_purpose);
+my ($type,$declaration_name,$return_type);
+my ($newsection,$newcontents,$prototype,$filelist, $brcount, %source_map);
+
+# Generated docbook code is inserted in a template at a point where
+# docbook v3.1 requires a non-zero sequence of RefEntry's; see:
+# http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html
+# We keep track of number of generated entries and generate a dummy
+# if needs be to ensure the expanded template can be postprocessed
+# into html.
+my $section_counter = 0;
+
+my $lineprefix="";
+
+# states
+# 0 - normal code
+# 1 - looking for function name
+# 2 - scanning field start.
+# 3 - scanning prototype.
+# 4 - documentation block
+my $state;
+
+#declaration types: can be
+# 'function', 'struct', 'union', 'enum', 'typedef'
+my $decl_type;
+
+my $doc_special = "\@\%\$\&";
+
+my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
+my $doc_end = '\*/';
+my $doc_com = '\s*\*\s*';
+my $doc_decl = $doc_com.'(\w+)';
+my $doc_sect = $doc_com.'(['.$doc_special.']?[\w ]+):(.*)';
+my $doc_content = $doc_com.'(.*)';
+my $doc_block = $doc_com.'DOC:\s*(.*)?';
+
+my %constants;
+my %parameterdescs;
+my @parameterlist;
+my %sections;
+my @sectionlist;
+
+my $contents = "";
+my $section_default = "Description"; # default section
+my $section_intro = "Introduction";
+my $section = $section_default;
+my $section_context = "Context";
+
+my $undescribed = "-- undescribed --";
+
+reset_state();
+
+while ($ARGV[0] =~ m/^-(.*)/) {
+ my $cmd = shift @ARGV;
+ if ($cmd eq "-html") {
+ $output_mode = "html";
+ %highlights = %highlights_html;
+ $blankline = $blankline_html;
+ } elsif ($cmd eq "-man") {
+ $output_mode = "man";
+ %highlights = %highlights_man;
+ $blankline = $blankline_man;
+ } elsif ($cmd eq "-text") {
+ $output_mode = "text";
+ %highlights = %highlights_text;
+ $blankline = $blankline_text;
+ } elsif ($cmd eq "-docbook") {
+ $output_mode = "sgml";
+ %highlights = %highlights_sgml;
+ $blankline = $blankline_sgml;
+ } elsif ($cmd eq "-gnome") {
+ $output_mode = "gnome";
+ %highlights = %highlights_gnome;
+ $blankline = $blankline_gnome;
+ } elsif ($cmd eq "-module") { # not needed for sgml, inherits from calling document
+ $modulename = shift @ARGV;
+ } elsif ($cmd eq "-function") { # to only output specific functions
+ $function_only = 1;
+ $function = shift @ARGV;
+ $function_table{$function} = 1;
+ } elsif ($cmd eq "-nofunction") { # to only output specific functions
+ $function_only = 2;
+ $function = shift @ARGV;
+ $function_table{$function} = 1;
+ } elsif ($cmd eq "-v") {
+ $verbose = 1;
+ } elsif (($cmd eq "-h") || ($cmd eq "--help")) {
+ usage();
+ } elsif ($cmd eq '-filelist') {
+ $filelist = shift @ARGV;
+ }
+}
+
+
+# generate a sequence of code that will splice in highlighting information
+# using the s// operator.
+my $dohighlight = "";
+foreach my $pattern (keys %highlights) {
+# print "scanning pattern $pattern ($highlights{$pattern})\n";
+ $dohighlight .= "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
+}
+
+##
+# dumps section contents to arrays/hashes intended for that purpose.
+#
+sub dump_section {
+ my $name = shift;
+ my $contents = join "\n", @_;
+
+ if ($name =~ m/$type_constant/) {
+ $name = $1;
+# print STDERR "constant section '$1' = '$contents'\n";
+ $constants{$name} = $contents;
+ } elsif ($name =~ m/$type_param/) {
+# print STDERR "parameter def '$1' = '$contents'\n";
+ $name = $1;
+ $parameterdescs{$name} = $contents;
+ } else {
+# print STDERR "other section '$name' = '$contents'\n";
+ $sections{$name} = $contents;
+ push @sectionlist, $name;
+ }
+}
+
+##
+# output function
+#
+# parameterdescs, a hash.
+# function => "function name"
+# parameterlist => @list of parameters
+# parameterdescs => %parameter descriptions
+# sectionlist => @list of sections
+# sections => %descriont descriptions
+#
+
+sub output_highlight {
+ my $contents = join "\n",@_;
+ my $line;
+
+# DEBUG
+# if (!defined $contents) {
+# use Carp;
+# confess "output_highlight got called with no args?\n";
+# }
+
+ eval $dohighlight;
+ die $@ if $@;
+ foreach $line (split "\n", $contents) {
+ if ($line eq ""){
+ print $lineprefix, $blankline;
+ } else {
+ $line =~ s/\\\\\\/\&/g;
+ print $lineprefix, $line;
+ }
+ print "\n";
+ }
+}
+
+#output sections in html
+sub output_section_html(%) {
+ my %args = %{$_[0]};
+ my $section;
+
+ foreach $section (@{$args{'sectionlist'}}) {
+ print "<h3>$section</h3>\n";
+ print "<blockquote>\n";
+ output_highlight($args{'sections'}{$section});
+ print "</blockquote>\n";
+ }
+}
+
+# output enum in html
+sub output_enum_html(%) {
+ my %args = %{$_[0]};
+ my ($parameter);
+ my $count;
+ print "<h2>enum ".$args{'enum'}."</h2>\n";
+
+ print "<b>enum ".$args{'enum'}."</b> {<br>\n";
+ $count = 0;
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print " <b>".$parameter."</b>";
+ if ($count != $#{$args{'parameterlist'}}) {
+ $count++;
+ print ",\n";
+ }
+ print "<br>";
+ }
+ print "};<br>\n";
+
+ print "<h3>Constants</h3>\n";
+ print "<dl>\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print "<dt><b>".$parameter."</b>\n";
+ print "<dd>";
+ output_highlight($args{'parameterdescs'}{$parameter});
+ }
+ print "</dl>\n";
+ output_section_html(@_);
+ print "<hr>\n";
+}
+
+# output tyepdef in html
+sub output_typedef_html(%) {
+ my %args = %{$_[0]};
+ my ($parameter);
+ my $count;
+ print "<h2>typedef ".$args{'typedef'}."</h2>\n";
+
+ print "<b>typedef ".$args{'typedef'}."</b>\n";
+ output_section_html(@_);
+ print "<hr>\n";
+}
+
+# output struct in html
+sub output_struct_html(%) {
+ my %args = %{$_[0]};
+ my ($parameter);
+
+ print "<h2>".$args{'type'}." ".$args{'struct'}."</h2>\n";
+ print "<b>".$args{'type'}." ".$args{'struct'}."</b> {<br>\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
+ $type = $args{'parametertypes'}{$parameter};
+ if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+ # pointer-to-function
+ print " <i>$1</i><b>$parameter</b>) <i>($2)</i>;<br>\n";
+ } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
+ print " <i>$1</i> <b>$parameter</b>$2;<br>\n";
+ } else {
+ print " <i>$type</i> <b>$parameter</b>;<br>\n";
+ }
+ }
+ print "};<br>\n";
+
+ print "<h3>Members</h3>\n";
+ print "<dl>\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
+ print "<dt><b>".$parameter."</b>\n";
+ print "<dd>";
+ output_highlight($args{'parameterdescs'}{$parameter});
+ }
+ print "</dl>\n";
+ output_section_html(@_);
+ print "<hr>\n";
+}
+
+# output function in html
+sub output_function_html(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+ print "<h2>Function</h2>\n";
+
+ print "<i>".$args{'functiontype'}."</i>\n";
+ print "<b>".$args{'function'}."</b>\n";
+ print "(";
+ $count = 0;
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ $type = $args{'parametertypes'}{$parameter};
+ if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+ # pointer-to-function
+ print "<i>$1</i><b>$parameter</b>) <i>($2)</i>";
+ } else {
+ print "<i>".$type."</i> <b>".$parameter."</b>";
+ }
+ if ($count != $#{$args{'parameterlist'}}) {
+ $count++;
+ print ",\n";
+ }
+ }
+ print ")\n";
+
+ print "<h3>Arguments</h3>\n";
+ print "<dl>\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
+ print "<dt><b>".$parameter."</b>\n";
+ print "<dd>";
+ output_highlight($args{'parameterdescs'}{$parameter});
+ }
+ print "</dl>\n";
+ output_section_html(@_);
+ print "<hr>\n";
+}
+
+# output intro in html
+sub output_intro_html(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+
+ foreach $section (@{$args{'sectionlist'}}) {
+ print "<h3>$section</h3>\n";
+ print "<ul>\n";
+ output_highlight($args{'sections'}{$section});
+ print "</ul>\n";
+ }
+ print "<hr>\n";
+}
+
+sub output_section_sgml(%) {
+ my %args = %{$_[0]};
+ my $section;
+ # print out each section
+ $lineprefix=" ";
+ foreach $section (@{$args{'sectionlist'}}) {
+ print "<refsect1>\n <title>$section</title>\n <para>\n";
+ if ($section =~ m/EXAMPLE/i) {
+ print "<example><para>\n";
+ }
+ output_highlight($args{'sections'}{$section});
+ if ($section =~ m/EXAMPLE/i) {
+ print "</para></example>\n";
+ }
+ print " </para>\n</refsect1>\n";
+ }
+}
+
+# output function in sgml DocBook
+sub output_function_sgml(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+ my $id;
+
+ $id = "API-".$args{'function'};
+ $id =~ s/[^A-Za-z0-9]/-/g;
+
+ print "<refentry>\n";
+ print "<refmeta>\n";
+ print "<refentrytitle><phrase id=\"$id\">".$args{'function'}."</phrase></refentrytitle>\n";
+ print "</refmeta>\n";
+ print "<refnamediv>\n";
+ print " <refname>".$args{'function'}."</refname>\n";
+ print " <refpurpose>\n";
+ print " ";
+ output_highlight ($args{'purpose'});
+ print " </refpurpose>\n";
+ print "</refnamediv>\n";
+
+ print "<refsynopsisdiv>\n";
+ print " <title>Synopsis</title>\n";
+ print " <funcsynopsis><funcprototype>\n";
+ print " <funcdef>".$args{'functiontype'}." ";
+ print "<function>".$args{'function'}." </function></funcdef>\n";
+
+ $count = 0;
+ if ($#{$args{'parameterlist'}} >= 0) {
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ $type = $args{'parametertypes'}{$parameter};
+ if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+ # pointer-to-function
+ print " <paramdef>$1<parameter>$parameter</parameter>)\n";
+ print " <funcparams>$2</funcparams></paramdef>\n";
+ } else {
+ print " <paramdef>".$type;
+ print " <parameter>$parameter</parameter></paramdef>\n";
+ }
+ }
+ } else {
+ print " <void>\n";
+ }
+ print " </funcprototype></funcsynopsis>\n";
+ print "</refsynopsisdiv>\n";
+
+ # print parameters
+ print "<refsect1>\n <title>Arguments</title>\n";
+ if ($#{$args{'parameterlist'}} >= 0) {
+ print " <variablelist>\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print " <varlistentry>\n <term><parameter>$parameter</parameter></term>\n";
+ print " <listitem>\n <para>\n";
+ $lineprefix=" ";
+ output_highlight($args{'parameterdescs'}{$parameter});
+ print " </para>\n </listitem>\n </varlistentry>\n";
+ }
+ print " </variablelist>\n";
+ } else {
+ print " <para>\n None\n </para>\n";
+ }
+ print "</refsect1>\n";
+
+ output_section_sgml(@_);
+ print "</refentry>\n\n";
+}
+
+# output struct in sgml DocBook
+sub output_struct_sgml(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $id;
+
+ $id = "API-struct-".$args{'struct'};
+ $id =~ s/[^A-Za-z0-9]/-/g;
+
+ print "<refentry>\n";
+ print "<refmeta>\n";
+ print "<refentrytitle><phrase id=\"$id\">".$args{'type'}." ".$args{'struct'}."</phrase></refentrytitle>\n";
+ print "</refmeta>\n";
+ print "<refnamediv>\n";
+ print " <refname>".$args{'type'}." ".$args{'struct'}."</refname>\n";
+ print " <refpurpose>\n";
+ print " ";
+ output_highlight ($args{'purpose'});
+ print " </refpurpose>\n";
+ print "</refnamediv>\n";
+
+ print "<refsynopsisdiv>\n";
+ print " <title>Synopsis</title>\n";
+ print " <programlisting>\n";
+ print $args{'type'}." ".$args{'struct'}." {\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ defined($args{'parameterdescs'}{$parameter}) || next;
+ ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
+ $type = $args{'parametertypes'}{$parameter};
+ if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+ # pointer-to-function
+ print " $1 $parameter ($2);\n";
+ } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
+ print " $1 $parameter$2;\n";
+ } else {
+ print " ".$type." ".$parameter.";\n";
+ }
+ }
+ print "};";
+ print " </programlisting>\n";
+ print "</refsynopsisdiv>\n";
+
+ print " <refsect1>\n";
+ print " <title>Members</title>\n";
+
+ print " <variablelist>\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ defined($args{'parameterdescs'}{$parameter}) || next;
+ ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
+ print " <varlistentry>";
+ print " <term>$parameter</term>\n";
+ print " <listitem><para>\n";
+ output_highlight($args{'parameterdescs'}{$parameter});
+ print " </para></listitem>\n";
+ print " </varlistentry>\n";
+ }
+ print " </variablelist>\n";
+ print " </refsect1>\n";
+
+ output_section_sgml(@_);
+
+ print "</refentry>\n\n";
+}
+
+# output enum in sgml DocBook
+sub output_enum_sgml(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+ my $id;
+
+ $id = "API-enum-".$args{'enum'};
+ $id =~ s/[^A-Za-z0-9]/-/g;
+
+ print "<refentry>\n";
+ print "<refmeta>\n";
+ print "<refentrytitle><phrase id=\"$id\">enum ".$args{'enum'}."</phrase></refentrytitle>\n";
+ print "</refmeta>\n";
+ print "<refnamediv>\n";
+ print " <refname>enum ".$args{'enum'}."</refname>\n";
+ print " <refpurpose>\n";
+ print " ";
+ output_highlight ($args{'purpose'});
+ print " </refpurpose>\n";
+ print "</refnamediv>\n";
+
+ print "<refsynopsisdiv>\n";
+ print " <title>Synopsis</title>\n";
+ print " <programlisting>\n";
+ print "enum ".$args{'enum'}." {\n";
+ $count = 0;
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print " $parameter";
+ if ($count != $#{$args{'parameterlist'}}) {
+ $count++;
+ print ",";
+ }
+ print "\n";
+ }
+ print "};";
+ print " </programlisting>\n";
+ print "</refsynopsisdiv>\n";
+
+ print "<refsect1>\n";
+ print " <title>Constants</title>\n";
+ print " <variablelist>\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print " <varlistentry>";
+ print " <term>$parameter</term>\n";
+ print " <listitem><para>\n";
+ output_highlight($args{'parameterdescs'}{$parameter});
+ print " </para></listitem>\n";
+ print " </varlistentry>\n";
+ }
+ print " </variablelist>\n";
+ print "</refsect1>\n";
+
+ output_section_sgml(@_);
+
+ print "</refentry>\n\n";
+}
+
+# output typedef in sgml DocBook
+sub output_typedef_sgml(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $id;
+
+ $id = "API-typedef-".$args{'typedef'};
+ $id =~ s/[^A-Za-z0-9]/-/g;
+
+ print "<refentry>\n";
+ print "<refmeta>\n";
+ print "<refentrytitle><phrase id=\"$id\">typedef ".$args{'typedef'}."</phrase></refentrytitle>\n";
+ print "</refmeta>\n";
+ print "<refnamediv>\n";
+ print " <refname>typedef ".$args{'typedef'}."</refname>\n";
+ print " <refpurpose>\n";
+ print " ";
+ output_highlight ($args{'purpose'});
+ print " </refpurpose>\n";
+ print "</refnamediv>\n";
+
+ print "<refsynopsisdiv>\n";
+ print " <title>Synopsis</title>\n";
+ print " <synopsis>typedef ".$args{'typedef'}.";</synopsis>\n";
+ print "</refsynopsisdiv>\n";
+
+ output_section_sgml(@_);
+
+ print "</refentry>\n\n";
+}
+
+# output in sgml DocBook
+sub output_intro_sgml(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+
+ my $id = $args{'module'};
+ $id =~ s/[^A-Za-z0-9]/-/g;
+
+ # print out each section
+ $lineprefix=" ";
+ foreach $section (@{$args{'sectionlist'}}) {
+ print "<refsect1>\n <title>$section</title>\n <para>\n";
+ if ($section =~ m/EXAMPLE/i) {
+ print "<example><para>\n";
+ }
+ output_highlight($args{'sections'}{$section});
+ if ($section =~ m/EXAMPLE/i) {
+ print "</para></example>\n";
+ }
+ print " </para>\n</refsect1>\n";
+ }
+
+ print "\n\n";
+}
+
+# output in sgml DocBook
+sub output_function_gnome {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+ my $id;
+
+ $id = $args{'module'}."-".$args{'function'};
+ $id =~ s/[^A-Za-z0-9]/-/g;
+
+ print "<sect2>\n";
+ print " <title id=\"$id\">".$args{'function'}."</title>\n";
+
+ print " <funcsynopsis>\n";
+ print " <funcdef>".$args{'functiontype'}." ";
+ print "<function>".$args{'function'}." ";
+ print "</function></funcdef>\n";
+
+ $count = 0;
+ if ($#{$args{'parameterlist'}} >= 0) {
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ $type = $args{'parametertypes'}{$parameter};
+ if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+ # pointer-to-function
+ print " <paramdef>$1 <parameter>$parameter</parameter>)\n";
+ print " <funcparams>$2</funcparams></paramdef>\n";
+ } else {
+ print " <paramdef>".$type;
+ print " <parameter>$parameter</parameter></paramdef>\n";
+ }
+ }
+ } else {
+ print " <void>\n";
+ }
+ print " </funcsynopsis>\n";
+ if ($#{$args{'parameterlist'}} >= 0) {
+ print " <informaltable pgwide=\"1\" frame=\"none\" role=\"params\">\n";
+ print "<tgroup cols=\"2\">\n";
+ print "<colspec colwidth=\"2*\">\n";
+ print "<colspec colwidth=\"8*\">\n";
+ print "<tbody>\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print " <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n";
+ print " <entry>\n";
+ $lineprefix=" ";
+ output_highlight($args{'parameterdescs'}{$parameter});
+ print " </entry></row>\n";
+ }
+ print " </tbody></tgroup></informaltable>\n";
+ } else {
+ print " <para>\n None\n </para>\n";
+ }
+
+ # print out each section
+ $lineprefix=" ";
+ foreach $section (@{$args{'sectionlist'}}) {
+ print "<simplesect>\n <title>$section</title>\n";
+ if ($section =~ m/EXAMPLE/i) {
+ print "<example><programlisting>\n";
+ } else {
+ }
+ print "<para>\n";
+ output_highlight($args{'sections'}{$section});
+ print "</para>\n";
+ if ($section =~ m/EXAMPLE/i) {
+ print "</programlisting></example>\n";
+ } else {
+ }
+ print " </simplesect>\n";
+ }
+
+ print "</sect2>\n\n";
+}
+
+##
+# output function in man
+sub output_function_man(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+
+ print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Kernel Hacker's Manual\" LINUX\n";
+
+ print ".SH NAME\n";
+ print $args{'function'}." \\- ".$args{'purpose'}."\n";
+
+ print ".SH SYNOPSIS\n";
+ print ".B \"".$args{'functiontype'}."\" ".$args{'function'}."\n";
+ $count = 0;
+ my $parenth = "(";
+ my $post = ",";
+ foreach my $parameter (@{$args{'parameterlist'}}) {
+ if ($count == $#{$args{'parameterlist'}}) {
+ $post = ");";
+ }
+ $type = $args{'parametertypes'}{$parameter};
+ if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+ # pointer-to-function
+ print ".BI \"".$parenth.$1."\" ".$parameter." \") (".$2.")".$post."\"\n";
+ } else {
+ $type =~ s/([^\*])$/$1 /;
+ print ".BI \"".$parenth.$type."\" ".$parameter." \"".$post."\"\n";
+ }
+ $count++;
+ $parenth = "";
+ }
+
+ print ".SH ARGUMENTS\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print ".IP \"".$parameter."\" 12\n";
+ output_highlight($args{'parameterdescs'}{$parameter});
+ }
+ foreach $section (@{$args{'sectionlist'}}) {
+ print ".SH \"", uc $section, "\"\n";
+ output_highlight($args{'sections'}{$section});
+ }
+}
+
+##
+# output enum in man
+sub output_enum_man(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+
+ print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n";
+
+ print ".SH NAME\n";
+ print "enum ".$args{'enum'}." \\- ".$args{'purpose'}."\n";
+
+ print ".SH SYNOPSIS\n";
+ print "enum ".$args{'enum'}." {\n";
+ $count = 0;
+ foreach my $parameter (@{$args{'parameterlist'}}) {
+ print ".br\n.BI \" $parameter\"\n";
+ if ($count == $#{$args{'parameterlist'}}) {
+ print "\n};\n";
+ last;
+ }
+ else {
+ print ", \n.br\n";
+ }
+ $count++;
+ }
+
+ print ".SH Constants\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print ".IP \"".$parameter."\" 12\n";
+ output_highlight($args{'parameterdescs'}{$parameter});
+ }
+ foreach $section (@{$args{'sectionlist'}}) {
+ print ".SH \"$section\"\n";
+ output_highlight($args{'sections'}{$section});
+ }
+}
+
+##
+# output struct in man
+sub output_struct_man(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+
+ print ".TH \"$args{'module'}\" 9 \"".$args{'type'}." ".$args{'struct'}."\" \"$man_date\" \"API Manual\" LINUX\n";
+
+ print ".SH NAME\n";
+ print $args{'type'}." ".$args{'struct'}." \\- ".$args{'purpose'}."\n";
+
+ print ".SH SYNOPSIS\n";
+ print $args{'type'}." ".$args{'struct'}." {\n";
+
+ foreach my $parameter (@{$args{'parameterlist'}}) {
+ ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
+ print "\n.br\n";
+ $type = $args{'parametertypes'}{$parameter};
+ if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+ # pointer-to-function
+ print ".BI \" ".$1."\" ".$parameter." \") (".$2.")"."\"\n;\n";
+ } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
+ print ".BI \" ".$1."\" ".$parameter.$2." \""."\"\n;\n";
+ } else {
+ $type =~ s/([^\*])$/$1 /;
+ print ".BI \" ".$type."\" ".$parameter." \""."\"\n;\n";
+ }
+ print "\n.br\n";
+ }
+ print "};\n.br\n";
+
+ print ".SH Arguments\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
+ print ".IP \"".$parameter."\" 12\n";
+ output_highlight($args{'parameterdescs'}{$parameter});
+ }
+ foreach $section (@{$args{'sectionlist'}}) {
+ print ".SH \"$section\"\n";
+ output_highlight($args{'sections'}{$section});
+ }
+}
+
+##
+# output typedef in man
+sub output_typedef_man(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+
+ print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n";
+
+ print ".SH NAME\n";
+ print "typedef ".$args{'typedef'}." \\- ".$args{'purpose'}."\n";
+
+ foreach $section (@{$args{'sectionlist'}}) {
+ print ".SH \"$section\"\n";
+ output_highlight($args{'sections'}{$section});
+ }
+}
+
+sub output_intro_man(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+
+ print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n";
+
+ foreach $section (@{$args{'sectionlist'}}) {
+ print ".SH \"$section\"\n";
+ output_highlight($args{'sections'}{$section});
+ }
+}
+
+##
+# output in text
+sub output_function_text(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+
+ print "Function:\n\n";
+ my $start=$args{'functiontype'}." ".$args{'function'}." (";
+ print $start;
+ my $count = 0;
+ foreach my $parameter (@{$args{'parameterlist'}}) {
+ $type = $args{'parametertypes'}{$parameter};
+ if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+ # pointer-to-function
+ print $1.$parameter.") (".$2;
+ } else {
+ print $type." ".$parameter;
+ }
+ if ($count != $#{$args{'parameterlist'}}) {
+ $count++;
+ print ",\n";
+ print " " x length($start);
+ } else {
+ print ");\n\n";
+ }
+ }
+
+ print "Arguments:\n\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print $parameter."\n\t".$args{'parameterdescs'}{$parameter}."\n";
+ }
+ output_section_text(@_);
+}
+
+#output sections in text
+sub output_section_text(%) {
+ my %args = %{$_[0]};
+ my $section;
+
+ print "\n";
+ foreach $section (@{$args{'sectionlist'}}) {
+ print "$section:\n\n";
+ output_highlight($args{'sections'}{$section});
+ }
+ print "\n\n";
+}
+
+# output enum in text
+sub output_enum_text(%) {
+ my %args = %{$_[0]};
+ my ($parameter);
+ my $count;
+ print "Enum:\n\n";
+
+ print "enum ".$args{'enum'}." {\n";
+ $count = 0;
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print "\t$parameter";
+ if ($count != $#{$args{'parameterlist'}}) {
+ $count++;
+ print ",";
+ }
+ print "\n";
+ }
+ print "};\n\n";
+
+ print "Constants:\n\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print "$parameter\n\t";
+ print $args{'parameterdescs'}{$parameter}."\n";
+ }
+
+ output_section_text(@_);
+}
+
+# output typedef in text
+sub output_typedef_text(%) {
+ my %args = %{$_[0]};
+ my ($parameter);
+ my $count;
+ print "Typedef:\n\n";
+
+ print "typedef ".$args{'typedef'}."\n";
+ output_section_text(@_);
+}
+
+# output struct as text
+sub output_struct_text(%) {
+ my %args = %{$_[0]};
+ my ($parameter);
+
+ print $args{'type'}." ".$args{'struct'}.":\n\n";
+ print $args{'type'}." ".$args{'struct'}." {\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
+ $type = $args{'parametertypes'}{$parameter};
+ if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+ # pointer-to-function
+ print "\t$1 $parameter) ($2);\n";
+ } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
+ print "\t$1 $parameter$2;\n";
+ } else {
+ print "\t".$type." ".$parameter.";\n";
+ }
+ }
+ print "};\n\n";
+
+ print "Members:\n\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
+ print "$parameter\n\t";
+ print $args{'parameterdescs'}{$parameter}."\n";
+ }
+ print "\n";
+ output_section_text(@_);
+}
+
+sub output_intro_text(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+
+ foreach $section (@{$args{'sectionlist'}}) {
+ print " $section:\n";
+ print " -> ";
+ output_highlight($args{'sections'}{$section});
+ }
+}
+
+##
+# generic output function for typedefs
+sub output_declaration {
+ no strict 'refs';
+ my $name = shift;
+ my $functype = shift;
+ my $func = "output_${functype}_$output_mode";
+ if (($function_only==0) ||
+ ( $function_only == 1 && defined($function_table{$name})) ||
+ ( $function_only == 2 && !defined($function_table{$name})))
+ {
+ &$func(@_);
+ $section_counter++;
+ }
+}
+
+##
+# generic output function - calls the right one based
+# on current output mode.
+sub output_intro {
+ no strict 'refs';
+ my $func = "output_intro_".$output_mode;
+ &$func(@_);
+ $section_counter++;
+}
+
+##
+# takes a declaration (struct, union, enum, typedef) and
+# invokes the right handler. NOT called for functions.
+sub dump_declaration($$) {
+ no strict 'refs';
+ my ($prototype, $file) = @_;
+ my $func = "dump_".$decl_type;
+ &$func(@_);
+}
+
+sub dump_union($$) {
+ dump_struct(@_);
+}
+
+sub dump_struct($$) {
+ my $x = shift;
+ my $file = shift;
+
+ if ($x =~/(struct|union)\s+(\w+)\s*{(.*)}/) {
+ $declaration_name = $2;
+ my $members = $3;
+
+ # ignore embedded structs or unions
+ $members =~ s/{.*}//g;
+
+ create_parameterlist($members, ';', $file);
+
+ output_declaration($declaration_name,
+ 'struct',
+ {'struct' => $declaration_name,
+ 'module' => $modulename,
+ 'parameterlist' => \@parameterlist,
+ 'parameterdescs' => \%parameterdescs,
+ 'parametertypes' => \%parametertypes,
+ 'sectionlist' => \@sectionlist,
+ 'sections' => \%sections,
+ 'purpose' => $declaration_purpose,
+ 'type' => $decl_type
+ });
+ }
+ else {
+ print STDERR "Error(${file}:$.): Cannot parse struct or union!\n";
+ ++$errors;
+ }
+}
+
+sub dump_enum($$) {
+ my $x = shift;
+ my $file = shift;
+
+ if ($x =~ /enum\s+(\w+)\s*{(.*)}/) {
+ $declaration_name = $1;
+ my $members = $2;
+
+ foreach my $arg (split ',', $members) {
+ $arg =~ s/^\s*(\w+).*/$1/;
+ push @parameterlist, $arg;
+ if (!$parameterdescs{$arg}) {
+ $parameterdescs{$arg} = $undescribed;
+ print STDERR "Warning(${file}:$.): Enum value '$arg' ".
+ "not described in enum '$declaration_name'\n";
+ }
+
+ }
+
+ output_declaration($declaration_name,
+ 'enum',
+ {'enum' => $declaration_name,
+ 'module' => $modulename,
+ 'parameterlist' => \@parameterlist,
+ 'parameterdescs' => \%parameterdescs,
+ 'sectionlist' => \@sectionlist,
+ 'sections' => \%sections,
+ 'purpose' => $declaration_purpose
+ });
+ }
+ else {
+ print STDERR "Error(${file}:$.): Cannot parse enum!\n";
+ ++$errors;
+ }
+}
+
+sub dump_typedef($$) {
+ my $x = shift;
+ my $file = shift;
+
+ while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
+ $x =~ s/\(*.\)\s*;$/;/;
+ $x =~ s/\[*.\]\s*;$/;/;
+ }
+
+ if ($x =~ /typedef.*\s+(\w+)\s*;/) {
+ $declaration_name = $1;
+
+ output_declaration($declaration_name,
+ 'typedef',
+ {'typedef' => $declaration_name,
+ 'module' => $modulename,
+ 'sectionlist' => \@sectionlist,
+ 'sections' => \%sections,
+ 'purpose' => $declaration_purpose
+ });
+ }
+ else {
+ print STDERR "Error(${file}:$.): Cannot parse typedef!\n";
+ ++$errors;
+ }
+}
+
+sub create_parameterlist($$$) {
+ my $args = shift;
+ my $splitter = shift;
+ my $file = shift;
+ my $type;
+ my $param;
+
+ while ($args =~ /(\([^\),]+),/) {
+ $args =~ s/(\([^\),]+),/$1#/g;
+ }
+
+ foreach my $arg (split($splitter, $args)) {
+ # strip leading/trailing spaces
+ $arg =~ s/^\s*//;
+ $arg =~ s/\s*$//;
+ $arg =~ s/\s+/ /;
+
+ if ($arg =~ m/\(/) {
+ # pointer-to-function
+ $arg =~ tr/#/,/;
+ $arg =~ m/[^\(]+\(\*([^\)]+)\)/;
+ $param = $1;
+ $type = $arg;
+ $type =~ s/([^\(]+\(\*)$param/$1/;
+ } else {
+ # evil magic to get fixed array parameters to work
+ $arg =~ s/(.+\s+)(.+)\[.*/$1* $2/;
+ my @args = split('\s', $arg);
+
+ $param = pop @args;
+ if ($param =~ m/^(\*+)(.*)/) {
+ $param = $2;
+ push @args, $1;
+ }
+ elsif ($param =~ m/(.*?)\s*:\s*(\d+)/) {
+ $param = $1;
+ push @args, ":$2";
+ }
+ $type = join " ", @args;
+ }
+
+ if ($type eq "" && $param eq "...")
+ {
+ $type="...";
+ $param="...";
+ $parameterdescs{"..."} = "variable arguments";
+ }
+ elsif ($type eq "" && ($param eq "" or $param eq "void"))
+ {
+ $type="";
+ $param="void";
+ $parameterdescs{void} = "no arguments";
+ }
+ if (defined $type && $type && !defined $parameterdescs{$param}) {
+ $parameterdescs{$param} = $undescribed;
+
+ if (($type eq 'function') || ($type eq 'enum')) {
+ print STDERR "Warning(${file}:$.): Function parameter ".
+ "or member '$param' not " .
+ "described in '$declaration_name'\n";
+ }
+ print STDERR "Warning(${file}:$.): omitted parameter '$param'\n";
+ ++$warnings;
+ }
+
+ push @parameterlist, $param;
+ $parametertypes{$param} = $type;
+ }
+}
+
+##
+# takes a function prototype and the name of the current file being
+# processed and spits out all the details stored in the global
+# arrays/hashes.
+sub dump_function($$) {
+ my $prototype = shift;
+ my $file = shift;
+
+ $prototype =~ s/^static +//;
+ $prototype =~ s/^extern +//;
+ $prototype =~ s/^inline +//;
+ $prototype =~ s/^__inline__ +//;
+ $prototype =~ s/^#define +//; #ak added
+
+ # Yes, this truly is vile. We are looking for:
+ # 1. Return type (may be nothing if we're looking at a macro)
+ # 2. Function name
+ # 3. Function parameters.
+ #
+ # All the while we have to watch out for function pointer parameters
+ # (which IIRC is what the two sections are for), C types (these
+ # regexps don't even start to express all the possibilities), and
+ # so on.
+ #
+ # If you mess with these regexps, it's a good idea to check that
+ # the following functions' documentation still comes out right:
+ # - parport_register_device (function pointer parameters)
+ # - atomic_set (macro)
+ # - pci_match_device (long return type)
+
+ if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+ $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+ $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/) {
+ $return_type = $1;
+ $declaration_name = $2;
+ my $args = $3;
+
+ create_parameterlist($args, ',', $file);
+ } else {
+ print STDERR "Error(${file}:$.): cannot understand prototype: '$prototype'\n";
+ ++$errors;
+ return;
+ }
+
+ output_declaration($declaration_name,
+ 'function',
+ {'function' => $declaration_name,
+ 'module' => $modulename,
+ 'functiontype' => $return_type,
+ 'parameterlist' => \@parameterlist,
+ 'parameterdescs' => \%parameterdescs,
+ 'parametertypes' => \%parametertypes,
+ 'sectionlist' => \@sectionlist,
+ 'sections' => \%sections,
+ 'purpose' => $declaration_purpose
+ });
+}
+
+sub process_file($);
+
+# Read the file that maps relative names to absolute names for
+# separate source and object directories and for shadow trees.
+if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
+ my ($relname, $absname);
+ while(<SOURCE_MAP>) {
+ chop();
+ ($relname, $absname) = (split())[0..1];
+ $relname =~ s:^/+::;
+ $source_map{$relname} = $absname;
+ }
+ close(SOURCE_MAP);
+}
+
+if ($filelist) {
+ open(FLIST,"<$filelist") or die "Can't open file list $filelist";
+ while(<FLIST>) {
+ chop;
+ process_file($_);
+ }
+}
+
+foreach (@ARGV) {
+ chomp;
+ process_file($_);
+}
+
+print STDERR "Warnings: $warnings\n";
+print STDERR "Errors: $errors\n";
+exit($errors);
+
+sub reset_state {
+ $function = "";
+ %constants = ();
+ %parameterdescs = ();
+ %parametertypes = ();
+ @parameterlist = ();
+ %sections = ();
+ @sectionlist = ();
+ $prototype = "";
+
+ $state = 0;
+}
+
+sub process_state3_function($$) {
+ my $x = shift;
+ my $file = shift;
+
+ if ($x =~ m#\s*/\*\s+MACDOC\s*#io) {
+ # do nothing
+ }
+ elsif ($x =~ /([^\{]*)/) {
+ $prototype .= $1;
+ }
+ if (($x =~ /\{/) || ($x =~ /\#/) || ($x =~ /;/)) {
+ $prototype =~ s@/\*.*?\*/@@gos; # strip comments.
+ $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
+ $prototype =~ s@^\s+@@gos; # strip leading spaces
+ dump_function($prototype,$file);
+ reset_state();
+ }
+}
+
+sub process_state3_type($$) {
+ my $x = shift;
+ my $file = shift;
+
+ $x =~ s@/\*.*?\*/@@gos; # strip comments.
+ $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
+ $x =~ s@^\s+@@gos; # strip leading spaces
+ $x =~ s@\s+$@@gos; # strip trailing spaces
+
+ while (1) {
+ if ( $x =~ /([^{};]*)([{};])(.*)/ ) {
+ $prototype .= $1 . $2;
+ ($2 eq '{') && $brcount++;
+ ($2 eq '}') && $brcount--;
+ if (($2 eq ';') && ($brcount == 0)) {
+ dump_declaration($prototype,$file);
+ reset_state();
+ last;
+ }
+ $x = $3;
+ } else {
+ $prototype .= $x;
+ last;
+ }
+ }
+}
+
+sub process_file($) {
+ my ($file) = @_;
+ my $identifier;
+ my $func;
+ my $initial_section_counter = $section_counter;
+
+ if (defined($source_map{$file})) {
+ $file = $source_map{$file};
+ }
+
+ if (!open(IN,"<$file")) {
+ print STDERR "Error: Cannot open file $file\n";
+ ++$errors;
+ return;
+ }
+
+ $section_counter = 0;
+ while (<IN>) {
+ if ($state == 0) {
+ if (/$doc_start/o) {
+ $state = 1; # next line is always the function name
+ }
+ } elsif ($state == 1) { # this line is the function name (always)
+ if (/$doc_block/o) {
+ $state = 4;
+ $contents = "";
+ if ( $1 eq "" ) {
+ $section = $section_intro;
+ } else {
+ $section = $1;
+ }
+ }
+ elsif (/$doc_decl/o) {
+ $identifier = $1;
+ if (/\s*([\w\s]+?)\s*-/) {
+ $identifier = $1;
+ }
+
+ $state = 2;
+ if (/-(.*)/) {
+ $declaration_purpose = $1;
+ } else {
+ $declaration_purpose = "";
+ }
+ if ($identifier =~ m/^struct/) {
+ $decl_type = 'struct';
+ } elsif ($identifier =~ m/^union/) {
+ $decl_type = 'union';
+ } elsif ($identifier =~ m/^enum/) {
+ $decl_type = 'enum';
+ } elsif ($identifier =~ m/^typedef/) {
+ $decl_type = 'typedef';
+ } else {
+ $decl_type = 'function';
+ }
+
+ if ($verbose) {
+ print STDERR "Info(${file}:$.): Scanning doc for $identifier\n";
+ }
+ } else {
+ print STDERR "Warning(${file}:$.): Cannot understand $_ on line $.",
+ " - I thought it was a doc line\n";
+ ++$warnings;
+ $state = 0;
+ }
+ } elsif ($state == 2) { # look for head: lines, and include content
+ if (/$doc_sect/o) {
+ $newsection = $1;
+ $newcontents = $2;
+
+ if ($contents ne "") {
+ $contents =~ s/\&/\\\\\\amp;/g;
+ $contents =~ s/\</\\\\\\lt;/g;
+ $contents =~ s/\>/\\\\\\gt;/g;
+ dump_section($section, $contents);
+ $section = $section_default;
+ }
+
+ $contents = $newcontents;
+ if ($contents ne "") {
+ $contents .= "\n";
+ }
+ $section = $newsection;
+ } elsif (/$doc_end/) {
+
+ if ($contents ne "") {
+ $contents =~ s/\&/\\\\\\amp;/g;
+ $contents =~ s/\</\\\\\\lt;/g;
+ $contents =~ s/\>/\\\\\\gt;/g;
+ dump_section($section, $contents);
+ $section = $section_default;
+ $contents = "";
+ }
+
+ $prototype = "";
+ $state = 3;
+ $brcount = 0;
+# print STDERR "end of doc comment, looking for prototype\n";
+ } elsif (/$doc_content/) {
+ # miguel-style comment kludge, look for blank lines after
+ # @parameter line to signify start of description
+ if ($1 eq "" &&
+ ($section =~ m/^@/ || $section eq $section_context)) {
+ $contents =~ s/\&/\\\\\\amp;/g;
+ $contents =~ s/\</\\\\\\lt;/g;
+ $contents =~ s/\>/\\\\\\gt;/g;
+ dump_section($section, $contents);
+ $section = $section_default;
+ $contents = "";
+ } else {
+ $contents .= $1."\n";
+ }
+ } else {
+ # i dont know - bad line? ignore.
+ print STDERR "Warning(${file}:$.): bad line: $_";
+ ++$warnings;
+ }
+ } elsif ($state == 3) { # scanning for function { (end of prototype)
+ if ($decl_type eq 'function') {
+ process_state3_function($_, $file);
+ } else {
+ process_state3_type($_, $file);
+ }
+ } elsif ($state == 4) {
+ # Documentation block
+ if (/$doc_block/) {
+ dump_section($section, $contents);
+ output_intro({'sectionlist' => \@sectionlist,
+ 'sections' => \%sections });
+ $contents = "";
+ $function = "";
+ %constants = ();
+ %parameterdescs = ();
+ %parametertypes = ();
+ @parameterlist = ();
+ %sections = ();
+ @sectionlist = ();
+ $prototype = "";
+ if ( $1 eq "" ) {
+ $section = $section_intro;
+ } else {
+ $section = $1;
+ }
+ }
+ elsif (/$doc_end/)
+ {
+ dump_section($section, $contents);
+ output_intro({'sectionlist' => \@sectionlist,
+ 'sections' => \%sections });
+ $contents = "";
+ $function = "";
+ %constants = ();
+ %parameterdescs = ();
+ %parametertypes = ();
+ @parameterlist = ();
+ %sections = ();
+ @sectionlist = ();
+ $prototype = "";
+ $state = 0;
+ }
+ elsif (/$doc_content/)
+ {
+ if ( $1 eq "" )
+ {
+ $contents .= $blankline;
+ }
+ else
+ {
+ $contents .= $1 . "\n";
+ }
+ }
+ }
+ }
+ if ($initial_section_counter == $section_counter) {
+ print STDERR "Warning(${file}): no structured comments found\n";
+ if ($output_mode eq "sgml") {
+ # The template wants at least one RefEntry here; make one.
+ print "<refentry>\n";
+ print " <refnamediv>\n";
+ print " <refname>\n";
+ print " ${file}\n";
+ print " </refname>\n";
+ print " <refpurpose>\n";
+ print " Document generation inconsistency\n";
+ print " </refpurpose>\n";
+ print " </refnamediv>\n";
+ print " <refsect1>\n";
+ print " <title>\n";
+ print " Oops\n";
+ print " </title>\n";
+ print " <warning>\n";
+ print " <para>\n";
+ print " The template for this document tried to insert\n";
+ print " the structured comment from the file\n";
+ print " <filename>${file}</filename> at this point,\n";
+ print " but none was found.\n";
+ print " This dummy section is inserted to allow\n";
+ print " generation to continue.\n";
+ print " </para>\n";
+ print " </warning>\n";
+ print " </refsect1>\n";
+ print "</refentry>\n";
+ }
+ }
+}
--- /dev/null
+#!/usr/bin/perl
+#warn "No digit found.\n";
+
+use Env qw(PATH TMPL2SGML KERNELDOC);
+
+warn "Processing $ARGV[0]\n" ;
+#warn "PATH=$PATH\n" ;
+warn "KERNELDOC=$KERNELDOC\n" ;
+
+open (TMPLFILE, "$ARGV[0]");
+
+while (<TMPLFILE>) {
+ $line=$_;
+ if($line=~m/^![EIF]/){
+ ($srctype,$srcfile)= $line =~ /^!([EIF])(.*)$/ ;
+ warn "Found $srctype : $srcfile\n" ;
+ system "$KERNELDOC -docbook $srcfile";
+ }else{
+ print $line
+ }
+}
+
+close TMPLFILE;