TIVI-153: add as dependency for iputils
[profile/ivi/docbook-utils.git] / packaging / docbook2man-spec.pl
1 =head1 NAME
2
3 docbook2man-spec.pl - convert DocBook RefEntries to Unix manpages
4
5 =head1 SYNOPSIS
6
7 The sgmlspl script from the SGMLSpm Perl module must be used to run
8 this script.  Use it like this:
9
10 nsgmls some-docbook-document.sgml | sgmlspl docbook2man-spec.pl
11
12 See man page or included DocBook documentation for details.
13
14 =head1 DESCRIPTION
15
16 This is a sgmlspl spec file that produces Unix-style
17 man pages from DocBook RefEntry markup.
18
19 =head1 COPYRIGHT
20
21 Copyright (C) 1998-2001 Steve Cheng <stevecheng@users.sourceforge.net>
22
23 Copyright (C) 1999 Thomas Lockhart <lockhart@alumni.caltech.edu>
24
25 This program is free software; you can redistribute it and/or modify it
26 under the terms of the GNU General Public License as published by the Free
27 Software Foundation; either version 2, or (at your option) any later
28 version.
29
30 You should have received a copy of the GNU General Public License along with
31 this program; see the file COPYING.  If not, please write to the Free
32 Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
33
34 =cut
35
36 # $Id: docbook2man-spec.pl,v 1.2 2009/07/24 13:30:48 ovasik Exp $
37
38 use SGMLS;                      # Use the SGMLS package.
39 use SGMLS::Output;              # Use stack-based output.
40 use SGMLS::Refs;
41
42
43 ########################################################################
44 # SGMLSPL script produced automatically by the script sgmlspl.pl
45 #
46 # Document Type: any, but processes only RefEntries
47 # Edited by: me :)
48 ########################################################################
49
50
51 $write_manpages = 0;
52 $blank_xrefs = 0;
53
54 $default_sect = "1";
55 $default_date = `date "+%d %B %Y"`;
56 $cite_numeral_only = 1;
57
58 while (@ARGV) {
59         my $arg = shift @ARGV;
60         if ($arg eq "--section") {
61                 $default_sect = shift @ARGV || die "$arg requires an argument\n";
62         } elsif ($arg eq "--date") {
63                 $default_date = shift @ARGV || die "$arg requires an argument\n";
64         } elsif ($arg eq "--lowercase") {
65                 $lowercase_names = 1;
66         } elsif ($arg eq "--preserve-case") {
67                 $lowercase_names = 0;
68         } elsif ($arg eq "--cite-numeral-only") {
69                 $cite_numeral_only = 1;
70         } elsif ($arg eq "--nocite-numeral-only") {
71                 $cite_numeral_only = 0;
72         } elsif ($arg eq "--help") {
73                 print "Usage: $0",
74                         " [ --section <label> ]",
75                         " [ --date <string> ]",
76                         " [ --lowercase | --preserve-case ]",
77                         " [ --cite-numeral-only | --nocite-numeral-only ]",
78                         "\n";
79                 exit;
80         } else {
81                 die "unrecognized switch $arg; try $0 --help\n";
82         }
83 }
84
85 sgml('start', sub { 
86         push_output('nul');
87         $raw_cdata = 1;                 # Makes it a bit faster.
88         
89         # Links file
90         open(LINKSFILE, ">manpage.links");
91
92         $Refs = new SGMLS::Refs("manpage.refs", "manpage.log");
93 });
94 sgml('end', sub {
95         close(LINKSFILE);
96
97         # Explicitly invoke destructor,
98         # otherwise cache file may not get written!
99         # Thomas Lockhart, 1999-08-03, perl-5.004, RedHat5.2
100         undef $Refs;
101
102         if($blank_xrefs) {
103                 warn "Warning: output contains unresolved XRefs\n";
104         }
105 });
106
107
108 ########################################################################
109 #
110 # Output helpers 
111 #
112 ########################################################################
113
114 # Remove leading and trailing blanks.
115
116 sub StripString
117 {
118         my $str = shift;
119
120         $str = $1 if ($str =~ m#^\s*(\S.*)#);
121         $str = $1 if ($str =~ m#^(.*\S)\s*$#);
122
123         return $str;
124 }
125
126 # Generate a good file name, for given manpage title and manvolnum
127 # (cdata content).
128 # Cleanup whitespace and convert to lower case if required.
129
130 sub FileInfo
131 {
132         my $title = StripString(shift);
133         my $volnum = StripString(shift);
134
135         $title = lc $title if $lowercase_names;
136
137         $title =~ tr/ /_/;
138         $volnum =~ tr/ /_/;
139
140         my $sectcite = $volnum;
141         # The 'package name' part of the section should
142         # not be used when citing it.
143         if ($cite_numeral_only) {
144                 $sectcite = $1 if ($volnum =~ /^([0-9]+)/);
145         }
146         
147         return ("$title.$volnum", "$title($sectcite)");
148 }
149
150 # Our own version of sgml() and output() to allow simple string output
151 # to play well with roff's stupid whitespace rules. 
152
153 sub man_sgml
154 {
155         if(ref($_[1]) eq 'CODE') {
156                 return &sgml;
157         }
158         
159         my $s = $_[1];
160         $s =~ s/\\/\\\\/g;
161         $s =~ s/'/\\'/g;
162
163         sgml($_[0], eval("sub { man_output '$s' }"));
164 }
165
166 sub man_output
167 {
168         if($separator eq 'full') {
169                 output "\n" unless $newline_last++;
170                 output ".PP\n";
171                 $separator = '';
172         }
173         
174         $_ = shift;
175         if(s/^\n//) {
176                 output "\n" unless $newline_last++;
177         }
178         return if $_ eq '';
179         
180         output $_;
181
182         if(@_) {
183                 output @_;
184                 $newline_last = (pop(@_) =~ /\n$/);
185         } else {
186                 $newline_last = ($_ =~ /\n$/)
187         }
188 }
189
190 # Fold lines into one, quote some characters
191 sub fold_string
192 {
193         $_ = shift;
194         
195         s/\\/\\\\/g;
196         s/"/\\\&"/g;
197
198         # Change tabs and newlines to spaces
199         # The newlines will be swallowed later while trimming
200         tr/[\t\n]/  /;
201
202         # Trim whitespace from beginning and end.
203         s/^ +//;
204         s/ +$//;
205
206         return $_;
207 }
208         
209 sub save_cdata()
210 {
211         $raw_cdata++;
212         push_output('string');
213 }
214
215 sub bold_on()
216 {
217         # If the last font is also bold, don't change anything.
218         # Basically this is to just get more readable man output.
219         if($fontstack[$#fontstack] ne 'bold') {
220                 if(!$raw_cdata) {
221                         output '\fB';
222                         #$newline_last = 0;
223                 }
224         }
225         push(@fontstack, 'bold');
226 }
227
228 sub italic_on()
229 {
230         # If the last font is also italic, don't change anything.
231         if($fontstack[$#fontstack] ne 'italic') {
232                 if(!$raw_cdata) {
233                         output '\fI';
234                         #$newline_last = 0;
235                 }
236         }
237         push(@fontstack, 'italic');
238 }
239
240 sub font_off()
241 {
242         my $thisfont = pop(@fontstack);
243         my $lastfont = $fontstack[$#fontstack];
244         
245         # Only output font change if it is different
246         if($thisfont ne $lastfont) {
247                 if($raw_cdata)                  { return; }
248                 elsif($lastfont eq 'bold')      { output '\fB'; }
249                 elsif($lastfont eq 'italic')    { output '\fI'; }
250                 else                            { output '\fR'; }
251         
252                 #$newline_last = 0;
253         }
254 }
255
256
257 ########################################################################
258 #
259 # Manpage management
260 #
261 ########################################################################
262
263 sgml('<REFENTRY>', sub { 
264         # This will be overwritten at end of REFMETA, when we know the name of the page.
265         pop_output();
266         
267         $write_manpages = 1;            # Currently writing manpage.
268         
269         $nocollapse_whitespace = 0;     # Current whitespace collapse counter.
270         $newline_last = 1;              # At beginning of line?
271                 # Just a bit of warning, you will see this variable manipulated
272                 # manually a lot.  It makes the code harder to follow but it
273                 # saves you from having to worry about collapsing at the end of
274                 # parse, stopping at verbatims, etc.
275         $raw_cdata = 0;                 # Instructs certain output functions to
276                                         # leave CDATA alone, so we can assign
277                                         # it to a string and process it, etc.
278         @fontstack = ();                # Fonts being activated.
279         
280         $list_nestlevel = 0;            # Indent certain nested content.
281
282         # Separator to use between 'elements' in the content of a
283         # paragraph (usually).  This makes sure that PCDATA after a list
284         # in a PARA gets a break in between and not become part of the
285         # last listitem.  Note that we can't do it after the list ends,
286         # because often the list ends the paragraph and we'll get an
287         # extra break.  Anything that changes the separator status from
288         # the default should also save its last state in the parent
289         # element's ext, but I'm not going to explain further.  It's a
290         # gross hack and almost guaranteed to fail in unforseen cases.
291         # The only way to avoid all this is to use a tree/grove model, which
292         # we're _not_ doing.
293         $separator = '';
294         
295         $manpage_title = '';            # Needed for indexing.
296         $manpage_sect = '';
297         @manpage_names = ();
298         
299         $manpage_misc = '';
300
301         # check refentry's language
302         if(defined($_[0]->attribute('LANG')->value)) {
303           $manpage_lang = $_[0]->attribute('LANG')->value;
304         }
305         else {
306           $manpage_lang = '';
307         }
308 });
309 sgml('</REFENTRY>', sub {
310         if(!$newline_last) {
311                 output "\n";
312         }
313         
314         $raw_cdata = 1;
315         push_output('nul');
316
317         $write_manpages = 0;
318 });
319
320 sgml('</REFMETA>', sub {
321         my ($filename, $citation) = 
322                 FileInfo($manpage_title, $manpage_sect || $default_sect);
323
324         push_output('file', $filename);
325
326         output <<'_END_BANNER';
327 .\\" auto-generated by docbook2man-spec $Revision: 1.2 $
328 _END_BANNER
329
330         my $manpage_date = $_[0]->parent->ext->{'date'} || $default_date;
331
332         output '.TH "';
333
334         # If the title is not mixed-case, convention says to
335         # uppercase the whole title.  (The canonical title is
336         # lowercase.)
337         if($manpage_title =~ /[A-Z]/) {
338                 output fold_string($manpage_title);
339         } else {
340                 output uc(fold_string($manpage_title));
341         }
342         
343         output  '" "', fold_string($manpage_sect), 
344                 '" "', fold_string($manpage_date),
345                 '" "', $manpage_misc, 
346                 '" "', $manpage_manual, 
347                 "\"\n";
348
349         $newline_last = 1;
350
351         # References to this RefEntry.
352         if(defined($_[0]->parent->attribute('ID')->value)) {
353                 my $id = $_[0]->parent->attribute('ID')->value;
354
355                 # Append XREFLABEL content to citations.
356                 if(defined($_[0]->parent->attribute('XREFLABEL')->value)) {
357                         $citation = $_[0]->parent->attribute('XREFLABEL')->value .
358                                         ' [' . $citation . ']';
359                 }
360
361                 $Refs->put("refentry:$id", $citation);
362         }
363 });
364
365 sgml('<REFENTRYTITLE>', sub { 
366         if($_[0]->in('REFMETA')) { 
367                 save_cdata();
368         } else { 
369                 # Manpage citations are in bold.
370                 bold_on();
371         }
372 });
373 sgml('</REFENTRYTITLE>', sub { 
374         if($_[0]->in('REFMETA')) {
375                 $raw_cdata--;
376                 $manpage_title = pop_output();
377         }
378         else { font_off(); }
379
380         if (defined($_[0]->attribute('ID')->value)) {
381                 my $id = $_[0]->attribute('ID')->value;
382                 $Refs->put("refentrytitle:$id", $manpage_title);
383         }
384 });
385
386 sgml('<MANVOLNUM>', sub { 
387         if($_[0]->in('REFMETA')) { 
388                 save_cdata();   
389         } else {
390                 # Manpage citations use ().
391                 output '(';
392         }
393 });
394 sgml('</MANVOLNUM>', sub { 
395         if($_[0]->in('REFMETA')) {
396                 $raw_cdata--;
397                 $manpage_sect = pop_output();
398         }
399         else { output ')' }
400 });
401
402 sgml('<REFMISCINFO>', \&save_cdata);
403 sgml('</REFMISCINFO>', sub { 
404         $raw_cdata--;
405         $manpage_misc = fold_string(pop_output());
406 });
407
408
409 # NAME section
410 #man_sgml('<REFNAMEDIV>', "\n.SH NAME\n");
411 man_sgml('<REFNAMEDIV>', sub {
412         my %text = { fr=>'NOM', es=>'NOMBRE', pl=>'NAZWA' };
413         
414         if(defined $text{lc($manpage_lang)})
415         {
416                 man_output "\n.SH " . $text{lc($manpage_lang)} . "\n";
417         } elsif(defined $_[0]->attribute('LANG') and
418                 defined $text{lc($_[0]->attribute('LANG')->value)})
419         {
420                 man_output "\n.SH " . $text{lc($_[0]->attribute('LANG'))} . "\n";
421         } else {
422                 man_output "\n.SH NAME\n";
423         }
424 });
425
426 sgml('<REFNAME>', \&save_cdata);
427 sgml('</REFNAME>', sub { 
428         $raw_cdata--;
429         push(@manpage_names, pop_output());
430 });
431
432 sgml('<REFPURPOSE>', \&save_cdata);
433 sgml('</REFPURPOSE>', sub { 
434         $raw_cdata--;
435         my $manpage_purpose = fold_string(pop_output());
436         
437         for(my $i = 0; $i < $#manpage_names; $i++) {
438                 output fold_string($manpage_names[$i]), ', ';
439         }
440
441         output fold_string($manpage_names[$#manpage_names]);
442         output " \\- $manpage_purpose\n";
443
444         $newline_last = 1;
445
446         foreach(@manpage_names) {
447                 # Don't link to itself
448                 if($_ ne $manpage_title) {
449                         print LINKSFILE "$manpage_title.$manpage_sect   $_.$manpage_sect\n";
450                 }
451         }
452 });
453         
454 man_sgml('<REFCLASS>', "\n.sp\n");
455
456 #RefDescriptor
457
458
459 ########################################################################
460 #
461 # SYNOPSIS section and synopses
462 #
463 ########################################################################
464
465 #man_sgml('<REFSYNOPSISDIV>', "\n.SH SYNOPSIS\n");
466 man_sgml('<REFSYNOPSISDIV>', sub {
467            if ($manpage_lang eq "pl") { man_output "\n.SH SK£ADNIA\n"; }
468            # waits for another languages
469            #elsif ($manpage_lang eq "xx") { man_output "\n.SH xxxxxxx\n"; } 
470            else { man_output "\n.SH SYNOPSIS\n"; }
471 });   
472
473 man_sgml('</REFSYNOPSISDIV>', "\n");
474
475 ## FIXME! Must be made into block elements!!
476 #sgml('<FUNCSYNOPSIS>', \&bold_on);
477 #sgml('</FUNCSYNOPSIS>', \&font_off);
478 #sgml('<CMDSYNOPSIS>', \&bold_on);
479 #sgml('</CMDSYNOPSIS>', \&font_off);
480
481 man_sgml('<FUNCSYNOPSIS>', sub {
482         man_output("\n.nf\n");
483         bold_on();
484 });
485 man_sgml('</FUNCSYNOPSIS>', sub {
486         font_off();
487         man_output "\n.fi";
488 });
489
490 man_sgml('<CMDSYNOPSIS>', "\n.sp\n");
491 man_sgml('</CMDSYNOPSIS>', "\n");
492
493 man_sgml('<FUNCPROTOTYPE>', "\n.sp\n");
494
495 # Arguments to functions.  This is C convention.
496 man_sgml('<PARAMDEF>', '(');
497 man_sgml('</PARAMDEF>', ");\n");
498 man_sgml('<VOID>', "(void);\n");
499
500
501 sub arg_start
502 {
503         # my $choice = $_[0]->attribute('CHOICE')->value;
504
505         # The content model for CmdSynopsis doesn't include #PCDATA,
506         # so we won't see any of the whitespace in the source file,
507         # so we have to add it after each component.
508         man_output ' ';
509
510         if($_[0]->attribute('CHOICE')->value =~ /opt/i) {
511                 man_output '[ ';
512         }
513         bold_on();
514 }
515 sub arg_end
516 {
517         font_off();
518         if($_[0]->attribute('REP')->value =~ /^Repeat/i) {
519                 italic_on();
520                 man_output '...';
521                 font_off();
522         }
523         if($_[0]->attribute('CHOICE')->value =~ /opt/i) {
524                 man_output ' ] ';
525         }
526 }
527
528 sgml('<ARG>', \&arg_start);
529 sgml('</ARG>', \&arg_end);
530 sgml('<GROUP>', \&arg_start);
531 sgml('</GROUP>', \&arg_end);
532
533 sgml('<OPTION>', \&bold_on);
534 sgml('</OPTION>', \&font_off);
535
536 # FIXME: This is one _blank_ line.
537 man_sgml('<SBR>', "\n\n");
538
539
540 ########################################################################
541 #
542 # General sections
543 #
544 ########################################################################
545
546 # The name of the section is handled by TITLE.  This just sets
547 # up the roff markup.
548 man_sgml('<REFSECT1>', sub { $separator = ''; man_output "\n.SH "});
549 man_sgml('<REFSECT2>', sub { $separator = ''; man_output "\n.SS "});
550 man_sgml('<REFSECT3>', sub { $separator = ''; man_output "\n.SS "});
551
552
553 ########################################################################
554 #
555 # Titles, metadata.
556 #
557 ########################################################################
558
559 sgml('<TITLE>', sub {
560         if($_[0]->in('REFERENCE') or $_[0]->in('BOOK')) {
561                 $write_manpages = 1;
562         }
563         save_cdata();
564 });
565 sgml('</TITLE>', sub {
566         my ($element, $event) = @_;
567         my $title = fold_string(pop_output());
568         $raw_cdata--;
569         
570         if($element->in('REFERENCE') or $element->in('BOOK')) {
571                 # We use TITLE of enclosing Reference or Book as manual name
572                 $manpage_manual = $title;
573                 $write_manpages = 0;
574         }
575         elsif(exists $element->parent->ext->{'title'}) {
576                 # By far the easiest case.  Just fold the string as
577                 # above, and then set the parent element's variable.
578                 $_[0]->parent->ext->{'title'} = $title;
579         }
580         else {
581                 # If the parent element's handlers are lazy, 
582                 # output the folded string for them :)
583                 # We assume they want uppercase and a newline.
584                 man_output '"', uc($title), "\"\n";
585         }
586
587         if (defined($element->attribute('ID')->value)) {
588                 my $id = $_[0]->attribute('ID')->value;
589                 $Refs->put("title:$id", $title);
590         }
591
592         my ($filename, $citation) =
593                 FileInfo($manpage_title, $manpage_sect || $default_sect);
594         my $parentid = $element->parent->attribute('ID')->value;
595         if ($parentid and ($element->in('REFSECT1') or $element->in('REFSECT2') or $element->in('REFSECT3'))) {
596                 $Refs->put("refsect:$parentid", "$citation");
597         }
598 });
599
600 sgml('<ATTRIBUTION>', sub { 
601         if($_[0]->in('BLOCKQUOTE')) {
602                 push_output('string');
603         }
604 });
605 sgml('</ATTRIBUTION>', sub { 
606         if($_[0]->in('BLOCKQUOTE')) {
607                 $_[0]->parent->ext->{'attribution'} = pop_output(); 
608         } else {
609                 # For an Epigraph.
610                 man_output "\n\n";
611         }
612 });
613
614 sgml('<DATE>', sub {
615       save_cdata();
616 });
617 sgml('</DATE>', sub {
618       $_[0]->parent->parent->ext->{'date'} = fold_string(pop_output());
619       $raw_cdata--;
620 });
621
622 sub ignore_content { push_output 'nul'; }
623 sub restore_content { pop_output(); }
624
625 sgml('<DOCINFO>', \&ignore_content);
626 sgml('</DOCINFO>', \&restore_content);
627 sgml('<REFSYNOPSISDIVINFO>', \&ignore_content);
628 sgml('</REFSYNOPSISDIVINFO>', \&restore_content);
629 sgml('<REFSECT1INFO>', \&ignore_content);
630 sgml('</REFSECT1INFO>', \&restore_content);
631 sgml('<REFSECT2INFO>', \&ignore_content);
632 sgml('</REFSECT2INFO>', \&restore_content);
633 sgml('<REFSECT3INFO>', \&ignore_content);
634 sgml('</REFSECT3INFO>', \&restore_content);
635
636 sgml('<INDEXTERM>', \&ignore_content);
637 sgml('</INDEXTERM>', \&restore_content);
638
639 sgml('<AUTHORBLURB>', \&ignore_content);
640 sgml('</AUTHORBLURB>', \&restore_content);
641
642
643 ########################################################################
644 #
645 # Set bold on enclosed content 
646 #
647 ########################################################################
648
649 sgml('<APPLICATION>', \&bold_on);
650 sgml('</APPLICATION>', \&font_off);
651
652 sgml('<CLASSNAME>', \&bold_on);         sgml('</CLASSNAME>', \&font_off);
653 sgml('<STRUCTNAME>', \&bold_on);        sgml('</STRUCTNAME>', \&font_off);
654 sgml('<STRUCTFIELD>', \&bold_on);       sgml('</STRUCTFIELD>', \&font_off);
655 sgml('<SYMBOL>', \&bold_on);            sgml('</SYMBOL>', \&font_off);
656 sgml('<TYPE>', \&bold_on);              sgml('</TYPE>', \&font_off);
657
658 sgml('<ENVAR>', \&bold_on);     sgml('</ENVAR>', \&font_off);
659
660 sgml('<FUNCTION>', \&bold_on);  sgml('</FUNCTION>', \&font_off);
661
662 sgml('<EMPHASIS>', \&bold_on);  sgml('</EMPHASIS>', \&font_off);
663
664 sgml('<ERRORNAME>', \&bold_on); sgml('</ERRORNAME>', \&font_off);
665 # ERRORTYPE
666
667 sgml('<COMMAND>', \&bold_on);   sgml('</COMMAND>', \&font_off);
668
669 sgml('<GUIBUTTON>', \&bold_on); sgml('</GUIBUTTON>', \&font_off);
670 sgml('<GUIICON>', \&bold_on);   sgml('</GUIICON>', \&font_off);
671 # GUILABEL
672 # GUIMENU
673 # GUIMENUITEM
674 # GUISUBMENU
675 # MENUCHOICE
676
677 sgml('<ACCEL>', \&bold_on);     sgml('</ACCEL>', \&font_off);
678 # KEYCODE
679 # SHORTCUT
680
681
682 sgml('<KEYCOMBO>', sub {
683         $separator = 'none';
684         $_[0]->ext->{'separator'} = 'none';
685 });
686 sgml('</KEYCOMBO>', sub { $separator = $_[0]->parent->ext->{'separator'}; });
687
688 sub _keycombo {
689         if($_[0]->in('KEYCOMBO')) {
690                 if($separator eq 'none') { $separator = '' }
691                 else { man_output "+"; }
692         }
693         bold_on();
694 }
695 sgml('<KEYCAP>', \&_keycombo);  sgml('</KEYCAP>', \&font_off);
696 sgml('<KEYSYM>', \&_keycombo);  sgml('</KEYSYM>', \&font_off);
697 sgml('<MOUSEBUTTON>', \&_keycombo);     sgml('</MOUSEBUTTON>', \&font_off);
698
699
700 sgml('<USERINPUT>', \&bold_on); sgml('</USERINPUT>', \&font_off);
701
702 sgml('<INTERFACEDEFINITION>', \&bold_on);
703 sgml('</INTERFACEDEFINITION>', \&font_off);
704
705 # May need to look at the CLASS
706 sgml('<SYSTEMITEM>', \&bold_on);
707 sgml('</SYSTEMITEM>', \&font_off);
708
709
710 ########################################################################
711 #
712 # Set italic on enclosed content 
713 #
714 ########################################################################
715
716 sgml('<FIRSTTERM>', \&italic_on);       sgml('</FIRSTTERM>', \&font_off);
717
718 sgml('<FILENAME>', \&italic_on);        sgml('</FILENAME>', \&font_off);
719 sgml('<PARAMETER>', \&italic_on);       sgml('</PARAMETER>', \&font_off);
720 sgml('<PROPERTY>', \&italic_on);        sgml('</PROPERTY>', \&font_off);
721
722 sgml('<REPLACEABLE>', sub {
723         italic_on();
724         if($_[0]->in('TOKEN')) {
725                 # When tokenizing, follow more 'intuitive' convention
726                 output "<";
727         }
728 });
729 sgml('</REPLACEABLE>', sub {
730         if($_[0]->in('TOKEN')) {
731                 output ">";
732         }
733         font_off();
734 });
735
736 sgml('<CITETITLE>', \&italic_on);       sgml('</CITETITLE>', \&font_off);
737 sgml('<FOREIGNPHRASE>', \&italic_on);   sgml('</FOREIGNPHRASE>', \&font_off);
738
739 sgml('<LINEANNOTATION>', \&italic_on);  sgml('</LINEANNOTATION>', \&font_off);
740
741
742 ########################################################################
743 #
744 # Other 'inline' elements 
745 #
746 ########################################################################
747
748 man_sgml('<EMAIL>', '<');
749 man_sgml('</EMAIL>', '>');
750 man_sgml('<OPTIONAL>', '[');
751 man_sgml('</OPTIONAL>', ']');
752
753 man_sgml('</TRADEMARK>', "\\u\\s-2TM\\s+2\\d");
754
755 man_sgml('<COMMENT>', "[Comment: ");
756 man_sgml('</COMMENT>', "]");
757
758 man_sgml('<QUOTE>', "``");
759 man_sgml('</QUOTE>', "''");
760
761 #man_sgml('<LITERAL>', '"');
762 #man_sgml('</LITERAL>', '"');
763 # There doesn't seem to be a good way to represent LITERAL in -man
764 # ComputerOutput, SGMLTag, Markup are the same thing.
765
766 # These create spaces between content in special elements
767 # without PCDATA content.
768 man_sgml('</HONORIFIC>', " ");
769 man_sgml('</FIRSTNAME>', " ");
770 man_sgml('</SURNAME>', " ");
771 man_sgml('</LINEAGE>', " ");
772 man_sgml('</OTHERNAME>', " ");
773
774 man_sgml('<AFFILIATION>', "(");
775 man_sgml('</AFFILIATION>', ") ");
776 man_sgml('<CONTRIB>', "(");
777 man_sgml('</CONTRIB>', ") ");
778
779 man_sgml('</STREET>', " ");
780 man_sgml('</POB>', " ");
781 man_sgml('</POSTCODE>', " ");
782 man_sgml('</CITY>', " ");
783 man_sgml('</STATE>', " ");
784 man_sgml('</COUNTRY>', " ");
785 man_sgml('</PHONE>', " ");
786 man_sgml('</FAX>', " ");
787 man_sgml('</OTHERADDRESS>', " ");
788
789 man_sgml('</ALT>', ": ");
790 man_sgml('<GRAPHIC>', " [GRAPHIC] ");
791
792 # No special presentation:
793
794 # AUTHORINITIALS
795
796 # ABBREV
797 # ACTION
798 # ACRONYM
799 # CITATION
800 # PHRASE
801 # QUOTE
802 # WORDASWORD
803
804 # PROMPT
805 # RETURNVALUE
806 # TOKEN
807
808 # DATABASE
809 # HARDWARE
810 # INTERFACE
811 # MEDIALABEL
812
813
814 ########################################################################
815 #
816 # Paragraph and paragraph-like elements 
817 #
818 ########################################################################
819
820 sub para_start {
821         if($separator eq '' or $separator eq 'full') {
822                 $separator = '';
823                 man_output "\n.PP\n";
824         } elsif($separator eq 'blank') { 
825                 man_output "\n\n";
826         } elsif($separator eq 'none' ) {
827                 $_[0]->parent->ext->{'separator'} = 'blank';
828                 $separator = 'blank';
829         }
830 }
831 # Actually applies to a few other block elements as well
832 sub para_end {
833         $separator = $_[0]->parent->ext->{'separator'};
834         man_output "\n";
835 }
836
837 sgml('<PARA>', \&para_start);
838 sgml('</PARA>', \&para_end);
839 sgml('<SIMPARA>', \&para_start);
840 sgml('</SIMPARA>', \&para_end);
841
842 # Nothing special, except maybe FIXME set nobreak.
843 sgml('<INFORMALEXAMPLE>', \&para_start);
844 sgml('</INFORMALEXAMPLE>', \&para_end);
845
846
847 ########################################################################
848 #
849 # Blocks using SS sections
850 #
851 ########################################################################
852
853 # FIXME: We need to consider the effects of SS
854 # in a hanging tag :(
855
856 # Complete with the optional-title dilemma (again).
857 sgml('<ABSTRACT>', sub {
858         $_[0]->ext->{'title'} = 'ABSTRACT';
859         output "\n" unless $newline_last++;
860         push_output('string');
861 });
862 sgml('</ABSTRACT>', sub {
863         my $content = pop_output();
864         
865         # As ABSTRACT is never on the same level as RefSect1,
866         # this leaves us with only .SS in terms of -man macros.
867         output ".SS \"", uc($_[0]->ext->{'title'}), "\"\n";
868
869         output $content;
870         output "\n" unless $newline_last++;
871 });
872
873
874
875 # Ah, I needed a break.  Example always has a title.
876 sgml('<EXAMPLE>', sub { $separator = ''; man_output "\n.SS "});
877 sgml('</EXAMPLE>', \&para_end);
878
879 # Same with sidebar.
880 sgml('<SIDEBAR>', sub { $separator = ''; man_output "\n.SS "});
881 sgml('</SIDEBAR>', \&para_end);
882
883 sgml('<FORMALPARA>', sub { $separator = ''; man_output "\n.SS "});
884 sgml('</FORMALPARA>', \&para_end);
885
886 sgml('<FIGURE>', sub { $separator = ''; man_output "\n.SS "});
887 sgml('</FIGURE>', \&para_end);
888
889
890
891 # NO title.
892 sgml('<HIGHLIGHTS>', sub { $separator = ''; man_output "\n.SS HIGHLIGHTS\n"});
893 sgml('</HIGHLIGHTS>', \&para_end);
894
895
896 ########################################################################
897 #
898 # Indented 'Block' elements 
899 #
900 ########################################################################
901
902 sub indent_block_start
903 {
904         $separator = '';
905         man_output "\n.sp\n.RS\n";
906 }
907 sub indent_block_end
908 {
909         $separator = $_[0]->parent->ext->{'separator'};
910         man_output "\n.RE\n.sp\n";
911 }
912
913 sgml('<ADDRESS>', sub {
914         &indent_block_start;
915         if($_[0]->attribute('FORMAT')->type eq 'NOTATION'
916            and $_[0]->attribute('FORMAT')->value->name eq 'LINESPECIFIC') {
917                 &verbatim_start;
918         }
919 });
920 sgml('</ADDRESS>', sub {
921         if($_[0]->attribute('FORMAT')->type eq 'NOTATION'
922            and $_[0]->attribute('FORMAT')->value->name eq 'LINESPECIFIC') {
923                 &verbatim_end;
924         }
925         &indent_block_end;
926 });
927         
928 # This element is almost like an admonition (below),
929 # only the default title is blank :)
930
931 sgml('<BLOCKQUOTE>', sub { 
932         $_[0]->ext->{'title'} = ''; 
933         &indent_block_start;
934         push_output('string');
935 });
936 sgml('</BLOCKQUOTE>', sub {
937         my $content = pop_output();
938
939         if($_[0]->ext->{'title'}) {
940                 output ".B \"", $_[0]->ext->{'title'}, ":\"\n";
941         }
942         
943         output $content;
944
945         if($_[0]->ext->{'attribution'}) {
946                 man_output "\n\n                -- ",
947                                 $_[0]->ext->{'attribution'}, "\n";
948         }
949         
950         &indent_block_end;
951 });
952
953 # Set off admonitions from the rest of the text by indenting.
954 # FIXME: Need to check if this works inside paragraphs, not enclosing them.
955 sub admonition_end {
956         my $content = pop_output();
957
958         # When the admonition is only one paragraph,
959         # it looks nicer if the title was inline.
960         my $num_para;
961         while ($content =~ /^\.PP/gm) { $num_para++ }
962         if($num_para==1) {
963                 $content =~ s/^\.PP\n//;
964         }
965         
966         output ".B \"" . $_[0]->ext->{'title'} . ":\"\n";
967         output $content;
968         
969         &indent_block_end;
970 }
971
972 sgml('<NOTE>', sub {
973         # We can't see right now whether or not there is a TITLE
974         # element, so we have to save the output now and add it back
975         # at the end of this admonition.
976         $_[0]->ext->{'title'} = 'Note';
977         
978         &indent_block_start;
979         
980         push_output('string');
981 });
982 sgml('</NOTE>', \&admonition_end);
983
984 # Same as above.
985 sgml('<WARNING>', sub { 
986         $_[0]->ext->{'title'} = 'Warning'; 
987         &indent_block_start;
988         push_output('string');
989 });
990 sgml('</WARNING>', \&admonition_end);
991
992 sgml('<TIP>', sub {
993         $_[0]->ext->{'title'} = 'Tip';
994         &indent_block_start;
995         push_output('string');
996 });
997 sgml('</TIP>', \&admonition_end);
998 sgml('<CAUTION>', sub {
999         $_[0]->ext->{'title'} = 'Caution';
1000         &indent_block_start;
1001         push_output('string');
1002 });
1003 sgml('</CAUTION>', \&admonition_end);
1004
1005 sgml('<IMPORTANT>', sub {
1006         $_[0]->ext->{'title'} = 'Important';
1007         &indent_block_start;
1008         push_output('string');
1009 });
1010 sgml('</IMPORTANT>', \&admonition_end);
1011
1012
1013 ########################################################################
1014 #
1015 # Verbatim displays. 
1016 #
1017 ########################################################################
1018
1019 sub verbatim_start {
1020         $separator = '';
1021         man_output "\n.sp\n";
1022         man_output "\n.nf\n" unless $nocollapse_whitespace++;
1023 }
1024
1025 sub verbatim_end {
1026         man_output "\n.sp\n";
1027         man_output "\n.fi\n" unless --$nocollapse_whitespace;
1028         $separator = $_[0]->parent->ext->{'separator'};
1029 }
1030
1031 sgml('<PROGRAMLISTING>', \&verbatim_start); 
1032 sgml('</PROGRAMLISTING>', \&verbatim_end);
1033
1034 sgml('<SCREEN>', \&verbatim_start); 
1035 sgml('</SCREEN>', \&verbatim_end);
1036
1037 sgml('<LITERALLAYOUT>', \&verbatim_start); 
1038 sgml('</LITERALLAYOUT>', \&verbatim_end);
1039
1040 sgml('<SYNOPSIS>', sub {
1041         my $format = $_[0]->attribute('FORMAT');
1042
1043         if($format->type eq 'NOTATION'
1044            and $format->value->name eq 'LINESPECIFIC')
1045         {
1046                 &verbatim_start;
1047         } else {
1048                 $separator = '';
1049                 man_output "\n.sp\n";
1050         }
1051 });
1052
1053 sgml('</SYNOPSIS>', sub {
1054         my $format = $_[0]->attribute('FORMAT');
1055         
1056         if($format->type eq 'NOTATION'
1057            and $format->value->name eq 'LINESPECIFIC')
1058         {
1059                 &verbatim_end;
1060         } else {
1061                 man_output "\n";
1062                 $_[0]->parent->ext->{'separator'} = 'full';
1063                 $separator = 'full';
1064         }
1065 });
1066
1067
1068 ########################################################################
1069 #
1070 # Lists
1071 #
1072 ########################################################################
1073
1074 # Indent nested lists.
1075 sub list_start {
1076         man_output "\n.RS\n" if $list_nestlevel++;
1077 }
1078 sub list_end {
1079         man_output "\n.RE\n" if --$list_nestlevel;
1080         $_[0]->parent->ext->{'separator'} = 'full';
1081         $separator = 'full';
1082 }
1083
1084 sgml('<VARIABLELIST>', \&list_start);
1085 sgml('</VARIABLELIST>', \&list_end);
1086 sgml('<ITEMIZEDLIST>', \&list_start);
1087 sgml('</ITEMIZEDLIST>', \&list_end);
1088 sgml('<ORDEREDLIST>', sub { 
1089         &list_start;
1090         $_[0]->ext->{'count'} = 1;
1091 });
1092 sgml('</ORDEREDLIST>', \&list_end);
1093                 
1094 # Output content on one line, bolded.
1095 sgml('<TERM>', sub { 
1096         man_output "\n.TP\n";
1097         bold_on();
1098         push_output('string');
1099 });
1100 sgml('</TERM>', sub { 
1101         my $term = StripString(pop_output());
1102         $term =~ tr/\n/ /;
1103         output $term;
1104         font_off();
1105         output "\n";
1106         $newline_last = 1;
1107 });
1108         
1109 sgml('<LISTITEM>', sub {
1110         # A bulleted list.
1111         if($_[0]->in('ITEMIZEDLIST')) {
1112                 man_output "\n.TP 0.2i\n\\(bu\n";
1113         }
1114
1115         # Need numbers.
1116         # Assume Arabic numeration for now.
1117         elsif($_[0]->in('ORDEREDLIST')) {
1118                 man_output "\n.IP ", $_[0]->parent->ext->{'count'}++, ". \n";
1119         }
1120         
1121         $_[0]->ext->{'separator'} = 'none';
1122         $separator = 'none';
1123 });
1124
1125 sgml('<SIMPLELIST>', sub {
1126         $_[0]->ext->{'first_member'} = 1;
1127 });
1128 sgml('<MEMBER>', sub {
1129         my $parent = $_[0]->parent;
1130         
1131         if($parent->attribute('TYPE')->value =~ /Inline/i) {
1132                 if($parent->ext->{'first_member'}) {
1133                         # If this is the first member don't put any commas
1134                         $parent->ext->{'first_member'} = 0;
1135                 } else {
1136                         man_output ", ";
1137                 }
1138
1139         # We don't really have Horiz rendering, so it's the same
1140         # as Vert.
1141         } else {
1142                 man_output "\n\n";
1143         }
1144 });
1145
1146 # We implement Procedures as indent and lists
1147
1148 sgml('<PROCEDURE>', sub {
1149         $_[0]->ext->{'count'} = 1;
1150         &indent_block_start;
1151 });
1152 sgml('</PROCEDURE>', sub {
1153         &indent_block_end;
1154         $_[0]->parent->ext->{'separator'} = 'full';
1155         $separator = 'full';
1156 });
1157
1158 sgml('<STEP>', sub {
1159         man_output "\n.IP ", $_[0]->parent->ext->{'count'}++, ". \n";
1160         $_[0]->ext->{'separator'} = 'none';
1161         $separator = 'none';
1162 });
1163
1164
1165 ########################################################################
1166 #
1167 # Linkage, cross references
1168 #
1169 ########################################################################
1170
1171 # Print the URL
1172 sgml('</ULINK>', sub {
1173         man_output ' <URL:', $_[0]->attribute('URL')->value, '>';
1174 });
1175
1176 # If cross reference target is a RefEntry, 
1177 # output CiteRefEntry-style references.
1178 sgml('<XREF>', sub {
1179         my $id = $_[0]->attribute('LINKEND')->value;
1180
1181         my $manref = $Refs->get("refentry:$id") || $Refs->get("refsect:$id");
1182         if(!defined $manref) {
1183                 $blank_xrefs++ if $write_manpages;
1184                 man_output "[XRef to $id]";
1185                 return;
1186         }
1187
1188         # Limited ENDTERM support.
1189         if(defined $_[0]->attribute('ENDTERM')->value) {
1190                 my $endterm = $_[0]->attribute('ENDTERM')->value;
1191                 my $content = $Refs->get("title:$endterm") ||
1192                                 $Refs->get("refentrytitle:$endterm");
1193                 man_output $content, ' [';
1194         }
1195
1196         # This also displays the XREFLABEL (as bold)...
1197         # It's not worth the bother to fix it though, there
1198         # are better tools for this.
1199         my ($title, $sect) = ($manref =~ /(.*)(\(.*\))/);
1200         bold_on();
1201         man_output $title;
1202         font_off();
1203         man_output $sect;
1204
1205         if(defined $_[0]->attribute('ENDTERM')->value) {
1206                 man_output ']';
1207         }
1208 });
1209
1210 # Anchor
1211
1212 ########################################################################
1213 #
1214 # SDATA 
1215 #
1216 ########################################################################
1217
1218 man_sgml('|[lt    ]|', '<');
1219 man_sgml('|[equals]|', '=');
1220 man_sgml('|[gt    ]|', '>');
1221 man_sgml('|[plus  ]|', '\(pl');
1222 man_sgml('|[dollar]|', '$');
1223 man_sgml('|[num   ]|', '#');
1224 man_sgml('|[percnt]|', '%');
1225 man_sgml('|[amp   ]|', '&');
1226 man_sgml('|[commat]|', '@');
1227 man_sgml('|[lsqb  ]|', '[');
1228 man_sgml('|[bsol  ]|', '\e');
1229 man_sgml('|[rsqb  ]|', ']');
1230 man_sgml('|[lcub  ]|', '{');
1231 man_sgml('|[verbar]|', '\(or');
1232 man_sgml('|[rcub  ]|', '}');
1233 man_sgml('|[excl  ]|', '!');
1234 man_sgml('|[quot  ]|', '"');
1235 man_sgml('|[apos  ]|', '\\&\'');
1236 man_sgml('|[lpar  ]|', '(');
1237 man_sgml('|[rpar  ]|', ')');
1238 man_sgml('|[comma ]|', ',');
1239 man_sgml('|[lowbar]|', '_');
1240 man_sgml('|[period]|', '.');
1241 man_sgml('|[sol   ]|', '/');
1242 man_sgml('|[colon ]|', ':');
1243 man_sgml('|[semi  ]|', ';');
1244 man_sgml('|[quest ]|', '?');
1245 man_sgml('|[grave ]|', '`');
1246 man_sgml('|[tilde ]|', '~');
1247 man_sgml('|[half  ]|', '\(12');
1248 man_sgml('|[frac12]|', '\(12');
1249 man_sgml('|[frac14]|', '\(14');
1250 man_sgml('|[frac34]|', '\(34');
1251 man_sgml('|[frac18]|', '1/8');
1252 man_sgml('|[frac38]|', '3/8');
1253 man_sgml('|[frac58]|', '5/8');
1254 man_sgml('|[frac78]|', '7/8');
1255 man_sgml('|[sup1  ]|', '\u1\l');
1256 man_sgml('|[sup2  ]|', '\u2\l');
1257 man_sgml('|[sup3  ]|', '\u3\l');
1258 man_sgml('|[plusmn]|', '\(+-');
1259 man_sgml('|[divide]|', '\(di');
1260 man_sgml('|[times ]|', '\(ti');
1261 man_sgml('|[pound ]|', '#');
1262 man_sgml('|[cent  ]|', '\(ct');
1263 man_sgml('|[yen   ]|', 'yen');
1264 man_sgml('|[ast   ]|', '*');
1265 man_sgml('|[horbar]|', '_');
1266 man_sgml('|[micro ]|', '\(*m');
1267 man_sgml('|[ohm   ]|', '\(*W');
1268 man_sgml('|[deg   ]|', '\(de');
1269 man_sgml('|[sect  ]|', '\(sc');
1270 man_sgml('|[larr  ]|', '\(<-');
1271 man_sgml('|[rarr  ]|', '\(->');
1272 man_sgml('|[uarr  ]|', '\(ua');
1273 man_sgml('|[darr  ]|', '\(da');
1274 man_sgml('|[copy  ]|', '\(co');
1275 man_sgml('|[reg   ]|', '\(rg');
1276 man_sgml('|[trade ]|', '\(tm');
1277 man_sgml('|[brvbar]|', '|');
1278 man_sgml('|[not   ]|', '\(no');
1279 man_sgml('|[hyphen]|', '\-');
1280 man_sgml('|[laquo ]|', '<<');
1281 man_sgml('|[raquo ]|', '>>');
1282 man_sgml('|[lsquo ]|', '`');
1283 man_sgml('|[rsquo ]|', '\&\'');
1284 man_sgml('|[ldquo ]|', '"');
1285 man_sgml('|[rdquo ]|', '"');
1286 man_sgml('|[nbsp  ]|', '\ ');
1287 man_sgml('|[shy   ]|', '\%');
1288 man_sgml('|[emsp  ]|', '\ \ ');
1289 man_sgml('|[ensp  ]|', '\ ');
1290 man_sgml('|[emsp3 ]|', '\ ');
1291 man_sgml('|[emsp4 ]|', '\ ');
1292 man_sgml('|[numsp ]|', '\0');
1293 man_sgml('|[puncsp]|', '\|');
1294 man_sgml('|[thinsp]|', '\!');
1295 man_sgml('|[hairsp]|', '\\^');
1296 man_sgml('|[mdash ]|', '\(em');
1297 man_sgml('|[ndash ]|', '-');
1298 man_sgml('|[dash  ]|', '-');
1299 man_sgml('|[blank ]|', '\ ');
1300 man_sgml('|[hellip]|', '\&...');
1301 man_sgml('|[nldr  ]|', '\&..');
1302 man_sgml('|[frac13]|', '1/3');
1303 man_sgml('|[frac23]|', '2/3');
1304 man_sgml('|[frac15]|', '1/5');
1305 man_sgml('|[frac25]|', '2/5');
1306 man_sgml('|[frac35]|', '3/5');
1307 man_sgml('|[frac45]|', '4/5');
1308 man_sgml('|[frac16]|', '1/6');
1309 man_sgml('|[frac56]|', '5/6');
1310 man_sgml('|[cir   ]|', '\(ci');
1311 man_sgml('|[squ   ]|', '\(sq');
1312 man_sgml('|[star  ]|', '\(**');
1313 man_sgml('|[bull  ]|', '\(bu');
1314 man_sgml('|[dagger]|', '\(dg');
1315 man_sgml('|[Dagger]|', '\(dd');
1316 man_sgml('|[caret ]|', '\^');
1317 man_sgml('|[lsquor]|', '`');
1318 man_sgml('|[ldquor]|', '``');
1319 man_sgml('|[fflig ]|', '\(ff');
1320 man_sgml('|[filig ]|', '\(fi');
1321 man_sgml('|[ffilig]|', '\(Fi');
1322 man_sgml('|[ffllig]|', '\(Fl');
1323 man_sgml('|[fllig ]|', '\(fl');
1324 man_sgml('|[rdquor]|', '\&\'\'');
1325 man_sgml('|[rsquor]|', '\&\'');
1326 man_sgml('|[vellip]|', '\&...');
1327 man_sgml('|[aacute]|', '\(a\'');
1328 man_sgml('|[Aacute]|', '\(A\'');
1329 man_sgml('|[acirc ]|', '\(a^');
1330 man_sgml('|[Acirc ]|', '\(A^');
1331 man_sgml('|[agrave]|', '\(a`');
1332 man_sgml('|[Agrave]|', '\(A`');
1333 man_sgml('|[auml  ]|', '\(a:');
1334 man_sgml('|[aelig ]|', '\(ae');
1335 man_sgml('|[AElig ]|', '\(AE');
1336 man_sgml('|[eacute]|', '\(e\'');
1337 man_sgml('|[Eacute]|', '\(E\'');
1338 man_sgml('|[egrave]|', '\(e`');
1339 man_sgml('|[Egrave]|', '\(E`');
1340 man_sgml('|[iacute]|', '\(i\'');
1341 man_sgml('|[Iacute]|', '\(I\'');
1342 man_sgml('|[igrave]|', '\(i`');
1343 man_sgml('|[Igrave]|', '\(I`');
1344 man_sgml('|[ntilde]|', '\(n~');
1345 man_sgml('|[Ntilde]|', '\(N~');
1346 man_sgml('|[oacute]|', '\(o\'');
1347 man_sgml('|[Oacute]|', '\(O\'');
1348 man_sgml('|[ograve]|', '\(o`');
1349 man_sgml('|[Ograve]|', '\(O`');
1350 man_sgml('|[oslash]|', '\(o/');
1351 man_sgml('|[Oslash]|', '\(O/');
1352 man_sgml('|[szlig ]|', '\(ss');
1353 man_sgml('|[thorn ]|', '\(th');
1354 man_sgml('|[uacute]|', '\(u\'');
1355 man_sgml('|[Uacute]|', '\(U\'');
1356 man_sgml('|[ugrave]|', '\(u`');
1357 man_sgml('|[Ugrave]|', '\(U`');
1358 man_sgml('|[aogon ]|', '\(ao');
1359 man_sgml('|[agr   ]|', '\(*a');
1360 man_sgml('|[Agr   ]|', '\(*A');
1361 man_sgml('|[bgr   ]|', '\(*b');
1362 man_sgml('|[Bgr   ]|', '\(*B');
1363 man_sgml('|[ggr   ]|', '\(*g');
1364 man_sgml('|[Ggr   ]|', '\(*G');
1365 man_sgml('|[dgr   ]|', '\(*d');
1366 man_sgml('|[Dgr   ]|', '\(*D');
1367 man_sgml('|[egr   ]|', '\(*e');
1368 man_sgml('|[Egr   ]|', '\(*E');
1369 man_sgml('|[zgr   ]|', '\(*z');
1370 man_sgml('|[Zgr   ]|', '\(*Z');
1371 man_sgml('|[eegr  ]|', '\(*y');
1372 man_sgml('|[EEgr  ]|', '\(*Y');
1373 man_sgml('|[thgr  ]|', '\(*h');
1374 man_sgml('|[THgr  ]|', '\(*H');
1375 man_sgml('|[igr   ]|', '\(*i');
1376 man_sgml('|[Igr   ]|', '\(*I');
1377 man_sgml('|[kgr   ]|', '\(*k');
1378 man_sgml('|[Kgr   ]|', '\(*K');
1379 man_sgml('|[lgr   ]|', '\(*l');
1380 man_sgml('|[Lgr   ]|', '\(*L');
1381 man_sgml('|[mgr   ]|', '\(*m');
1382 man_sgml('|[Mgr   ]|', '\(*M');
1383 man_sgml('|[ngr   ]|', '\(*n');
1384 man_sgml('|[Ngr   ]|', '\(*N');
1385 man_sgml('|[xgr   ]|', '\(*c');
1386 man_sgml('|[Xgr   ]|', '\(*C');
1387 man_sgml('|[ogr   ]|', '\(*o');
1388 man_sgml('|[Ogr   ]|', '\(*O');
1389 man_sgml('|[pgr   ]|', '\(*p');
1390 man_sgml('|[Pgr   ]|', '\(*P');
1391 man_sgml('|[rgr   ]|', '\(*r');
1392 man_sgml('|[Rgr   ]|', '\(*R');
1393 man_sgml('|[sgr   ]|', '\(*s');
1394 man_sgml('|[Sgr   ]|', '\(*S');
1395 man_sgml('|[sfgr  ]|', '\(ts');
1396 man_sgml('|[tgr   ]|', '\(*t');
1397 man_sgml('|[Tgr   ]|', '\(*T');
1398 man_sgml('|[ugr   ]|', '\(*u');
1399 man_sgml('|[Ugr   ]|', '\(*U');
1400 man_sgml('|[phgr  ]|', '\(*f');
1401 man_sgml('|[PHgr  ]|', '\(*F');
1402 man_sgml('|[khgr  ]|', '\(*x');
1403 man_sgml('|[KHgr  ]|', '\(*X');
1404 man_sgml('|[psgr  ]|', '\(*q');
1405 man_sgml('|[PSgr  ]|', '\(*Q');
1406 man_sgml('|[ohgr  ]|', '\(*w');
1407 man_sgml('|[OHgr  ]|', '\(*W');
1408 man_sgml('|[alpha ]|', '\(*a');
1409 man_sgml('|[beta  ]|', '\(*b');
1410 man_sgml('|[gamma ]|', '\(*g');
1411 man_sgml('|[Gamma ]|', '\(*G');
1412 man_sgml('|[delta ]|', '\(*d');
1413 man_sgml('|[Delta ]|', '\(*D');
1414 man_sgml('|[epsi  ]|', '\(*e');
1415 man_sgml('|[epsis ]|', '\(*e');
1416 man_sgml('|[zeta  ]|', '\(*z');
1417 man_sgml('|[eta   ]|', '\(*y');
1418 man_sgml('|[thetas]|', '\(*h');
1419 man_sgml('|[Theta ]|', '\(*H');
1420 man_sgml('|[iota  ]|', '\(*i');
1421 man_sgml('|[kappa ]|', '\(*k');
1422 man_sgml('|[lambda]|', '\(*l');
1423 man_sgml('|[Lambda]|', '\(*L');
1424 man_sgml('|[mu    ]|', '\(*m');
1425 man_sgml('|[nu    ]|', '\(*n');
1426 man_sgml('|[xi    ]|', '\(*c');
1427 man_sgml('|[Xi    ]|', '\(*C');
1428 man_sgml('|[pi    ]|', '\(*p');
1429 man_sgml('|[Pi    ]|', '\(*P');
1430 man_sgml('|[rho   ]|', '\(*r');
1431 man_sgml('|[sigma ]|', '\(*s');
1432 man_sgml('|[Sigma ]|', '\(*S');
1433 man_sgml('|[tau   ]|', '\(*t');
1434 man_sgml('|[upsi  ]|', '\(*u');
1435 man_sgml('|[Upsi  ]|', '\(*U');
1436 man_sgml('|[phis  ]|', '\(*f');
1437 man_sgml('|[Phi   ]|', '\(*F');
1438 man_sgml('|[chi   ]|', '\(*x');
1439 man_sgml('|[psi   ]|', '\(*q');
1440 man_sgml('|[Psi   ]|', '\(*X');
1441 man_sgml('|[omega ]|', '\(*w');
1442 man_sgml('|[Omega ]|', '\(*W');
1443 man_sgml('|[ap    ]|', '\(ap');
1444 man_sgml('|[equiv ]|', '\(==');
1445 man_sgml('|[ge    ]|', '\(>=');
1446 man_sgml('|[infin ]|', '\(if');
1447 man_sgml('|[isin  ]|', '\(sb');
1448 man_sgml('|[le    ]|', '\(<=');
1449 man_sgml('|[minus ]|', '\(mi');
1450 man_sgml('|[ne    ]|', '\(!=');
1451 man_sgml('|[prop  ]|', '\(pt');
1452 man_sgml('|[square]|', '\(sq');
1453 man_sgml('|[sub   ]|', '\(sb');
1454 man_sgml('|[sube  ]|', '\(ib');
1455 man_sgml('|[sup   ]|', '\(sp');
1456 man_sgml('|[supe  ]|', '\(ip');
1457 man_sgml('|[acute ]|', '\&\'');
1458 man_sgml('|[breve ]|', '\(be');
1459 man_sgml('|[caron ]|', '\(hc');
1460 man_sgml('|[cedil ]|', '\(cd');
1461 man_sgml('|[dot   ]|', '\(dt');
1462 man_sgml('|[macr  ]|', '\(ma');
1463 man_sgml('|[ogon  ]|', '\(og');
1464 man_sgml('|[ring  ]|', '\(ri');
1465 man_sgml('|[uml   ]|', '\(..');
1466
1467 sgml('sdata',sub {
1468         my ($element, $event) = @_;
1469         my ($file, $line) = ($event->file, $event->line);
1470         man_output "|[", $_[0], "]|";
1471         warn "Warning: unrecognized SDATA '$_[0]'"
1472              . ($file && $line ? " in $file on line $line" : "")
1473              . ": please add definition to docbook2man-spec.pl\n";
1474 });
1475
1476 #
1477 # Default handlers (uncomment these if needed).  Right now, these are set
1478 # up to gag on any unrecognised elements, sdata, processing-instructions,
1479 # or entities.
1480 #
1481 # sgml('start_element',sub { die "Unknown element: " . $_[0]->name; });
1482 # sgml('end_element','');
1483
1484 # This is for weeding out and escaping certain characters.
1485 # This looks like it's inefficient since it's done on every line, but
1486 # in reality, SGMLSpm and sgmlspl parsing ESIS takes _much_ longer.
1487
1488 sgml('cdata', sub
1489
1490         if(!$write_manpages) { return; }
1491         elsif($raw_cdata) { output $_[0]; return; }
1492
1493         if($separator eq 'full') {
1494                 output "\n" unless $newline_last++;
1495                 output ".PP\n";
1496                 $separator = '';
1497         }
1498         
1499         # Escape backslashes
1500         $_[0] =~ s/\\/\\\\/g;
1501
1502   # Escape dots and single quotes in column 1
1503         $_[0] =~ s/^[ \t]*\./\\\&\./;
1504         $_[0] =~ s/^[ \t]*\'/\\\&\'/;
1505
1506
1507         # In non-'pre'-type elements:
1508         if(!$nocollapse_whitespace) {
1509                 # Change tabs to spaces
1510                 $_[0] =~ tr/\t / /s;
1511
1512                 # Do not allow indents at beginning of line
1513                 # groff chokes on that.
1514                 if($newline_last) { 
1515                         $_[0] =~ s/^ //;
1516
1517                         # If the line is all blank, don't do anything.
1518                         if($_[0] eq '') { return; }
1519                         
1520                         $_[0] =~ s/^\./\\\&\./;
1521         
1522                         # Argh... roff doesn't like ' for some unknown reason 
1523                         $_[0] =~ s/^\'/\\\&\'/;
1524                 }
1525         }
1526
1527         $newline_last = 0;
1528
1529         output $_[0];
1530 });
1531
1532
1533 # When in whitespace-collapsing mode, we disallow consecutive newlines.
1534
1535 sgml('re', sub
1536 {
1537         if($nocollapse_whitespace || !$newline_last) {
1538                 output "\n";
1539         }
1540
1541         $newline_last = 1;
1542 });
1543
1544 sgml('pi', sub {});
1545 sgml('entity',sub { die "Unknown external entity: " . $_[0]->name; });
1546 sgml('start_subdoc',sub { die "Unknown subdoc entity: " . $_[0]->name; });
1547 sgml('end_subdoc',sub{});
1548 sgml('conforming',sub{});
1549
1550 1;
1551