aboutsummaryrefslogtreecommitdiff
path: root/release/doc/share/misc/man2hwnotes.pl
diff options
context:
space:
mode:
authorSimon L. B. Nielsen <simon@FreeBSD.org>2004-08-03 22:12:45 +0000
committerSimon L. B. Nielsen <simon@FreeBSD.org>2004-08-03 22:12:45 +0000
commit4e702f5b140c8ab63afe07df4dd882310fc639be (patch)
tree201c61c13fdbfc870db0edc4181601f660590220 /release/doc/share/misc/man2hwnotes.pl
parentfdae98ecd6e3978107418c01d896c6d37b0e2821 (diff)
downloadsrc-4e702f5b140c8ab63afe07df4dd882310fc639be.tar.gz
src-4e702f5b140c8ab63afe07df4dd882310fc639be.zip
Auto generate the device listings in the Hardware Notes based on
manual pages, to avoid duplicating work between the Hardware Notes and manual pages. Each text line in the output from the manual page parser is generated as a SGML entity, making it possible for translators to only translate lines which actually contains English text (this neat idea came from hrs). To determine which drivers are usable on which architectures the dev.archlist.txt file is used to explicitly list this. It it an imperfect solution, but the best I have been able to come up with for now. This commit converts most of the devices which has a section 4 manual page with a HARDWARE section to be the new auto generated format. Reviewed in principle by: ru, hrs, trhodes Good ideas for improvements: hrs No objections: -doc, re
Notes
Notes: svn path=/head/; revision=133094
Diffstat (limited to 'release/doc/share/misc/man2hwnotes.pl')
-rw-r--r--release/doc/share/misc/man2hwnotes.pl353
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 000000000000..915728dfc783
--- /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/'/&lsquo;/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);
+}