1
2use strict "vars";
3
4my $x;
5my $F;
6my @regs;
7my %file;
8my %func;
9
10my %o = ( verbose => 0 );
11
12$o{version} =
13    `grep -i "^version *:" *.spec | sed -e "s/[Vv]ersion *: *//"`;
14$o{package} =
15    `grep -i "^name *:" *.spec | sed -e "s/[Nn]ame *: *//"`;
16$o{version} =~ s{\s*}{}gs;
17$o{package} =~ s{\s*}{}gs;
18
19$o{version} = `date +%Y.%m.%d` if not length $o{version};
20$o{package} = "_project" if not length $o{package};
21
22$o{suffix} = "-doc1";
23$o{mainheader} = "$o{package}.h";
24
25my %fn;
26my $id = 1000;
27
28for $F (@ARGV)
29{
30    if ($F =~ /^(\w+)=(.*)/)
31    {
32	$o{$1} = $2;
33    }else{
34	open F, "<$F" or next;
35	my $T = join ("",<F>); close F;
36
37	$T =~ s/\&/\&amp\;/sg;
38	$T =~ s/�/\&#AC\;/sg;
39	$T =~ s/\*\//�/sg;
40
41	# cut per-function comment block
42	while ( $T =~
43		s{ [/][*][*](?=\s) ([^�]+) � ([^\{\}\;\#]+) [\{\;] }
44		{ per_function_comment_and_declaration($F," ".$1,$2) }gsex
45		) {}
46
47	# cut per-file comment block
48	if ( $T =~ m{ ^ [/][*]+(?=\s) ([^�]+) �
49			  (\s*\#include\s*<[^<>]*>(?:\s*/[/*][^\n]*)?) }sx)
50	{
51	    $file{$F}{comment} = $1;
52	    $file{$F}{include} = $2;
53	    $file{$F}{comment} =~ s/�/\*\//sg;
54	    $file{$F}{include} =~ s/�/\*\//sg;
55	    $file{$F}{include} =~ s{[/][*]}{//}s;
56	    $file{$F}{include} =~ s{[*][/]}{\n}s;
57	    $file{$F}{include} =~ s{<}{\&lt\;}sg;
58	    $file{$F}{include} =~ s{>}{\&gt\;}sg;
59 	}
60	elsif ( $T =~ m{ ^ [/][*]+(?=\s) ([^�]+) � }sx)
61	{
62	    $file{$F}{comment} = $1;
63	    $file{$F}{comment} =~ s/�/\*\//sg;
64 	}
65
66	# throw away the rest - further processing on memorized strings only
67    }
68}
69
70$o{outputfilestem}= "$o{package}$o{suffix}" if not length $o{outputfilestem};
71$o{docbookfile}= "$o{outputfilestem}.docbook" if not length $o{docbookfile};
72$o{libhtmlfile}= "$o{outputfilestem}.html"    if not length $o{libhtmlfile};
73$o{dumpdocfile}= "$o{outputfilestem}.dxml"    if not length $o{dumpdocfile};
74
75sub per_function_comment_and_declaration
76{
77    my ($filename, $comment, $prototype) = @_;
78
79    $prototype =~ s{�}{*/}sg;
80    $comment =~ s{�}{*/}sg;
81    $comment =~ s{<([\w\.\-]+\@[\w\.\-]+\w\w)>}{&lt;$1&gt;}sg;
82    $func{$id}{filename} = $filename;
83    $func{$id}{comment}  = $comment;
84    $func{$id}{prototype} = $prototype;
85    $id ++;
86    return $prototype;
87}
88# -----------------------------------------------------------------------
89sub pre { # used for non-star lines in comment blocks
90    my $T = $_[0]; $T =~ s/\&/\&amp\;/g;
91    $T =~ s/\</\&lt\;/g; $T =~ s/\>/\&gt\;/g; $T =~ s/\"/\&quot\;/g;
92    $T =~ s/^/\ /gm; #  $T =~ s/^/\| /gm;
93    return " <pre> $T </pre> ";
94}
95
96# per-file comment block handling
97my $name;
98for $name (keys %file)
99{
100    $file{$name}{comment} =~ s{<([\w\.\-]+\@[\w\.\-]+\w\w)>}{&lt;$1&gt;}sg;
101    $file{$name}{comment} =~ s{ ^\s?\s?\s? ([^\*\s]+ .*) $}{&pre($1)}mgex;
102    $file{$name}{comment} =~ s{ ^\s*[*]\s* $}{ <p> }gmx;
103    $file{$name}{comment} =~ s{ ^\s?\s?\s?\* (.*) $}{ $1 }gmx;
104    $file{$name}{comment} =~ s{ </pre>(\s*)<pre> }{$1}gsx;
105    $file{$name}{comment} =~ s{ <([^<>\;]+\@[^<>\;]+)> }{<email>$1</email>}gsx;
106    $file{$name}{comment} =~ s{ \&lt\;([^<>\&\;]+\@[^<>\&\;]+)\&gt\; }
107				{<email>$1</email>}gsx;
108    $file{$name}{comment} .= "<p>";
109
110    $file{$name}{comment} =~ s{ \b[Aa]uthor\s*:(.*<\/email>) }
111    {
112	$file{$name}{author} = "$1";
113	"<author>"."$1"."</author>"
114    }sex;
115
116    $file{$name}{comment} =~ s{ \b[Cc]opyright[\s:]([^<>]*)<p> }
117    {
118	$file{$name}{copyright} = "$1";
119	"<copyright>"."$1"."</copyright>"
120    }sex;
121#   if ($name =~ /file/) {
122#       print STDERR $file{$name}{comment},"\n";
123#   }
124    if ($file{$name}{include} =~ m{//\s*(\w+)[.][.][.]\s*})
125    {
126	if (length $o{$1}) {
127	    $file{$name}{include} = "#include "
128		.$o{$1}."\n";
129	    $file{$name}{include} =~ s{<}{\&lt\;}sg;
130	    $file{$name}{include} =~ s{>}{\&gt\;}sg;
131	}
132    }
133}
134
135# -----------------------------------------------------------------------
136
137# pass 1 of per-func strings:
138# (a) cut prototype into prespec/namespec/callspec
139# (b) sanitize comment-block into proper docbook format
140# do this while copying strings from $func{$name} to $fn{name} strstrhash
141my @namelist;
142for $x (sort keys %func)
143{
144    my $name = $func{$x}{prototype};
145    $name =~ s/^.*[^.]\b(\w[\w.]*\w)\b\s*\(.*$/$1/s;
146    push @namelist, $name; # may be you want to omit some funcs from output?
147
148    $func{$x}{prototype} =~ m{ ^(.*[^.]) \b(\w[\w.]*\w)\b (\s*\(.*) $ }sx;
149    $fn{$name}{prespec} = $1;
150    $fn{$name}{namespec} = $2;
151    $fn{$name}{callspec} = $3;
152
153    $fn{$name}{comment} = $func{$x}{comment};
154    $fn{$name}{comment} =~ s/(^|\s)\=\>\"([^\"]*)\"/$1<link>$2<\/link>/gmx;
155    $fn{$name}{comment} =~ s/(^|\s)\=\>\'([^\"]*)\'/$1<link>$2<\/link>/gmx;
156    $fn{$name}{comment} =~ s/(^|\s)\=\>\s(\w[\w.]*\w)\b/$1<link>$2<\/link>/gmx;
157    $fn{$name}{comment} =~
158	s/(^|\s)\=\>\s([^\s\,\.\!\?\:\;\<\>\&\'\=\-]+)/$1<link>$2<\/link>/gmx;
159
160    # cut comment in first-line (describe) and only keep the rest in comment
161    $fn{$name}{describe} = $fn{$name}{comment};
162    $fn{$name}{describe} =~ s{^([^\n]*\n).*}{$1}gs;
163    $fn{$name}{comment} =~ s{^[^\n]*\n}{}gs;
164    if ($fn{$name}{describe} =~ /^\s*$/s)
165    {
166	$fn{$name}{describe} = "(".$func{$x}{filename}.")";
167	$fn{$name}{describe} =~ s,[.][.][/],,g;
168    }
169
170    $fn{$name}{comment} =~ s/ ^\s?\s?\s? ([^\*\s]+ .*) $/&pre($1)/mgex;
171    $fn{$name}{comment} =~ s/ ^\s?\s?\s?\* (.*) $/ <br \/> $1 /gmx;
172    $fn{$name}{comment} =~ s/ ^\s*<br\s*\/>\s* $/ <p> /gmx;
173    $fn{$name}{comment} =~ s{<<}{&lt;}sg;
174    $fn{$name}{comment} =~ s{>>}{&gt;}sg;
175    $fn{$name}{comment} =~ s/ (<p>\s*)<br\s*\/?>/$1/gsx;
176    $fn{$name}{comment} =~ s/ (<p>\s*)<br\s*\/?>/$1/gsx;
177    $fn{$name}{comment} =~ s/ (<br\s*\/?>\s*)<br\s*\/?>/$1/gsx;
178    $fn{$name}{comment} =~ s/<c>/<code>/gs;
179    $fn{$name}{comment} =~ s/<\/c>/<\/code>/gs;
180    $fn{$name}{comment} =~ s/<\/pre>(\s*)<pre>/$1/gs;
181
182    $fn{$name}{filename} = $func{$x}{filename};
183    $fn{$name}{callspec} =~ s{^ \s*}{}gsx;
184    $fn{$name}{prespec}  =~ s{^ \s*}{}gsx;
185    $fn{$id} = $x;
186}
187
188# add extra docbook markups to callspec in $fn-hash
189for $name (@namelist) # <paramdef>
190{
191    $fn{$name}{callspec} =~ s:^([^\(\)]*)\(:$1<parameters>\(<paramdef>:s;
192    $fn{$name}{callspec} =~ s:\)([^\(\)]*)$:</paramdef>\)</parameters>$1:s;
193    $fn{$name}{callspec} =~ s:,:</paramdef>,<paramdef>:gs;
194    $fn{$name}{callspec} =~ s:<paramdef>(\s+):$1<paramdef>:gs;
195    $fn{$name}{callspec} =~ s:(\s+)</paramdef>:</paramdef>$1:gs;
196}
197
198# html-formatting of callspec strings
199for $name (@namelist)
200{
201    $fn{$name}{declcode} =
202        "<td valign=\"top\"><code>".$fn{$name}{prespec}."<\/code><\/td>"
203	."<td valign=\"top\">&nbsp;&nbsp;</td>"
204	."<td valign=\"top\"><a href=\"#$name\">"
205	."\n <code>".$fn{$name}{namespec}."<\/code>\n"
206	."<\/a><\/td>"
207	."<td valign=\"top\">&nbsp;&nbsp;</td>"
208	."<td valign=\"top\">".$fn{$name}{callspec}."<\/td>";
209
210    $fn{$name}{implcode} =
211        "<code>".$fn{$name}{prespec}."<\/code>"
212	."\n <br \/><b><code>".$fn{$name}{namespec}."<\/code><\/b>"
213	."\n &nbsp; <code>".$fn{$name}{callspec}."<\/code>";
214
215    $fn{$name}{declcode} =~ s{\s+<paramdef>}{\n<nobr>}gs;
216    $fn{$name}{implcode} =~ s{\s+<paramdef>}{\n<nobr>}gs;
217    $fn{$name}{declcode} =~ s{<paramdef>}{<nobr>}gs;
218    $fn{$name}{implcode} =~ s{<paramdef>}{<nobr>}gs;
219    $fn{$name}{declcode} =~ s{</paramdef>}{</nobr>}gs;
220    $fn{$name}{implcode} =~ s{</paramdef>}{</nobr>}gs;
221    $fn{$name}{declcode} =~ s{<parameters>}{\n <code>}gs;
222    $fn{$name}{implcode} =~ s{<parameters>}{\n <code>}gs;
223    $fn{$name}{declcode} =~ s{</parameters>}{</code>\n}gs;
224    $fn{$name}{implcode} =~ s{</parameters>}{</code>\n}gs;
225}
226
227# whether each function should get its own page or combined with others
228my $combinedstyle = 1;
229
230for $name (@namelist)
231{
232    if ($fn{$name}{describe} =~ /^ \s* <link>(\w[\w.]*\w)<\/link> /sx)
233    {
234	if ($combinedstyle and exists $fn{$1})
235	{
236	    # $into tells later steps which func-name is the leader of a man
237	    # page and that this func should add its descriptions over there.
238	    $fn{$name}{into} = $1;
239	}
240    }
241
242    if ($fn{$name}{describe} =~ s/(.*)also:(.*)/$1/)
243    {
244	$fn{$name}{_seealso} = $2;
245    }
246
247    # and prepare items for being filled in $combinedstyle (html-mode)
248    # which includes adding descriptions of the leader functions firsthand
249    $fn{$name}{_anchors} = "<a name=\"$name\" />";
250    $fn{$name}{_impcode} = "<code>".$fn{$name}{implcode}."</code>";
251    $fn{$name}{_comment} = "<p> &nbsp;".$fn{$name}{describe}."\n";
252    $fn{$name}{_comment} .= "<p>".$fn{$name}{comment};
253}
254
255for $name (@namelist) # and add descriptions of non-leader entries (html-mode)
256{
257    next if not exists $fn{$name}{into}; # skip leader pages
258    my $into = $fn{$name}{into};
259    $fn{$into}{_anchors} .= "<a name=\"$name\" />";
260    $fn{$into}{_impcode} .= "<br />\n";
261    $fn{$into}{_impcode} .= "<code>".$fn{$name}{implcode}."</code>";
262    my $text = $fn{$name}{comment};
263    $text =~ s/ (T|t)his \s (function|procedure) /$1."he ".$name." ".$2/gsex;
264    $fn{$name}{_comment} .= "<p>".$text;
265}
266
267my $htmlTOC = "";
268my $htmlTXT = "";
269
270# generate the index-block at the start of the onepage-html file
271for $name (@namelist)
272{
273    $fn{$name}{_comment} =~ s/ (<p>\s*)<br\s*\/>/$1/gsx;
274
275    $htmlTOC .= "<tr valign=\"top\">\n".$fn{$name}{declcode}."</tr>";
276    next if $combinedstyle and exists $fn{$name}{into};
277
278    $htmlTXT .=  "\n<dt>".$fn{$name}{_anchors}.$fn{$name}{_impcode}."<dt>";
279    $htmlTXT .= "\n<dd>".$fn{$name}{_comment};
280    $htmlTXT .= "\n<p align=\"right\"><small>("
281	.$fn{$name}{filename}.")</small></p></dd>";
282}
283
284# link ref-names in this page with its endpoints on the same html page
285$htmlTXT =~ s/ <link>(\w+)([^<>]*)<\/link> / &a_name($1,$2) /gsex;
286sub a_name
287{
288    my ($n,$m) = @_;
289    if (exists $fn{$n}) { return "<a href=\"#$n\"><code>$n$m</code></a>"; }
290    else { return "<code>$n$m</code>"; }
291}
292$htmlTXT =~ s/ \-\> /<small>-\&gt\;<\/small>/gsx; # just sanitize
293
294# and finally print the html-formatted output
295open F, ">$o{libhtmlfile}" or die "could not open '$o{libhtmlfile}': $!";
296print F "<html><head><title> $o{package} autodoc documentation </title>";
297print F "</head>\n<body>\n";
298print F "\n<h1>",$o{package}," <small><small><i>-", $o{version};
299print F "</i></small></small></h1>";
300print F "\n<table border=0 cellspacing=2 cellpadding=0>";
301print F $htmlTOC;
302print F "\n</table>";
303print F "\n<h3>Documentation</h3>\n";
304print F "\n<dl>";
305print F $htmlTXT;
306print F "\n</dl>";
307print F "\n</body></html>\n";
308close F;
309
310# =========================================================================== #
311# let's go for the pure docbook, a reference type master file for all man pages
312my @headerlist; # leader function pages - a file will be created for each of th
313my @mergedlist; # non-leader function that end up in one of those in headerlist
314
315for $name (@namelist)
316{
317    push @headerlist, $name if not exists $fn{$name}{into};
318    push @mergedlist, $name if exists $fn{$name}{into};
319
320    # and initialize the fields need for a man page entry - the fields are
321    # named after the docbook-markup that encloses (!!) the text we store
322    # in the strstrhash - therefore, {}{_refhint} = "hello" will be printed
323    # as <refhint>hello</refhint>. Names with scores at the end are only used
324    # as temporaries but they are memorized - perhaps they are useful later.
325
326    $fn{$name}{_refhint} =
327		"\n<!--========= ".$name." (3) ===========-->\n";
328    $fn{$name}{_refstart} = "";
329    $fn{$name}{_date_} = $o{version};
330    $fn{$name}{_date_} =~ s{\s*}{}gs;
331    $fn{$name}{_refentryinfo}
332    = "\n <date>".$fn{$name}{_date_}."</date>";
333    $fn{$name}{_productname_} = $o{package};
334    $fn{$name}{_productname_} =~ s{\s*}{}gs;
335    $fn{$name}{_refentryinfo}
336    .= "\n <productname>".$fn{$name}{_productname_}."</productname>";
337#    if (exists $file{ $fn{$name}{filename} }{author})
338#    {
339#	$H = $file{ $fn{$name}{filename} }{author};
340#	$H =~ s{ \s* ([^<>]*) (<email>[^<>]*</email>) }{
341#	    $fn{$name}{_refentryinfo} .= "\n <author>".$1.$2."</author>";
342#	    "" }gmex;
343#    }
344    $fn{$name}{_refmeta} = "";
345    $fn{$name}{_refnamediv} = "";
346    $fn{$name}{_mainheader} = $o{mainheader};
347    $fn{$name}{_includes} = $file{ $fn{$name}{filename} }{include};
348    $fn{$name}{_manvolnum} = "3";
349    $fn{$name}{_funcsynopsisinfo} = "";
350    $fn{$name}{_funcsynopsis} = "";
351    $fn{$name}{_description} = "";
352    $fn{$name}{_refends} = "";
353}
354
355push @headerlist, @mergedlist; # aaahmm...
356
357# let's walk all (!!) entries...
358for $name (@headerlist)
359{
360    # $into is the target-manpage to add descriptions to. Initially it does
361    # reference the name of the function itself - but it overridden in the
362    # next line when we see an {into} mark. The self/into state is registered
363    # in two vars: $into is an index into %fn-strstrhash to be used instead of
364    # the $name-runvar and $me just a boolean value to conditionally add texts
365    my $into = $name; my $me = 1;
366
367    if (exists $fn{$name}{into})
368    {
369	$into = $fn{$name}{into}; $me = 0;
370	$fn{$name}{_refhint} =
371	    "\n              <!-- see ".$fn{$name}{mergeinto}." -->\n";
372    }
373
374    $fn{$into}{_refstart} .= '<refentry id="'.$name.'">' if $me;
375    $fn{$into}{_refends}  .= "\n</refentry>\n" if $me;
376
377    $fn{$name}{_title_} = $name;
378    $fn{$name}{_title_} =~ s{\s*}{}gs;
379    $fn{$name}{_refentryinfo}
380    .= "\n <title>".$fn{$name}{_title_}."</title>" if $me;
381    $fn{$into}{_refmeta}
382    .= "\n <manvolnum>".$fn{$name}{_manvolnum}."</manvolnum>" if $me;
383    $fn{$into}{_refmeta}
384    .= "\n <refentrytitle>".$name."</refentrytitle>" if $me;
385
386    $fn{$name}{_funcsynopsisinfo}
387    = "\n".' #include &lt;'.$fn{$into}{_mainheader}.'&gt;' if $me;
388    $fn{$name}{_funcsynopsisinfo}
389    = "\n".$fn{$into}{_includes} if $me and length $fn{$into}{_includes};
390    $fn{$name}{_funcsynopsisinfo}
391    .= " // ".$o{synopsis} if $me and length $o{synopsis};
392
393    $fn{$into}{_refnamediv} .= "\n ".
394	"<refpurpose>".$fn{$name}{describe}." </refpurpose>" if $me;
395    $fn{$into}{_refnamediv} .= "\n".' <refname>'.$name.'</refname>';
396
397    # add to {}{_funcsynopsis}...
398    $fn{$into}{_funcsynopsis} .= "\n <funcprototype>\n <funcdef>";
399    $fn{$into}{_funcsynopsis} .= $fn{$name}{prespec}
400    ." <function>".$name."</function></funcdef>";
401    $fn{$name}{_callspec_} = $fn{$name}{callspec};
402    $fn{$name}{_callspec_} =~ s{<parameters>\s*\(}{ }gs;
403    $fn{$name}{_callspec_} =~ s{\)\s*</parameters>}{ }gs;
404    $fn{$name}{_callspec_} =~ s{</paramdef>\s*,\s*}{</paramdef>\n }gs;
405    $fn{$into}{_funcsynopsis}
406    .= "\n".$fn{$name}{_callspec_}." </funcprototype>";
407
408    # add to {}{_description}...
409    $fn{$name}{_comment_} = "<para>\n".$fn{$name}{comment}."\n</para>";
410    $fn{$name}{_comment_} =~ s{ (T|t)his \s (function|procedure) }
411    { $1."he <function>".$name."</function> ".$2 }gsex;
412    $fn{$name}{_comment_} =~ s{<p>}{"\n</para><para>\n"}gsex;
413    $fn{$name}{_comment_} =~ s{<br\s*/?>}{}gs;
414    $fn{$name}{_comment_} =~ s{(</?)em>}{$1emphasis>}gs;
415    $fn{$name}{_comment_} =~ s{<code>}{<userinput>}gs;
416    $fn{$name}{_comment_} =~ s{</code>}{</userinput>}gs;
417    $fn{$name}{_comment_} =~ s{<link>}{<function>}gs;
418    $fn{$name}{_comment_} =~ s{</link>}{</function>}gs;
419    $fn{$name}{_comment_} =~ s{<pre>}{<screen>}gs;   # only xmlto .8 and
420    $fn{$name}{_comment_} =~ s{</pre>}{</screen>}gs; # higher !!
421#    $fn{$name}{_comment_} =~ s{<ul>}{</para><itemizedlist>}gs;
422#    $fn{$name}{_comment_} =~ s{</ul>}{</itemizedlist><para>}gs;
423#    $fn{$name}{_comment_} =~ s{<li>}{<listitem><para>}gs;
424#    $fn{$name}{_comment_} =~ s{</li>}{</para></listitem>\n}gs;
425    $fn{$name}{_comment_} =~ s{<ul>}{</para><programlisting>\n}gs;
426    $fn{$name}{_comment_} =~ s{</ul>}{</programlisting><para>}gs;
427    $fn{$name}{_comment_} =~ s{<li>}{}gs;
428    $fn{$name}{_comment_} =~ s{</li>}{}gs;
429    $fn{$into}{_description} .= $fn{$name}{_comment_};
430
431    if (length $fn{$name}{_seealso} and not $me)
432    {
433	$fn{$into}{_seealso} .= ", " if length $fn{$into}{_seealso};
434	$fn{$into}{_seealso} .= $fn{$name}{_seealso};
435    }
436
437    if (exists $file{ $fn{$name}{filename} }{author})
438    {
439	my $authors = $file{ $fn{$name}{filename} }{author};
440	$fn{$into}{_authors} = "<itemizedlist>";
441	$authors =~ s{ \s* ([^<>]*) (<email>[^<>]*</email>) }{
442	    $fn{$into}{_authors}
443	    .= "\n <listitem><para>".$1." ".$2."</para></listitem>";
444	    "" }gmex;
445	$fn{$into}{_authors} .= "</itemizedlist>";
446    }
447
448    if (exists $file{ $fn{$name}{filename} }{copyright})
449    {
450	$fn{$into}{_copyright}
451	= "<screen>\n".$file{ $fn{$name}{filename} }{copyright}."</screen>\n";
452    }
453}
454
455# printing the docbook file is a two-phase process - we spit out the
456# leader pages first - later we add more pages with _refstart pointing
457# to the lader page, so that xmlto will add the functions there. Only the
458# leader page contains some extra info needed for troff page processing.
459
460my %header;
461
462open F, ">$o{docbookfile}" or die "could not open $o{docbookfile}: $!";
463print F '<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"';
464print F "\n",'   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">';
465print F "\n\n",'<reference><title>Manual Pages</title>',"\n";
466for $name (@namelist)
467{
468    print F $fn{$name}{_refhint};
469    next if exists $fn{$name}{into};
470    print F $fn{$name}{_refstart};
471    print F "\n<refentryinfo>",               $fn{$name}{_refentryinfo}
472    ,       "\n</refentryinfo>\n"   if length $fn{$name}{_refentryinfo};
473    print F "\n<refmeta>",                    $fn{$name}{_refmeta}
474    ,       "\n</refmeta>\n"        if length $fn{$name}{_refmeta};
475    print F "\n<refnamediv>",                 $fn{$name}{_refnamediv}
476    ,       "\n</refnamediv>\n"     if length $fn{$name}{_refnamediv};
477
478    print F "\n<refsynopsisdiv>"    if length $fn{$name}{_funcsynopsis};
479    print F "\n<funcsynopsisinfo>",           $fn{$name}{_funcsynopsisinfo}
480    ,       "\n</funcsynopsisinfo>" if length $fn{$name}{_funcsynopsisinfo};
481    print F "\n<funcsynopsis>",               $fn{$name}{_funcsynopsis}
482    ,       "\n</funcsynopsis>"     if length $fn{$name}{_funcsynopsis};
483    print F "\n</refsynopsisdiv>"   if length $fn{$name}{_funcsynopsis};
484    print F "\n<refsect1><title>Description</title>", $fn{$name}{_description}
485    ,       "\n</refsect1>"                 if length $fn{$name}{_description};
486    print F "\n<refsect1><title>Author</title>",      $fn{$name}{_authors}
487    ,       "\n</refsect1>"                 if length $fn{$name}{_authors};
488    print F "\n<refsect1><title>Copyright</title>",   $fn{$name}{_copyright}
489    ,       "\n</refsect1>"                 if length $fn{$name}{_copyright};
490    print F "\n<refsect1><title>See Also</title>",    $fn{$name}{_seealso}
491    ,       "\n</refsect1>"                 if length $fn{$name}{_seealso};
492
493    print F $fn{$name}{_refends};
494
495    # ------------------------------------------------------------------
496    # creating the per-header manpage - a combination of function man pages
497
498    my $H = $fn{$name}{_mainheader}; # a shorthand for the mainheader index
499    my $me = 0; $me = 1 if not exists $header{$H};
500    my $HH = $H; $HH =~ s/[^\w\.]/-/g;
501    $header{$H}{_refstart} = "\n<refentry id=\"".$HH."\">" if $me;
502    $header{$H}{_refends} = "\n</refentry>\n" if $me;
503    $header{$H}{_refentryinfo} = $fn{$name}{_refentryinfo} if $me;
504    $header{$H}{_refentryinfo}
505    =~ s/(<title>)([^<>]*)(<\/title>)/$1 the library $3/s if $me;
506    $header{$H}{_refmeta}
507    = "\n   <manvolnum>".$fn{$name}{_manvolnum}."</manvolnum>\n"
508    . "\n   <refentrytitle>".$fn{$name}{_mainheader}."</refentrytitle>" if $me;
509    $header{$H}{_refnamediv} = "\n   <refpurpose> library </refpurpose>";
510    $header{$H}{_refnamediv} .= "\n   <refname>".$HH."</refname>";
511
512    $header{$H}{_refsynopsisinfo}
513    = $fn{$name}{_refsynopsisinfo} if exists $fn{$name}{_refsynopsisinfo};
514    $header{$H}{_funcsynopsis}
515    .= "\n".$fn{$name}{_funcsynopsis} if exists $fn{$name}{_funcsynopsis};
516#    $header{$H}{_funcsynopsisdiv} .= "\n<funcsynopsis>"
517#	.$fn{$name}{_funcsynopsis}."</funcsynopsis>"
518#	if exists  $fn{$name}{_funcsynopsis};
519    $header{$H}{_copyright}
520    = $fn{$name}{_copyright} if exists $fn{$name}{_copyright} and $me;
521    $header{$H}{_authors}
522    = $fn{$name}{_authors}   if exists $fn{$name}{_authors} and $me;
523    if ($me)
524    {
525	my $T = `cat $o{package}.spec`;
526	if ($T =~ /\%description\b([^\%]*)\%/s)
527	{
528	    $header{$H}{_description} = $1;
529	}elsif (not length $header{$H}{_description})
530	{
531	    $header{$H}{_description} = "$o{package} library";
532	}
533    }
534}
535
536my $H;
537for $H (keys %header) # second pass
538{
539    next if not length $header{$H}{_refstart};
540    print F "\n<!-- _______ ",$H," _______ -->";
541    print F $header{$H}{_refstart};
542    print F "\n<refentryinfo>",               $header{$H}{_refentryinfo}
543    ,       "\n</refentryinfo>\n"   if length $header{$H}{_refentryinfo};
544    print F "\n<refmeta>",                    $header{$H}{_refmeta}
545    ,       "\n</refmeta>\n"        if length $header{$H}{_refmeta};
546    print F "\n<refnamediv>",                 $header{$H}{_refnamediv}
547    ,       "\n</refnamediv>\n"     if length $header{$H}{_refnamediv};
548
549    print F "\n<refsynopsisdiv>"    if length $header{$H}{_funcsynopsis};
550    print F "\n<funcsynopsisinfo>",           $header{$H}{_funcsynopsisinfo}
551    ,       "\n</funcsynopsisinfo>" if length $header{$H}{_funcsynopsisinfo};
552    print F "\n<funcsynopsis>",               $header{$H}{_funcsynopsis}
553    ,       "\n</funcsynopsis>"     if length $header{$H}{_funcsynopsis};
554    print F  "\n</refsynopsisdiv>"  if length $header{$H}{_funcsynopsis};
555
556    print F "\n<refsect1><title>Description</title>", $header{$H}{_description}
557    ,       "\n</refsect1>"                if length $header{$H}{_description};
558    print F "\n<refsect1><title>Author</title>",      $header{$H}{_authors}
559    ,       "\n</refsect1>"                 if length $header{$H}{_authors};
560    print F "\n<refsect1><title>Copyright</title>",   $header{$H}{_copyright}
561    ,       "\n</refsect1>"                 if length $header{$H}{_copyright};
562
563    print F $header{$H}{_refends};
564}
565print F "\n",'</reference>',"\n";
566close (F);
567
568# _____________________________________________________________________
569open F, ">$o{dumpdocfile}" or die "could not open $o{dumpdocfile}: $!";
570
571for $name (sort keys %fn)
572{
573    print F "<fn id=\"$name\"><!-- FOR \"$name\" -->\n";
574    for $H (sort keys %{$fn{$name}})
575    {
576	print F "<$H name=\"$name\">",$fn{$name}{$H},"</$H>\n";
577    }
578    print F "</fn><!-- END \"$name\" -->\n\n";
579}
580close F;
581