diff options
Diffstat (limited to 'release/doc/share/misc/man2hwnotes.pl')
-rw-r--r-- | release/doc/share/misc/man2hwnotes.pl | 353 |
1 files changed, 353 insertions, 0 deletions
diff --git a/release/doc/share/misc/man2hwnotes.pl b/release/doc/share/misc/man2hwnotes.pl new file mode 100644 index 0000000..915728d --- /dev/null +++ b/release/doc/share/misc/man2hwnotes.pl @@ -0,0 +1,353 @@ +#!/usr/bin/perl -w +# Emacs should use -*- cperl -*- mode +# +# Copyright (c) 2003-2004 Simon L. Nielsen <simon@FreeBSD.org> +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +# Parse the list of supported hardware out of section 4 manual pages +# and output it on stdout as SGML/DocBook entities. + +# The script will look for the following line in the manual page: +# .Sh HARDWARE +# and make an entity of the content until the line containing: +# .Sh +# +# For Lists only the first line will be printed. If there are +# arguments to the .It command, only the argument will be printed. + +# Usage: +# mdoc2sgml [-l] [-d 0-6] [-a <archlist file>] manualpage [manualpage ...] + +use strict; +use Getopt::Std; +use Digest::MD5 qw(md5_hex); + +# Section from manual page to extract +my $hwlist_sect = "HARDWARE"; + +# Override default archtecture list for some devices: +my $archlist_file = "dev.archlist.txt"; +my %archlist; + +# Globals +my $debuglevel = 0; +my $only_list_out = 0; # Should only lists be generated in the output? +my @out_lines; # Single lines +my @out_dev; # Device entities + +# Getopt +my %options = (); +if (!getopts("a:d:l",\%options)) { + die("Invalid command line arguments\n"); +} + +if (defined($options{d})) { + $debuglevel = $options{d}; +} +if (defined($options{a})) { + $archlist_file = $options{a}; +} +if (defined($options{l})) { + $only_list_out = 1; +} + +if ($debuglevel > 0) { + # Don't do output buffering in debug mode. + $| = 1; +} + +load_archlist($archlist_file); + +if ($only_list_out) { + # Print the default device preamble entities + print "<!ENTITY hwlist.preamble.pre 'The'>\n"; + print "<!ENTITY hwlist.preamble.post 'driver supports:'>\n"; +} + +foreach my $page (@ARGV) { + dlog(2, "Parsing $page"); + parse($page); + + print join("\n", @out_lines); + print "\n"; + print join("\n", @out_dev); + print "\n"; + + @out_lines = (); + @out_dev = (); +} + +sub parse { + my ($manpage) = @_; + + my $cur_mansection; + my $found_hwlist = 0; + my %mdocvars; + $mdocvars{isin_hwlist} = 0; + $mdocvars{isin_list} = 0; + $mdocvars{parabuf} = ""; + $mdocvars{listtype} = ""; + + open(MANPAGE, "$manpage") || die(); + while(<MANPAGE>) { + chomp; + my $line = $_; + + dlog(5, "Read '$line'"); + + # Find commands + if (s/^\.(.*)$/$1/) { + # Detect, and ignore, comment lines + if (s/^\\"(.*)$/$1/) { + next; + } + + if (/^Nm "?(\w+)"?/ && !defined($mdocvars{Nm})) { + dlog(3, "Setting Nm to $1"); + $mdocvars{Nm} = $1; + + } elsif (/^Nm$/) { + if (defined($mdocvars{Nm}) && $mdocvars{Nm} ne "") { + parabuf_addline(\%mdocvars, "&man.".$mdocvars{Nm}.".$cur_mansection;"); + } else { + dlog(2, "Warning: Bad Nm call in $manpage"); + } + + } elsif (/^Sh (.+)$/) { + dlog(4, "Setting section to $1"); + my $cur_section = $1; + + flush_out(\%mdocvars); + + if ($cur_section =~ /^${hwlist_sect}$/) { + dlog(2, "Found the device section ${hwlist_sect}"); + $mdocvars{isin_hwlist} = 1; + $found_hwlist = 1; + add_sgmltag(\%mdocvars, "<!ENTITY hwlist.".$mdocvars{cur_manname}." '"); + if ($only_list_out) { + add_sgmltag("<para>&hwlist.preamble.pre; " . + "&man.".$mdocvars{Nm}.".$cur_mansection; " . + "&hwlist.preamble.post;</para>"); + } + } elsif ($mdocvars{isin_hwlist}) { + dlog(2, "Found a HWLIST STOP key!"); + add_sgmltag(\%mdocvars, "'>"); + $mdocvars{isin_hwlist} = 0; + } + + } elsif (/^Dt ([^ ]+) ([^ ]+)/) { + dlog(4, "Setting mansection to $2"); + $mdocvars{cur_manname} = lc($1); + $cur_mansection = $2; + + } elsif (/^It ?(.*)$/) { + # Flush last item + if ($mdocvars{parabuf} ne "") { + add_listitem(\%mdocvars); + } + parabuf_addline(\%mdocvars, $1); + } elsif (/^Bl/) { + $mdocvars{isin_list} = 1; + flush_out(\%mdocvars); + add_sgmltag(\%mdocvars, "<itemizedlist>"); + + if (/-tag/) { + $mdocvars{listtype} = "tag"; + # YACK! Hack for ata(4) + if ($mdocvars{Nm} eq "ata") { + $mdocvars{listtype} = "tagHACK"; + } + } elsif (/-bullet/) { + $mdocvars{listtype} = "bullet"; + } else { + $mdocvars{listtype} = "unknown"; + } + dlog(2, "Listtype set to $mdocvars{listtype}"); + } elsif (/^El/) { + if ($mdocvars{parabuf} ne "") { + add_listitem(\%mdocvars); + } + + add_sgmltag(\%mdocvars, "</itemizedlist>"); + $mdocvars{isin_list} = 0; + } elsif (/^Tn (.+)$/) { + # For now we print TradeName text as regular text. + my $txt = $1; + $txt =~ s/^(.+) ,$/$1,/; + + parabuf_addline(\%mdocvars, $txt); + } elsif (/^Xr (.+) (.+)/) { + # We need to check if the manual page exist to avoid + # breaking the doc build just because of a broken + # reference. + #parabuf_addline(\%mdocvars, "&man.$1.$2;"); + parabuf_addline(\%mdocvars, "$1($2)"); + } + # Ignore all other commands + } else { + # This is then regular text + parabuf_addline(\%mdocvars, $_); + } + } + close(MANPAGE) || die("Could not close input manual page"); + if (! $found_hwlist) { + dlog(1, "Hardware list not found in $manpage"); + } +} + +sub dlog { + my ($level, $txt) = @_; + + if ($level <= $debuglevel) { + print STDERR "$level: $txt\n"; + } +} + +# Output a SGML tag. +sub add_sgmltag { + my ($mdocvars, $txt) = (@_); + + # We only care about the HW list for now. + if (${$mdocvars}{isin_hwlist}) { + push(@out_dev, $txt); + } +} + +# Add a text entity, and return the used entity name. +sub add_txt_ent { + my ($itemtxt) = (@_); + my ($entity_name); + + # Convert mdoc(7) minus + $itemtxt =~ s/\\-/-/g; + + $itemtxt =~ s/'/‘/g; + + $entity_name = "hwlist." . md5_hex($itemtxt); + dlog(4, "Adding '$itemtxt' as entity $entity_name"); + push(@out_lines, "<!ENTITY $entity_name '$itemtxt'>"); + + return ($entity_name); +} +sub flush_out { + my ($mdocvars) = (@_); + my ($entity_name, $out); + my $para_arch = ""; + + if (!${$mdocvars}{isin_hwlist} || ${$mdocvars}{parabuf} eq "") { + return; + } + + $entity_name = add_txt_ent(${$mdocvars}{parabuf}); + ${$mdocvars}{parabuf} = ""; + if(defined($archlist{${$mdocvars}{Nm}})) { + $para_arch = ' arch="' . $archlist{${$mdocvars}{Nm}} . '"'; + } + $out = "<para".$para_arch.">&".$entity_name.";</para>"; + + dlog(4, "Flushing parabuf"); + add_sgmltag($mdocvars, $out); +} + +# Add a new list item from the "parabuf". +sub add_listitem { + my ($mdocvars) = (@_); + my ($listitem, $entity_name); + my $para_arch = ""; + + $entity_name = add_txt_ent(${$mdocvars}{parabuf}); + ${$mdocvars}{parabuf} = ""; + + if(defined($archlist{${$mdocvars}{Nm}})) { + $para_arch = ' arch="' . $archlist{${$mdocvars}{Nm}} . '"'; + } + $listitem = "<listitem><para".$para_arch.">&".$entity_name.";</para></listitem>"; + dlog(4, "Adding '$listitem' to out_dev"); + push(@out_dev, $listitem); + +} + +# Add a line to the "paragraph buffer" +sub parabuf_addline { + my $mdocvars = shift; + my ($txt) = (@_); + + dlog(5, "Now in parabuf_addline"); + + # We only care about the HW list for now. + if (!${$mdocvars}{isin_hwlist}) { + return; + } + if ($txt eq "") { + return; + } + + if ($only_list_out && !${$mdocvars}{isin_list}) { + return; + } + + # We only add the first line for "tag" lists + if (${$mdocvars}{parabuf} ne "" && ${$mdocvars}{isin_list} && + ${$mdocvars}{listtype} eq "tag") { + return; + } + + if (${$mdocvars}{parabuf} ne "") { + ${$mdocvars}{parabuf} .= " "; + } + + dlog(4, "Adding '$txt' to parabuf"); + + ${$mdocvars}{parabuf} .= $txt; +} + +sub load_archlist { + my ($file) = (@_); + + my $lineno = 0; + + dlog(2, "Parsing archlist $file"); + + open(FILE, "$file") || die("Could not open archlist $file\n"); + while(<FILE>) { + chomp; + $lineno++; + + if (/^#/ || $_ eq "") { + next; + } + + if (/(\w+)\t([\w,]+)/) { + dlog(4, "For driver $1 setting arch to $2"); + $archlist{$1} = $2; + } else { + dlog(1, "Could not parse line $lineno"); + } + } + + close(FILE); +} |