Adding stuff for man page generation so toolset is consistent.
authorhal9 <hal9@users.sourceforge.net>
Mon, 12 Aug 2002 05:03:44 +0000 (05:03 +0000)
committerhal9 <hal9@users.sourceforge.net>
Mon, 12 Aug 2002 05:03:44 +0000 (05:03 +0000)
utils/docbook2man/COPYING [new file with mode: 0644]
utils/docbook2man/docbook2man-spec.pl [new file with mode: 0644]
utils/docbook2man/docbook2man-spec.pl.1 [new file with mode: 0644]

diff --git a/utils/docbook2man/COPYING b/utils/docbook2man/COPYING
new file mode 100644 (file)
index 0000000..d60c31a
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/utils/docbook2man/docbook2man-spec.pl b/utils/docbook2man/docbook2man-spec.pl
new file mode 100644 (file)
index 0000000..4f3b81d
--- /dev/null
@@ -0,0 +1,1228 @@
+=head1 NAME
+
+docbook2man-spec - convert DocBook RefEntries to Unix manpages
+
+=head1 SYNOPSIS
+
+The SGMLSpm package from CPAN.  This contains the sgmlspl script which
+is used to grok this file.  Use it like this:
+
+nsgmls some-docbook-document.sgml | sgmlspl docbook2man-spec.pl
+
+=head1 DESCRIPTION
+
+This is a sgmlspl spec file that produces Unix-style
+manpages from RefEntry markup.
+
+See the accompanying RefEntry man page for 'plain new' documentation. :)
+
+=head1 LIMITATIONS
+
+Trying docbook2man on non-DocBook or non-conformant SGML results in
+undefined behavior. :-)
+
+This program is a slow, dodgy Perl script.
+
+This program does not come close to supporting all the possible markup
+in DocBook, and will produce wrong output in some cases with supported
+markup.
+
+=head1 TODO
+
+Add new element handling and fix existing handling.  Be robust.
+Produce cleanest, readable man output as possible (unlike some
+other converters).  Follow Linux man(7) convention.
+If this results in added logic in this script,
+that's okay.  The code should still be reasonably organized.
+
+Make it faster.  If Perl sucks port it to another language.
+
+=head1 COPYRIGHT
+
+Copyright (C) 1998-1999 Steve Cheng <steve@ggi-project.org>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+You should have received a copy of the GNU General Public License along with
+this program; see the file COPYING.  If not, please write to the Free
+Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+=cut
+
+# $Id: docbook2man-spec.pl,v 1.1.2.1 2002/08/11 20:01:30 hal9 Exp $
+
+use SGMLS;                     # Use the SGMLS package.
+use SGMLS::Output;             # Use stack-based output.
+use SGMLS::Refs;
+
+########################################################################
+# SGMLSPL script produced automatically by the script sgmlspl.pl
+#
+# Document Type: any, but processes only RefEntries
+# Edited by: me :)
+########################################################################
+
+$write_manpages = 0;
+$blank_xrefs = 0;
+
+sgml('start', sub { 
+       push_output('nul');
+       $raw_cdata = 1;                 # Makes it a bit faster.
+       
+       # Links file
+       open(LINKSFILE, ">manpage.links");
+
+       $Refs = new SGMLS::Refs("manpage.refs");
+});
+sgml('end', sub {
+       close(LINKSFILE);
+       if($blank_xrefs) {
+               print STDERR "Warning: output contains unresolved XRefs\n";
+       }
+});
+
+
+
+
+########################################################################
+#
+# Output helpers 
+#
+########################################################################
+
+# Our own version of sgml() and output() to allow simple string output
+# to play well with roff's stupid whitespace rules. 
+
+sub man_sgml
+{
+       if(ref($_[1]) eq 'CODE') {
+               return &sgml;
+       }
+       
+       my $s = $_[1];
+
+       $s =~ s/\\/\\\\/g;
+       $s =~ s/'/\\'/g;
+
+       # \n at the beginning means start at beginning of line
+       if($s =~ s/^\n//) {
+               $sub = 'sub { output "\n" unless $newline_last++; ';
+               if($s eq '') { 
+                       sgml($_[0], eval('sub { output "\n" unless $newline_last++; }'));
+               } elsif($s =~ /\n$/) {
+                       sgml($_[0], eval("sub { output \"\\n\" unless \$newline_last++; output '$s'; }"));
+               } else {
+                       sgml($_[0], eval("sub { output \"\\n\" unless \$newline_last; output '$s'; \$newline_last = 0; }"));
+               }
+       } else {
+               if($s =~ /\n$/) {
+                       sgml($_[0], eval("sub { output '$s'; \$newline_last = 1; }"));
+               } else {
+                       sgml($_[0], eval("sub { output '$s'; \$newline_last = 0; }"));
+               }
+       }
+}
+
+sub man_output
+{
+       $_ = shift;
+       if(s/^\n//) {
+               output "\n" unless $newline_last++;
+       }
+       return if $_ eq '';
+       
+       output $_;
+
+       if(@_) {
+               output @_;
+               $newline_last = (pop(@_) =~ /\n$/);
+       } else {
+               $newline_last = ($_ =~ /\n$/)
+       }
+}
+
+# Fold lines into one, quote some characters
+sub fold_string
+{
+       $_ = shift;
+       
+       s/\\/\\\\/g;
+       s/"/\\\&"/g;
+
+       # Change tabs to spaces
+       tr/\t\n/  /;
+
+       # Trim whitespace from beginning and end.
+       s/^ +//;
+       s/ +$//;
+
+       return $_;
+}
+       
+sub save_cdata()
+{
+       $raw_cdata++;
+       push_output('string');
+}
+
+sub bold_on()
+{
+       # If the last font is also bold, don't change anything.
+       # Basically this is to just get more readable man output.
+       if($fontstack[$#fontstack] ne 'bold') {
+               if(!$raw_cdata) {
+                       output '\fB';
+                       $newline_last = 0;
+               }
+       }
+       push(@fontstack, 'bold');
+}
+
+sub italic_on()
+{
+       # If the last font is also italic, don't change anything.
+       if($fontstack[$#fontstack] ne 'italic') {
+               if(!$raw_cdata) {
+                       output '\fI';
+                       $newline_last = 0;
+               }
+       }
+       push(@fontstack, 'italic');
+}
+
+sub font_off()
+{
+       my $thisfont = pop(@fontstack);
+       my $lastfont = $fontstack[$#fontstack];
+       
+       # Only output font change if it is different
+       if($thisfont ne $lastfont) {
+               if($raw_cdata)                  { return; }
+               elsif($lastfont eq 'bold')      { output '\fB'; }
+               elsif($lastfont eq 'italic')    { output '\fI'; }
+               else                            { output '\fR'; }
+       
+               $newline_last = 0;
+       }
+}
+
+
+
+
+
+
+########################################################################
+#
+# Manpage management
+#
+########################################################################
+
+sgml('<REFENTRY>', sub { 
+       # This will be overwritten at end of REFMETA, when we know the name of the page.
+       pop_output();
+       
+       $write_manpages = 1;            # Currently writing manpage.
+       
+       $nocollapse_whitespace = 0;     # Current whitespace collapse counter.
+       $newline_last = 1;              # At beginning of line?
+               # Just a bit of warning, you will see this variable manipulated
+               # manually a lot.  It makes the code harder to follow but it
+               # saves you from having to worry about collapsing at the end of
+               # parse, stopping at verbatims, etc.
+       $raw_cdata = 0;                 # Instructs certain output functions to
+                                       # leave CDATA alone, so we can assign
+                                       # it to a string and process it, etc.
+       @fontstack = ();                # Fonts being activated.
+       
+       $manpage_title = '';            # Needed for indexing.
+       $manpage_sect = '';
+       @manpage_names = ();
+       
+       $manpage_misc = '';
+       
+       $list_nestlevel = 0;            # Indent certain nested content.
+});
+sgml('</REFENTRY>', sub {
+       if(!$newline_last) {
+               output "\n";
+       }
+       
+       $write_manpages = 0;
+       $raw_cdata = 1;
+       push_output('nul');
+});
+
+sgml('</REFMETA>', sub {
+       push_output('file', "$manpage_title.$manpage_sect");
+
+       output <<_END_BANNER;
+.\\" This manpage has been automatically generated by docbook2man 
+.\\" from a DocBook document.  This tool can be found at:
+.\\" <http://shell.ipoline.com/~elmert/comp/docbook2X/> 
+.\\" Please send any bug reports, improvements, comments, patches, 
+.\\" etc. to Steve Cheng <steve\@ggi-project.org>.
+_END_BANNER
+
+       my $manpage_date = `date "+%d %B %Y"`;
+               
+       output '.TH "';
+       
+       # If the title is not mixed-case, convention says to
+       # uppercase the whole title.  (The canonical title is
+       # lowercase.)
+       if($manpage_title =~ /[A-Z]/) {
+               output fold_string($manpage_title);
+       } else {
+               output uc(fold_string($manpage_title));
+       }
+       
+       output  '" "', fold_string($manpage_sect), 
+               '" "', fold_string(`date "+%d %B %Y"`), 
+               '" "', $manpage_misc, 
+               '" "', $manpage_manual, 
+               "\"\n";
+
+       $newline_last = 1;
+
+       # References to this RefEntry.
+       my $id = $_[0]->parent->attribute('ID')->value;
+       if($id ne '') {
+               # The 'package name' part of the section should
+               # not be used when citing it.
+               my ($sectnum) = ($manpage_sect =~ /([0-9]*)/);
+               
+               if($_[0]->parent->attribute('XREFLABEL')->value eq '') {
+                       $Refs->put("refentry:$id", "$manpage_title($sectnum)");
+               } else {
+                       $Refs->put("refentry:$id",
+                               $_[0]->parent->attribute('XREFLABEL')->value . 
+                               "($sectnum)");
+               }
+       }
+});
+
+sgml('<REFENTRYTITLE>', sub { 
+       if($_[0]->in('REFMETA')) { 
+               save_cdata();
+       } else { 
+               # Manpage citations are in bold.
+               bold_on();
+       }
+});
+sgml('</REFENTRYTITLE>', sub { 
+       if($_[0]->in('REFMETA')) {
+               $raw_cdata--;
+               $manpage_title = pop_output();
+       }
+       else { font_off(); }
+});
+
+sgml('<MANVOLNUM>', sub { 
+       if($_[0]->in('REFMETA')) { 
+               save_cdata();   
+       } else {
+               # Manpage citations use ().
+               output '(';
+       }
+});
+sgml('</MANVOLNUM>', sub { 
+       if($_[0]->in('REFMETA')) {
+               $raw_cdata--;
+               $manpage_sect = pop_output();
+       }
+       else { output ')' }
+});
+
+sgml('<REFMISCINFO>', \&save_cdata);
+sgml('</REFMISCINFO>', sub { 
+       $raw_cdata--;
+       $manpage_misc = fold_string(pop_output());
+});
+
+
+# NAME section
+man_sgml('<REFNAMEDIV>', "\n.SH NAME\n");
+
+sgml('<REFNAME>', \&save_cdata);
+sgml('</REFNAME>', sub { 
+       $raw_cdata--;
+       push(@manpage_names, pop_output());
+});
+
+sgml('<REFPURPOSE>', \&save_cdata);
+sgml('</REFPURPOSE>', sub { 
+       $raw_cdata--;
+       my $manpage_purpose = fold_string(pop_output());
+       
+       for(my $i = 0; $i < $#manpage_names; $i++) {
+               output fold_string($manpage_names[$i]), ', ';
+       }
+
+       output fold_string($manpage_names[$#manpage_names]);
+       output " \\- $manpage_purpose\n";
+
+       $newline_last = 1;
+
+       foreach(@manpage_names) {
+               # Don't link to itself
+               if($_ ne $manpage_title) {
+                       print LINKSFILE "$manpage_title.$manpage_sect   $_.$manpage_sect\n";
+               }
+       }
+});
+       
+man_sgml('<REFCLASS>', "\n.sp\n");
+
+#RefDescriptor
+
+
+
+
+
+########################################################################
+#
+# SYNOPSIS section and synopses
+#
+########################################################################
+
+man_sgml('<REFSYNOPSISDIV>', "\n.SH SYNOPSIS\n");
+man_sgml('</REFSYNOPSISDIV>', "\n");
+
+## FIXME! Must be made into block elements!!
+#sgml('<FUNCSYNOPSIS>', \&bold_on);
+#sgml('</FUNCSYNOPSIS>', \&font_off);
+#sgml('<CMDSYNOPSIS>', \&bold_on);
+#sgml('</CMDSYNOPSIS>', \&font_off);
+
+man_sgml('<FUNCSYNOPSIS>', sub {
+       man_output("\n.sp\n");
+       bold_on();
+});
+man_sgml('</FUNCSYNOPSIS>', sub {
+       font_off();
+       man_output("\n");
+});
+
+man_sgml('<CMDSYNOPSIS>', "\n\n");
+man_sgml('</CMDSYNOPSIS>', "\n\n");
+
+man_sgml('<FUNCPROTOTYPE>', "\n.sp\n");
+
+# Arguments to functions.  This is C convention.
+sub paramdef
+{
+       if($_[0]->parent->ext->{'inparams'}) {
+               output ', ';
+       } else {
+               output ' (';
+               $_[0]->parent->ext->{'inparams'} = 1;
+       }
+}
+man_sgml('<PARAMDEF>', \&paramdef);
+man_sgml('</FUNCPROTOTYPE>', ");\n");
+man_sgml('<VOID>', "(void");
+man_sgml('<VARARGS>', "(...");
+
+
+
+sub group_start
+{
+       if(not $_[0]->parent->in('TERM')) {
+               if($_[0]->attribute('CHOICE')->value =~ /opt/i) {
+                       output ' [';
+               } elsif($_[0]->attribute('CHOICE')->value =~ /req/i) {
+                       output ' {';
+               }
+       }
+       $_[0]->ext->{'count'} = 1;
+}
+sub group_end
+{
+       if($_[0]->attribute('REP')->value =~ /^Repeat/i) {
+               italic_on();
+               output ' ...';
+               font_off();
+       }
+       if(not $_[0]->parent->in('TERM')) {
+               if($_[0]->attribute('CHOICE')->value =~ /opt/i) {
+                       output ' ]';
+               } elsif($_[0]->attribute('CHOICE')->value =~ /req/i) {
+                       output ' }';
+               }
+       }
+}
+
+sub arg_start
+{
+       # my $choice = $_[0]->attribute('CHOICE')->value;
+
+       # The content model for CmdSynopsis doesn't include #PCDATA,
+       # so we won't see any of the whitespace in the source file,
+       # so we have to add it after each component.
+       output ' ';
+
+       if($_[0]->in('GROUP')) {
+               output '| ' if $_[0]->parent->ext->{'count'} > 1;
+               $_[0]->parent->ext->{'count'}++;
+       } elsif($_[0]->attribute('CHOICE')->value =~ /opt/i) {
+               output '[ ';
+       }
+       bold_on();
+}
+sub arg_end
+{
+       font_off();
+       if($_[0]->attribute('REP')->value =~ /^Repeat/i) {
+               italic_on();
+               output ' ...';
+               font_off();
+       }
+       if($_[0]->attribute('CHOICE')->value =~ /opt/i and
+           not $_[0]->in('GROUP')) {
+               output ' ]';
+       }
+}
+
+sgml('<ARG>', \&arg_start);
+sgml('</ARG>', \&arg_end);
+sgml('<GROUP>', \&group_start);
+sgml('</GROUP>', \&group_end);
+
+sgml('<OPTION>', \&bold_on);
+sgml('</OPTION>', \&font_off);
+
+man_sgml('<SBR>', "\n   ");
+
+
+########################################################################
+#
+# General sections
+#
+########################################################################
+
+# The name of the section is handled by TITLE.  This just sets
+# up the roff markup.
+man_sgml('<REFSECT1>', "\n.SH ");
+man_sgml('<REFSECT2>', "\n.SS ");
+man_sgml('<REFSECT3>', "\n.SS ");
+
+
+########################################################################
+#
+# Titles, metadata.
+#
+########################################################################
+
+sgml('<TITLE>', sub {
+       if($_[0]->in('REFERENCE') or $_[0]->in('BOOK')) {
+               $write_manpages = 1;
+       }
+       save_cdata();
+});
+sgml('</TITLE>', sub { 
+       my $title = fold_string(pop_output());
+       $raw_cdata--;
+       
+       if($_[0]->in('REFERENCE') or $_[0]->in('BOOK')) {
+               # We use TITLE of enclosing Reference or Book as manual name
+               $manpage_manual = $title;
+               $write_manpages = 0;
+       }
+       elsif(exists $_[0]->parent->ext->{'title'}) {
+               # By far the easiest case.  Just fold the string as
+               # above, and then set the parent element's variable.
+               $_[0]->parent->ext->{'title'} = $title;
+       }
+       else {
+               # If the parent element's handlers are lazy, 
+               # output the folded string for them :)
+               # We assume they want uppercase and a newline.
+               output '"', uc($title), "\"\n";
+               $newline_last = 1;
+       }
+});
+
+sgml('<ATTRIBUTION>', sub { push_output('string') });
+sgml('</ATTRIBUTION>', sub { $_[0]->parent->ext->{'attribution'} = pop_output(); });
+
+
+# IGNORE.
+sgml('<DOCINFO>', sub { push_output('nul'); });
+sgml('</DOCINFO>', sub { pop_output(); });
+sgml('<REFSECT1INFO>', sub { push_output('nul'); });
+sgml('</REFSECT1INFO>', sub { pop_output(); });
+sgml('<REFSECT2INFO>', sub { push_output('nul'); });
+sgml('</REFSECT2INFO>', sub { pop_output(); });
+sgml('<REFSECT3INFO>', sub { push_output('nul'); });
+sgml('</REFSECT3INFO>', sub { pop_output(); });
+
+sgml('<INDEXTERM>', sub { push_output('nul'); });
+sgml('</INDEXTERM>', sub { pop_output(); });
+
+
+########################################################################
+#
+# Set bold on enclosed content 
+#
+########################################################################
+
+sgml('<APPLICATION>', \&bold_on);      sgml('</APPLICATION>', \&font_off);
+
+sgml('<CLASSNAME>', \&bold_on);                sgml('</CLASSNAME>', \&font_off);
+sgml('<STRUCTNANE>', \&bold_on);       sgml('</STRUCTNAME>', \&font_off);
+sgml('<STRUCTFIELD>', \&bold_on);      sgml('</STRUCTFIELD>', \&font_off);
+sgml('<SYMBOL>', \&bold_on);           sgml('</SYMBOL>', \&font_off);
+sgml('<TYPE>', \&bold_on);             sgml('</TYPE>', \&font_off);
+
+sgml('<ENVAR>', \&bold_on);    sgml('</ENVAR>', \&font_off);
+
+sgml('<FUNCTION>', \&bold_on); sgml('</FUNCTION>', \&font_off);
+
+sgml('<EMPHASIS>', \&bold_on); sgml('</EMPHASIS>', \&font_off);
+
+sgml('<ERRORNAME>', \&bold_on);        sgml('</ERRORNAME>', \&font_off);
+# ERRORTYPE
+
+sgml('<COMMAND>', \&bold_on);  sgml('</COMMAND>', \&font_off);
+
+sgml('<GUIBUTTON>', \&bold_on);        sgml('</GUIBUTTON>', \&font_off);
+sgml('<GUIICON>', \&bold_on);  sgml('</GUIICON>', \&font_off);
+# GUILABEL
+# GUIMENU
+# GUIMENUITEM
+# GUISUBMENU
+# MENUCHOICE
+# MOUSEBUTTON
+
+sgml('<ACCEL>', \&bold_on);    sgml('</ACCEL>', \&font_off);
+sgml('<KEYCAP>', \&bold_on);   sgml('</KEYCAP>', \&font_off);
+sgml('<KEYSYM>', \&bold_on);   sgml('</KEYSYM>', \&font_off);
+# KEYCODE
+# KEYCOMBO
+# SHORTCUT
+
+sgml('<USERINPUT>', \&bold_on);        sgml('</USERINPUT>', \&font_off);
+
+sgml('<INTERFACEDEFINITION>', \&bold_on);
+sgml('</INTERFACEDEFINITION>', \&font_off);
+
+# May need to look at the CLASS
+sgml('<SYSTEMITEM>', \&bold_on);
+sgml('</SYSTEMITEM>', \&font_off);
+
+
+
+
+
+########################################################################
+#
+# Set italic on enclosed content 
+#
+########################################################################
+
+sgml('<FIRSTTERM>', \&italic_on);      sgml('</FIRSTTERM>', \&font_off);
+
+sgml('<FILENAME>', \&italic_on);       sgml('</FILENAME>', \&font_off);
+sgml('<PARAMETER>', \&italic_on);      sgml('</PARAMETER>', \&font_off);
+sgml('<PROPERTY>', \&italic_on);       sgml('</PROPERTY>', \&font_off);
+
+sgml('<REPLACEABLE>', sub {
+       italic_on();
+       if($_[0]->in('TOKEN')) {
+               # When tokenizing, follow more 'intuitive' convention
+               output "<";
+       }
+});
+sgml('</REPLACEABLE>', sub {
+       if($_[0]->in('TOKEN')) {
+               output ">";
+       }
+       font_off();
+});
+
+sgml('<CITETITLE>', \&italic_on);      sgml('</CITETITLE>', \&font_off);
+sgml('<FOREIGNPHRASE>', \&italic_on);  sgml('</FOREIGNPHRASE>', \&font_off);
+
+sgml('<LINEANNOTATION>', \&italic_on); sgml('</LINEANNOTATION>', \&font_off);
+
+
+
+
+
+
+########################################################################
+#
+# Other 'inline' elements 
+#
+########################################################################
+
+man_sgml('<EMAIL>', '<');
+man_sgml('</EMAIL>', '>');
+man_sgml('<OPTIONAL>', '[');
+man_sgml('</OPTIONAL>', ']');
+
+man_sgml('</TRADEMARK>', "\\u\\s-2TM\\s+2\\d");
+
+man_sgml('<COMMENT>', "[Comment: ");
+man_sgml('</COMMENT>', "]");
+
+man_sgml('<QUOTE>', "``");
+man_sgml('</QUOTE>', "''");
+
+#man_sgml('<LITERAL>', '"');
+#man_sgml('</LITERAL>', '"');
+
+# No special presentation:
+
+# AUTHOR
+# AUTHORINITIALS
+
+# ABBREV
+# ACTION
+# ACRONYM
+# ALT
+# CITATION
+# PHRASE
+# QUOTE
+# WORDASWORD
+
+# COMPUTEROUTPUT
+# MARKUP
+# PROMPT
+# RETURNVALUE
+# SGMLTAG
+# TOKEN
+
+# DATABASE
+# HARDWARE
+# INTERFACE
+# MEDIALABEL
+
+# There doesn't seem to be a good way to represent LITERAL in -man
+
+
+
+########################################################################
+#
+# Paragraph and paragraph-like elements 
+#
+########################################################################
+
+sub para_start {
+       output "\n" unless $newline_last++;
+
+       # In lists, etc., don't start paragraph with .PP since
+       # the indentation will be gone.
+
+       if($_[0]->parent->ext->{'nobreak'}==1) {
+               # Usually this is the FIRST element of
+               # a hanging tag, so we MUST not do a full
+               # paragraph break.
+               $_[0]->parent->ext->{'nobreak'} = 2;
+       } elsif($_[0]->parent->ext->{'nobreak'}==2) {
+               # Usually these are the NEXT elements of
+               # a hanging tag.  If we break using a blank
+               # line, we're okay.
+               output "\n";
+       } else {
+               # Normal case. (For indented blocks too, at least
+               # -man isn't so braindead in this area.)
+               output ".PP\n";
+       }
+}
+# Actually applies to a few other block elements as well
+sub para_end {
+       output "\n" unless $newline_last++; 
+}
+
+sgml('<PARA>', \&para_start);
+sgml('</PARA>', \&para_end);
+sgml('<SIMPARA>', \&para_start);
+sgml('</SIMPARA>', \&para_end);
+
+# Nothing special, except maybe FIXME set nobreak.
+sgml('<INFORMALEXAMPLE>', \&para_start);
+sgml('</INFORMALEXAMPLE>', \&para_end);
+
+
+
+
+
+########################################################################
+#
+# Blocks using SS sections
+#
+########################################################################
+
+# FIXME: We need to consider the effects of SS
+# in a hanging tag :(
+
+# Complete with the optional-title dilemma (again).
+sgml('<ABSTRACT>', sub {
+       $_[0]->ext->{'title'} = 'ABSTRACT';
+       output "\n" unless $newline_last++;
+       push_output('string');
+});
+sgml('</ABSTRACT>', sub {
+       my $content = pop_output();
+       
+       # As ABSTRACT is never on the same level as RefSect1,
+       # this leaves us with only .SS in terms of -man macros.
+       output ".SS \"", uc($_[0]->ext->{'title'}), "\"\n";
+
+       output $content;
+       output "\n" unless $newline_last++;
+});
+
+# Ah, I needed a break.  Example always has a title.
+man_sgml('<EXAMPLE>', "\n.SS ");
+sgml('</EXAMPLE>', \&para_end);
+
+# Same with sidebar.
+man_sgml('<SIDEBAR>', "\n.SS ");
+sgml('</SIDEBAR>', \&para_end);
+
+# NO title.
+man_sgml('<HIGHLIGHTS>', "\n.SS HIGHLIGHTS\n");
+sgml('</HIGHLIGHTS>', \&para_end);
+
+
+
+
+########################################################################
+#
+# Indented 'Block' elements 
+#
+########################################################################
+
+sub indent_block_start
+{
+       output "\n" unless $newline_last++;
+       output ".sp\n.RS\n";
+}
+sub indent_block_end
+{
+       output "\n" unless $newline_last++;
+       output ".RE\n";
+}
+
+# This element is almost like an admonition (below),
+# only the default title is blank :)
+
+sgml('<BLOCKQUOTE>', sub { 
+       $_[0]->ext->{'title'} = ''; 
+       output "\n" unless $newline_last++;
+       push_output('string');
+});
+sgml('</BLOCKQUOTE>', sub {
+       my $content = pop_output();
+
+       indent_block_start();
+       
+       if($_[0]->ext->{'title'}) {
+               output ".B \"", $_[0]->ext->{'title'}, ":\"\n";
+       }
+       
+       output $content;
+
+       if($_[0]->ext->{'attribution'}) {
+               output "\n" unless $newline_last++;
+               # One place where roff's space-sensitivity makes sense :)
+               output "\n                -- ";
+               output $_[0]->ext->{'attribution'} . "\n";
+       }
+       
+       indent_block_end();
+});
+
+# Set off admonitions from the rest of the text by indenting.
+# FIXME: Need to check if this works inside paragraphs, not enclosing them.
+sub admonition_end {
+       my $content = pop_output();
+
+       indent_block_start();
+       
+       # When the admonition is only one paragraph,
+       # it looks nicer if the title was inline.
+       my $num_para;
+       while ($content =~ /^\.PP/gm) { $num_para++ }
+       if($num_para==1) {
+               $content =~ s/^\.PP\n//;
+       }
+       
+       output ".B \"" . $_[0]->ext->{'title'} . ":\"\n";
+       output $content;
+       
+       indent_block_end();
+}
+
+sgml('<NOTE>', sub {
+       # We can't see right now whether or not there is a TITLE
+       # element, so we have to save the output now and add it back
+       # at the end of this admonition.
+       $_[0]->ext->{'title'} = 'Note';
+
+       # Although admonition_end's indent_block_start will do this,
+       # we need to synchronize the output _now_
+       output "\n" unless $newline_last++;
+
+       push_output('string');
+});
+sgml('</NOTE>', \&admonition_end);
+
+# Same as above.
+sgml('<WARNING>', sub { 
+       $_[0]->ext->{'title'} = 'Warning'; 
+       output "\n" unless $newline_last++;
+       push_output('string');
+});
+sgml('</WARNING>', \&admonition_end);
+
+sgml('<TIP>', sub {
+       $_[0]->ext->{'title'} = 'Tip';
+       output "\n" unless $newline_last++;
+       push_output('string');
+});
+sgml('</TIP>', \&admonition_end);
+sgml('<CAUTION>', sub {
+       $_[0]->ext->{'title'} = 'Caution';
+       output "\n" unless $newline_last++;
+       push_output('string');
+});
+sgml('</CAUTION>', \&admonition_end);
+
+sgml('<IMPORTANT>', sub {
+       $_[0]->ext->{'title'} = 'Important';
+       output "\n" unless $newline_last++;
+       push_output('string');
+});
+sgml('</IMPORTANT>', \&admonition_end);
+
+
+
+
+
+
+
+
+
+
+
+
+########################################################################
+#
+# Verbatim displays. 
+#
+########################################################################
+
+sub verbatim_start {
+       output "\n" unless $newline_last++;
+       
+       if($_[0]->parent->ext->{'nobreak'}==1) {
+               # Usually this is the FIRST element of
+               # a hanging tag, so we MUST not do a full
+               # paragraph break.
+               $_[0]->parent->ext->{'nobreak'} = 2;
+       } else {
+               output "\n";
+       }
+       
+       output(".nf\n") unless $nocollapse_whitespace++;
+}
+
+sub verbatim_end {
+       output "\n" unless $newline_last++;
+       output(".fi\n") unless --$nocollapse_whitespace;
+}
+
+sgml('<PROGRAMLISTING>', \&verbatim_start); 
+sgml('</PROGRAMLISTING>', \&verbatim_end);
+
+sgml('<SCREEN>', \&verbatim_start); 
+sgml('</SCREEN>', \&verbatim_end);
+
+sgml('<LITERALLAYOUT>', \&verbatim_start); 
+sgml('</LITERALLAYOUT>', \&verbatim_end);
+
+#sgml('<SYNOPSIS>', sub {
+#      if($_[0]->attribute('FORMAT')->value =~ /linespecific/i) {
+#              &verbatim_start;
+#      } else {
+#              roffcmd("");
+#      }
+#});
+#
+#sgml('</SYNOPSIS>', sub {
+#      if($_[0]->attribute('FORMAT')->value =~ /linespecific/i) {
+#              &verbatim_end;
+#      }
+#      else {
+#              roffcmd("");# not sure about this.
+#      }
+#});
+sgml('<SYNOPSIS>', \&verbatim_start);
+sgml('</SYNOPSIS>', \&verbatim_end);
+
+
+
+
+
+
+
+
+
+########################################################################
+#
+# Lists
+#
+########################################################################
+
+# Indent nested lists.
+sub indent_list_start {
+       if($list_nestlevel++) {
+               output "\n" unless $newline_last++;
+               output ".RS\n";
+       }
+}
+sub indent_list_end {
+       if(--$list_nestlevel) {
+               output "\n" unless $newline_last++;
+               output ".RE\n";
+       }
+}
+
+sgml('<VARIABLELIST>', \&indent_list_start);
+sgml('</VARIABLELIST>', \&indent_list_end);
+sgml('<ITEMIZEDLIST>', \&indent_list_start);
+sgml('</ITEMIZEDLIST>', \&indent_list_end);
+sgml('<ORDEREDLIST>', sub { 
+       indent_list_start();
+       $_[0]->ext->{'count'} = 1;
+});
+sgml('</ORDEREDLIST>', \&indent_list_end);
+sgml('<GLOSSLIST>', \&indent_list_start);
+sgml('</GLOSSLIST>', \&indent_list_end);
+               
+# Output content on one line, bolded.
+sgml('<TERM>', sub { 
+       output "\n" unless $newline_last++;
+       output ".TP\n";
+       bold_on();
+       push_output('string');
+});
+sgml('</TERM>', sub { 
+       my $term = pop_output();
+       $term =~ tr/\n/ /;
+       output $term;
+       font_off();
+       output "\n";
+       $newline_last = 1;
+});
+sgml('<GLOSSTERM>', sub { 
+       output "\n" unless $newline_last++;
+       output ".TP\n";
+       bold_on();
+       push_output('string');
+});
+sgml('</GLOSSTERM>', sub { 
+       my $term = pop_output();
+       $term =~ tr/\n/ /;
+       output $term;
+       font_off();
+       output "\n";
+       $newline_last = 1;
+});
+       
+sgml('<LISTITEM>', sub {
+       # A bulleted list.
+       if($_[0]->in('ITEMIZEDLIST')) {
+               output "\n" unless $newline_last++;
+               output ".TP 0.2i\n\\(bu\n";
+       }
+
+       # Need numbers.
+       # Assume Arabic numeration for now.
+       elsif($_[0]->in('ORDEREDLIST')) {
+               output "\n" unless $newline_last++;
+               output ".TP 3\n", $_[0]->parent->ext->{'count'}++, ". \n";
+       }
+       
+       $_[0]->ext->{'nobreak'} = 1;
+});
+sgml('<GLOSSDEF>', sub {
+       $_[0]->ext->{'nobreak'} = 1;
+});
+
+sgml('<SIMPLELIST>', sub {
+       $_[0]->ext->{'first_member'} = 1;
+});
+
+sgml('<MEMBER>', sub {
+       my $parent = $_[0]->parent;
+       
+       if($parent->attribute('TYPE')->value =~ /Inline/i) {
+               if($parent->ext->{'first_member'}) { 
+                       # If this is the first member don't put any commas
+                       $parent->ext->{'first_member'} = 0;
+               } else {
+                       output ", ";
+               }
+       } elsif($parent->attribute('TYPE')->value =~ /Vert/i) {
+               output "\n" unless $newline_last++;
+               output "\n";
+       }
+});
+
+
+
+
+
+########################################################################
+#
+# Stuff we don't know how to handle (yet) 
+#
+########################################################################
+
+# Address blocks:
+
+# Credit stuff:
+# ACKNO
+# ADDRESS
+# AFFILIATION
+# ARTPAGENUMS
+# ATTRIBUTION
+# AUTHORBLURB
+# AUTHORGROUP
+# OTHERCREDIT
+# HONORIFIC
+
+# Areas:
+# AREA
+# AREASET
+# AREASPEC
+
+
+
+
+
+########################################################################
+#
+# Linkage, cross references
+#
+########################################################################
+
+# Print the URL
+sgml('</ULINK>', sub {
+       output ' <URL:', $_[0]->attribute('URL')->value, '>';
+       $newline_last = 0;
+});
+
+# If cross reference target is a RefEntry, 
+# output CiteRefEntry-style references.
+sgml('<XREF>', sub {
+       my $id = $_[0]->attribute('LINKEND')->value;
+       my $manref = $Refs->get("refentry:$id");
+
+       if($manref) {
+               my ($title, $sect) = ($manref =~ /(.*)(\(.*\))/);
+               bold_on();
+               output $title;
+               font_off();
+               output $sect;
+       } else {
+               $blank_xrefs++ if $write_manpages;
+               output "[XRef to $id]";
+       }
+
+       $newline_last = 0;
+});
+
+# Anchor
+
+
+
+
+########################################################################
+#
+# Other handlers 
+#
+########################################################################
+
+man_sgml('|[lt    ]|', '<');
+man_sgml('|[gt    ]|', '>');
+man_sgml('|[amp   ]|', '&');
+
+#
+# Default handlers (uncomment these if needed).  Right now, these are set
+# up to gag on any unrecognised elements, sdata, processing-instructions,
+# or entities.
+#
+# sgml('start_element',sub { die "Unknown element: " . $_[0]->name; });
+# sgml('end_element','');
+
+# This is for weeding out and escaping certain characters.
+# This looks like it's inefficient since it's done on every line, but
+# in reality, SGMLSpm and sgmlspl parsing ESIS takes _much_ longer.
+
+sgml('cdata', sub
+{ 
+       if(!$write_manpages) { return; }
+       elsif($raw_cdata) { output $_[0]; return; }
+       
+       # Escape backslashes
+       $_[0] =~ s/\\/\\\\/g;
+
+       # In non-'pre'-type elements:
+       if(!$nocollapse_whitespace) {
+               # Change tabs to spaces
+               $_[0] =~ tr/\t/ /;
+
+               # Do not allow indents at beginning of line
+               # groff chokes on that.
+               if($newline_last) { 
+                       $_[0] =~ s/^ +//;
+
+                       # If the line is all blank, don't do anything.
+                       if($_[0] eq '') { return; }
+                       
+                       $_[0] =~ s/^\./\\\&\./;
+
+                       # Argh... roff doesn't like ' either...
+                       $_[0] =~ s/^\'/\\\&\'/;
+               }
+       }
+
+       $newline_last = 0;
+
+       output $_[0];
+});
+
+
+# When in whitespace-collapsing mode, we disallow consecutive newlines.
+
+sgml('re', sub
+{
+       if($nocollapse_whitespace || !$newline_last) {
+               output "\n";
+       }
+
+       $newline_last = 1;
+});
+
+sgml('sdata',sub
+{
+       if($_[0] =~ /\[minus \]/) { output "-"; }
+       elsif($_[0] =~ /\[copy  \]/) { output "(C)"; }
+       else { die "Unknown SDATA: " . $_[0]; }
+});
+sgml('pi',sub { die "Unknown processing instruction: " . $_[0]; });
+sgml('entity',sub { die "Unknown external entity: " . $_[0]->name; });
+sgml('start_subdoc',sub { die "Unknown subdoc entity: " . $_[0]->name; });
+sgml('end_subdoc','');
+sgml('conforming','');
+
+1;
+
diff --git a/utils/docbook2man/docbook2man-spec.pl.1 b/utils/docbook2man/docbook2man-spec.pl.1
new file mode 100644 (file)
index 0000000..4d2bf3b
--- /dev/null
@@ -0,0 +1,99 @@
+.\" This manpage has been automatically generated by docbook2man 
+.\" from a DocBook document.  This tool can be found at:
+.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/> 
+.\" Please send any bug reports, improvements, comments, patches, 
+.\" etc. to Steve Cheng <steve@ggi-project.org>.
+.TH "DOCBOOK2MAN-SPEC.PL" "1" "27 June 2002" "" ""
+.SH NAME
+docbook2man-spec.pl \- convert DocBook RefEntries to man pages
+.SH SYNOPSIS
+
+\fBsgmlspl\fR \fBdocbook2man-spec.pl\fR
+
+
+\fBnsgmls\fR [ \fB\fIsgml document\fB\fR ]\fB| sgmlspl\fR \fBdocbook2man-spec.pl\fR
+
+.SH "DESCRIPTION"
+.PP
+\fBdocbook2man\fR is a sgmlspl spec file that produced man
+pages (using the -man macros) from DocBook RefEntry markup.
+.PP
+The program reads ESIS produced by nsgmls (or other SGML parsers) from
+standard input.  Markup not found in RefEntry is discarded.
+.PP
+Its output, the converted man pages, are written to the current directory.  If
+RefMeta information is not specified in a
+RefEntry, then the man page will be written to standard
+output.
+.PP
+The file \fImanpage.links\fR will also be created, which contains
+any aliases of the manpages generated.  This file is in the format:
+
+.nf
+\fI<man page>\fR \fI<alias
+manpage>\fR
+.fi
+.PP
+The \fImanpage.refs\fR file keeps track of
+XRef references.  Note that if the input document has any
+forward references, then \fBdocbook2man\fR may have to be
+invoked twice (the first time updating \fImanpage.refs\fR) to
+resolve them.
+.SH "REQUIREMENTS"
+
+The SGMLSpm package from CPAN.  This package includes the sgmlspl script
+that is also needed.
+.SH "LIMITATIONS"
+.PP
+Trying \fBdocbook2man\fR on non-DocBook or non-conformant
+SGML results in undefined behavior. :-)
+.PP
+This program is a slow, dodgy Perl script.
+.PP
+This program does not come close to supporting all the possible markup
+in DocBook, and may produce wrong output in some cases with supported
+markup.
+.SH "TO DO"
+.PP
+Obvious stuff:
+.TP 0.2i
+\(bu
+Fix \fBdocbook2man\fR breakages found in
+the test documents, especially
+\fIweird.sgml\fR.
+.TP 0.2i
+\(bu
+Add new element handling and fix existing handling.  
+Be robust.  
+.TP 0.2i
+\(bu
+Produce cleanest, readable man output as possible (unlike some
+other converters).  Follow Linux
+\fBman\fR(7)
+convention.  As conversion to man pages is usually not done very often, it is
+better to be slower/more complicated than to produce wrong output.  Also if
+someone wants to give up using DocBook for whatever reason, the last-converted
+man pages can then be maintained manually.  
+.TP 0.2i
+\(bu
+Make it faster. I think most of the speed problems so far is with parsing
+ESIS.  Rewrite \fISGMLS.pm\fR with C and/or get input directly
+from \fBSP\fR.
+.TP 0.2i
+\(bu
+Support other (human) languages.  But what to do with non-ASCII charsets?
+SGMLSpm doesn't report them and \fBroff\fR does not grok them.
+[Comment: text after enclosed lists (and SS blocks) will break docbook2man]
+If we do this, more people can use DocBook.
+.SH "COPYRIGHT"
+.PP
+Copyright (C) 1998-1999 Steve Cheng <steve@ggi-project.org>
+.PP
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+.PP
+You should have received a copy of the GNU General Public License along with
+this program; see the file \fICOPYING\fR.  If not, please write
+to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.