1133094Ssimon#!/usr/bin/perl -w 2133094Ssimon# Emacs should use -*- cperl -*- mode 3133094Ssimon# 4160802Ssimon# Copyright (c) 2003-2006 Simon L. Nielsen <simon@FreeBSD.org> 5133094Ssimon# All rights reserved. 6133094Ssimon# 7133094Ssimon# Redistribution and use in source and binary forms, with or without 8133094Ssimon# modification, are permitted provided that the following conditions 9133094Ssimon# are met: 10133094Ssimon# 1. Redistributions of source code must retain the above copyright 11133094Ssimon# notice, this list of conditions and the following disclaimer. 12133094Ssimon# 2. Redistributions in binary form must reproduce the above copyright 13133094Ssimon# notice, this list of conditions and the following disclaimer in the 14133094Ssimon# documentation and/or other materials provided with the distribution. 15133094Ssimon# 16133094Ssimon# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17133094Ssimon# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18133094Ssimon# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19133094Ssimon# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20133094Ssimon# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21133094Ssimon# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22133094Ssimon# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23133094Ssimon# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24133094Ssimon# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25133094Ssimon# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26133094Ssimon# SUCH DAMAGE. 27133094Ssimon# 28133094Ssimon# $FreeBSD$ 29133094Ssimon# 30133094Ssimon 31133094Ssimon# Parse the list of supported hardware out of section 4 manual pages 32133094Ssimon# and output it on stdout as SGML/DocBook entities. 33133094Ssimon 34133094Ssimon# The script will look for the following line in the manual page: 35133094Ssimon# .Sh HARDWARE 36133094Ssimon# and make an entity of the content until the line containing: 37133094Ssimon# .Sh 38133094Ssimon# 39133094Ssimon# For Lists only the first line will be printed. If there are 40133094Ssimon# arguments to the .It command, only the argument will be printed. 41133094Ssimon 42133094Ssimon# Usage: 43166778Sbmah# man2hwnotes.pl [-cl] [-d 0-6] [-a <archlist file>] [-o <outputfile>] 44138845Ssimon# <manualpage> [<manualpage> ...] 45133094Ssimon 46133094Ssimonuse strict; 47133094Ssimonuse Getopt::Std; 48133094Ssimonuse Digest::MD5 qw(md5_hex); 49133094Ssimon 50133094Ssimon# Section from manual page to extract 51133094Ssimonmy $hwlist_sect = "HARDWARE"; 52133094Ssimon 53133094Ssimon# Override default archtecture list for some devices: 54133094Ssimonmy $archlist_file = "dev.archlist.txt"; 55133094Ssimonmy %archlist; 56133094Ssimon 57133094Ssimon# Globals 58166778Sbmahmy $compat_mode = 0; # Enable compat for old Hardware Notes style 59133094Ssimonmy $debuglevel = 0; 60133094Ssimonmy $only_list_out = 0; # Should only lists be generated in the output? 61133094Ssimonmy @out_lines; # Single lines 62133094Ssimonmy @out_dev; # Device entities 63133094Ssimon 64133094Ssimon# Getopt 65133094Ssimonmy %options = (); 66166778Sbmahif (!getopts("a:cd:lo:",\%options)) { 67133322Shrs die("$!: Invalid command line arguments in ", __LINE__, "\n"); 68133094Ssimon} 69133094Ssimon 70166778Sbmahif (defined($options{c})) { 71166778Sbmah $compat_mode = 1; 72166778Sbmah} 73133094Ssimonif (defined($options{d})) { 74133094Ssimon $debuglevel = $options{d}; 75133094Ssimon} 76133094Ssimonif (defined($options{a})) { 77133094Ssimon $archlist_file = $options{a}; 78133094Ssimon} 79133094Ssimonif (defined($options{l})) { 80133094Ssimon $only_list_out = 1; 81133094Ssimon} 82133094Ssimon 83133322Shrsmy $outputfile = $options{o}; 84133322Shrs 85133094Ssimonif ($debuglevel > 0) { 86133094Ssimon # Don't do output buffering in debug mode. 87133094Ssimon $| = 1; 88133094Ssimon} 89133094Ssimon 90133094Ssimonload_archlist($archlist_file); 91133094Ssimon 92133322Shrsif (defined($outputfile)) { 93133322Shrs open(OLDOUT, ">&STDOUT") || die("$!: Could not open STDOUT in ", __LINE__, ".\n"); 94133322Shrs open(STDOUT, ">$outputfile") || die("$!: Could not open $outputfile in ", __LINE__, ".\n"); 95133322Shrs} 96133322Shrs 97133322Shrsprint <<EOT; 98133322Shrs<!-- 99133322Shrs These are automatically generated device lists for FreeBSD hardware notes. 100133322Shrs--> 101133322ShrsEOT 102133322Shrs 103133094Ssimonif ($only_list_out) { 104133094Ssimon # Print the default device preamble entities 105240515Sgjb print "<!ENTITY hwlist.preamble.pre 'The'>\n"; 106240515Sgjb print "<!ENTITY hwlist.preamble.post 'driver supports:'>\n"; 107133094Ssimon} 108133094Ssimon 109133094Ssimonforeach my $page (@ARGV) { 110133322Shrs if ($page !~ m/\.4$/) { 111133322Shrs dlog(2, "Skipped $page (not *.4)"); 112133322Shrs next; 113133322Shrs } 114133094Ssimon dlog(2, "Parsing $page"); 115133094Ssimon parse($page); 116133094Ssimon 117133322Shrs if (@out_lines) { 118133322Shrs print join("\n", @out_lines), "\n"; 119133322Shrs } 120133322Shrs if (@out_dev) { 121133322Shrs print join("\n", @out_dev), "\n"; 122133322Shrs } 123133094Ssimon 124133094Ssimon @out_lines = (); 125133094Ssimon @out_dev = (); 126133094Ssimon} 127133094Ssimon 128133322Shrsif (defined($outputfile)) { 129133322Shrs open(STDOUT, ">&OLDOUT") || die("$!: Could not open STDOUT in ", __LINE__, ".\n"); 130133322Shrs close(OLDOUT) || die("$!: Could not close OLDOUT in ", __LINE__, ".\n"); 131133322Shrs} 132133322Shrs 133133322Shrssub normalize (@) { 134133322Shrs my @lines = @_; 135133322Shrs 136133322Shrs foreach my $l (@lines) { 137133780Ssimon $l =~ s/\\&//g; 138133322Shrs $l =~ s:([\x21-\x2f\x5b-\x60\x7b-\x7f]):sprintf("&\#\%d;", ord($1)):eg; 139134770Ssimon # Make sure ampersand is encoded as & since jade seems to 140134770Ssimon # be confused when it is encoded as & inside an entity. 141134770Ssimon $l =~ s/&/&/g; 142133322Shrs } 143133322Shrs return (wantarray) ? @lines : join "", @lines; 144133322Shrs} 145133322Shrs 146133094Ssimonsub parse { 147133094Ssimon my ($manpage) = @_; 148133094Ssimon 149133094Ssimon my $cur_mansection; 150133094Ssimon my $found_hwlist = 0; 151133094Ssimon my %mdocvars; 152133094Ssimon $mdocvars{isin_hwlist} = 0; 153133094Ssimon $mdocvars{isin_list} = 0; 154183621Ssimon $mdocvars{first_para} = 1; 155133094Ssimon $mdocvars{parabuf} = ""; 156133094Ssimon $mdocvars{listtype} = ""; 157134397Ssimon $mdocvars{it_nr} = 0; 158133094Ssimon 159133322Shrs open(MANPAGE, "$manpage") || die("$!: Could not open $manpage in ", __LINE__, ".\n"); 160133094Ssimon while(<MANPAGE>) { 161133094Ssimon chomp; 162133094Ssimon my $line = $_; 163133094Ssimon 164133094Ssimon dlog(5, "Read '$line'"); 165133094Ssimon 166133094Ssimon # Find commands 167133094Ssimon if (s/^\.(.*)$/$1/) { 168134397Ssimon my $cmd = $1; 169134397Ssimon 170133094Ssimon # Detect, and ignore, comment lines 171133094Ssimon if (s/^\\"(.*)$/$1/) { 172133094Ssimon next; 173133094Ssimon } 174133094Ssimon 175134397Ssimon $cmd =~ s/^([^ ]+).*$/$1/; 176134397Ssimon 177133094Ssimon if (/^Nm "?(\w+)"?/ && !defined($mdocvars{Nm})) { 178133094Ssimon dlog(3, "Setting Nm to $1"); 179133094Ssimon $mdocvars{Nm} = $1; 180134342Shrs # "_" cannot be used for an entity name. 181138845Ssimon $mdocvars{EntNm} = $1; 182138845Ssimon $mdocvars{EntNm} =~ s,_,.,g; 183133094Ssimon 184133094Ssimon } elsif (/^Nm$/) { 185133094Ssimon if (defined($mdocvars{Nm}) && $mdocvars{Nm} ne "") { 186138845Ssimon parabuf_addline(\%mdocvars, "&man.".$mdocvars{EntNm}.".$cur_mansection;"); 187133094Ssimon } else { 188133094Ssimon dlog(2, "Warning: Bad Nm call in $manpage"); 189133094Ssimon } 190133094Ssimon 191133094Ssimon } elsif (/^Sh (.+)$/) { 192133094Ssimon dlog(4, "Setting section to $1"); 193133094Ssimon my $cur_section = $1; 194133094Ssimon 195133094Ssimon flush_out(\%mdocvars); 196133094Ssimon 197133094Ssimon if ($cur_section =~ /^${hwlist_sect}$/) { 198133094Ssimon dlog(2, "Found the device section ${hwlist_sect}"); 199133094Ssimon $mdocvars{isin_hwlist} = 1; 200133094Ssimon $found_hwlist = 1; 201133094Ssimon add_sgmltag(\%mdocvars, "<!ENTITY hwlist.".$mdocvars{cur_manname}." '"); 202133094Ssimon if ($only_list_out) { 203257814Sgjb add_sgmltag("<para xmlns=\"http://docbook.org/ns/docbook\">&hwlist.preamble.pre; " . 204138845Ssimon "&man.".$mdocvars{EntNm}.".$cur_mansection; " . 205133094Ssimon "&hwlist.preamble.post;</para>"); 206133094Ssimon } 207133094Ssimon } elsif ($mdocvars{isin_hwlist}) { 208133094Ssimon dlog(2, "Found a HWLIST STOP key!"); 209133094Ssimon add_sgmltag(\%mdocvars, "'>"); 210133094Ssimon $mdocvars{isin_hwlist} = 0; 211133094Ssimon } 212160802Ssimon if ($mdocvars{isin_list}) { 213160802Ssimon dlog(1, "Warning: Still in list, but just entered new " . 214160802Ssimon "section. This is probably due to missing .El; " . 215160802Ssimon "check manual page for errors."); 216160802Ssimon # If we try to recover from this we will probably 217160802Ssimon # just end with bad SGML output and it really 218160802Ssimon # should be fixed in the manual page so we don't 219160802Ssimon # even try to "fix" this. 220160802Ssimon } 221133094Ssimon 222160802Ssimon 223133094Ssimon } elsif (/^Dt ([^ ]+) ([^ ]+)/) { 224133094Ssimon dlog(4, "Setting mansection to $2"); 225133094Ssimon $mdocvars{cur_manname} = lc($1); 226133094Ssimon $cur_mansection = $2; 227133094Ssimon 228134342Shrs # "_" cannot be used for an entity name. 229134342Shrs $mdocvars{cur_manname} =~ s,_,.,g; 230134342Shrs 231133094Ssimon } elsif (/^It ?(.*)$/) { 232134318Ssimon my $txt = $1; 233134318Ssimon 234134397Ssimon $mdocvars{it_nr}++; 235134397Ssimon 236133094Ssimon # Flush last item 237133094Ssimon if ($mdocvars{parabuf} ne "") { 238133094Ssimon add_listitem(\%mdocvars); 239133094Ssimon } 240134397Ssimon 241147767Ssimon # Remove quotes, if any. 242147767Ssimon $txt =~ s/"(.*)"/$1/; 243147767Ssimon 244134318Ssimon if ($mdocvars{listtype} eq "column") { 245134397Ssimon # Ignore first item when it is likely to be a 246134397Ssimon # header. 247134397Ssimon if ($mdocvars{it_nr} == 1 && $txt =~ m/^(Em|Sy) /) { 248134397Ssimon dlog(2, "Skipping header line in column list"); 249134397Ssimon next; 250134397Ssimon } 251134397Ssimon # Only extract the first column. 252134318Ssimon $txt =~ s/ Ta /\t/g; 253134318Ssimon $txt =~ s/([^\t]+)\t.*/$1/; 254134318Ssimon } 255197747Ssimon 256197747Ssimon # Remove Li commands 257197747Ssimon $txt =~ s/^Li //g; 258197747Ssimon 259134318Ssimon parabuf_addline(\%mdocvars, normalize($txt)); 260133094Ssimon } elsif (/^Bl/) { 261133094Ssimon $mdocvars{isin_list} = 1; 262133094Ssimon flush_out(\%mdocvars); 263257814Sgjb add_sgmltag(\%mdocvars, "<itemizedlist xmlns=\"http://docbook.org/ns/docbook\">"); 264133094Ssimon 265133094Ssimon if (/-tag/) { 266133094Ssimon $mdocvars{listtype} = "tag"; 267133094Ssimon # YACK! Hack for ata(4) 268133094Ssimon if ($mdocvars{Nm} eq "ata") { 269133094Ssimon $mdocvars{listtype} = "tagHACK"; 270133094Ssimon } 271133094Ssimon } elsif (/-bullet/) { 272133094Ssimon $mdocvars{listtype} = "bullet"; 273134318Ssimon } elsif (/-column/) { 274134318Ssimon $mdocvars{listtype} = "column"; 275133094Ssimon } else { 276133094Ssimon $mdocvars{listtype} = "unknown"; 277133094Ssimon } 278133094Ssimon dlog(2, "Listtype set to $mdocvars{listtype}"); 279133094Ssimon } elsif (/^El/) { 280133094Ssimon if ($mdocvars{parabuf} ne "") { 281133094Ssimon add_listitem(\%mdocvars); 282133094Ssimon } 283133094Ssimon 284133094Ssimon add_sgmltag(\%mdocvars, "</itemizedlist>"); 285133094Ssimon $mdocvars{isin_list} = 0; 286133094Ssimon } elsif (/^Tn (.+)$/) { 287133094Ssimon # For now we print TradeName text as regular text. 288134397Ssimon my ($txt, $punct_str) = split_punct_chars($1); 289133094Ssimon 290134397Ssimon parabuf_addline(\%mdocvars, normalize($txt . $punct_str)); 291134408Ssimon } elsif (/^Xr ([^ ]+) (.+)$/) { 292134408Ssimon my ($xr_sect, $punct_str) = split_punct_chars($2); 293134408Ssimon my $txt; 294134408Ssimon 295133094Ssimon # We need to check if the manual page exist to avoid 296133094Ssimon # breaking the doc build just because of a broken 297133094Ssimon # reference. 298134408Ssimon #$txt = "&man.$1.$xr_sect;$punct_str"; 299134408Ssimon $txt = "$1($xr_sect)$punct_str"; 300134408Ssimon parabuf_addline(\%mdocvars, normalize($txt)); 301133334Ssimon } elsif (/^Dq (.+)$/) { 302134397Ssimon my ($txt, $punct_str) = split_punct_chars($1); 303133334Ssimon 304134397Ssimon parabuf_addline(\%mdocvars, 305257814Sgjb normalize("<quote xmlns=\"http://docbook.org/ns/docbook\">$txt</quote>$punct_str")); 306133780Ssimon } elsif (/^Sx (.+)$/) { 307133780Ssimon if ($mdocvars{isin_hwlist}) { 308133780Ssimon dlog(1, "Warning: Reference to another section in the " . 309133780Ssimon "$hwlist_sect section in " . $mdocvars{Nm} . 310133780Ssimon "(${cur_mansection})"); 311133780Ssimon } 312133780Ssimon parabuf_addline(\%mdocvars, normalize($1)); 313134397Ssimon } elsif (/^Pa (.+)$/) { 314134397Ssimon my ($txt, $punct_str) = split_punct_chars($1); 315134397Ssimon 316134397Ssimon $txt = make_ulink($txt) . $punct_str; 317134397Ssimon parabuf_addline(\%mdocvars, normalize($txt)); 318183621Ssimon } elsif (/^Pp/) { 319183621Ssimon dlog(3, "Got Pp command - forcing new para"); 320183621Ssimon flush_out(\%mdocvars); 321183621Ssimon } elsif (/^Fx (.+)/) { 322183621Ssimon dlog(3, "Got Fx command"); 323183621Ssimon parabuf_addline(\%mdocvars, "FreeBSD $1"); 324183621Ssimon } elsif (/^Fx/) { 325183621Ssimon dlog(3, "Got Fx command"); 326183621Ssimon parabuf_addline(\%mdocvars, "FreeBSD"); 327230332Sjhb } elsif (/^Em (.+)$/) { 328230332Sjhb my ($txt, $punct_str) = split_punct_chars($1); 329230332Sjhb 330230332Sjhb parabuf_addline(\%mdocvars, 331257814Sgjb normalize("<emphasis xmlns=\"http://docbook.org/ns/docbook\">$txt</emphasis>$punct_str")); 332134397Ssimon } else { 333134397Ssimon # Ignore all other commands. 334134397Ssimon dlog(3, "Ignoring unknown command $cmd"); 335133094Ssimon } 336133094Ssimon } else { 337133094Ssimon # This is then regular text 338133322Shrs parabuf_addline(\%mdocvars, normalize($_)); 339133094Ssimon } 340133094Ssimon } 341133322Shrs close(MANPAGE) || die("$!: Could not close $manpage in ", __LINE__, ".\n"); 342133094Ssimon if (! $found_hwlist) { 343133780Ssimon dlog(2, "Hardware list not found in $manpage"); 344133094Ssimon } 345133094Ssimon} 346133094Ssimon 347133094Ssimonsub dlog { 348133094Ssimon my ($level, $txt) = @_; 349133094Ssimon 350133094Ssimon if ($level <= $debuglevel) { 351133094Ssimon print STDERR "$level: $txt\n"; 352133094Ssimon } 353133094Ssimon} 354133094Ssimon 355133094Ssimon# Output a SGML tag. 356133094Ssimonsub add_sgmltag { 357133094Ssimon my ($mdocvars, $txt) = (@_); 358133094Ssimon 359133094Ssimon # We only care about the HW list for now. 360133094Ssimon if (${$mdocvars}{isin_hwlist}) { 361133094Ssimon push(@out_dev, $txt); 362133094Ssimon } 363133094Ssimon} 364133094Ssimon 365133094Ssimon# Add a text entity, and return the used entity name. 366133094Ssimonsub add_txt_ent { 367133094Ssimon my ($itemtxt) = (@_); 368133094Ssimon my ($entity_name); 369133094Ssimon 370133094Ssimon # Convert mdoc(7) minus 371133094Ssimon $itemtxt =~ s/\\-/-/g; 372133094Ssimon 373133094Ssimon $itemtxt =~ s/'/‘/g; 374133094Ssimon 375133094Ssimon $entity_name = "hwlist." . md5_hex($itemtxt); 376133094Ssimon dlog(4, "Adding '$itemtxt' as entity $entity_name"); 377133094Ssimon push(@out_lines, "<!ENTITY $entity_name '$itemtxt'>"); 378133094Ssimon 379133094Ssimon return ($entity_name); 380133094Ssimon} 381133094Ssimonsub flush_out { 382133094Ssimon my ($mdocvars) = (@_); 383133094Ssimon my ($entity_name, $out); 384133094Ssimon my $para_arch = ""; 385133094Ssimon 386133094Ssimon if (!${$mdocvars}{isin_hwlist} || ${$mdocvars}{parabuf} eq "") { 387133094Ssimon return; 388133094Ssimon } 389133094Ssimon 390133094Ssimon $entity_name = add_txt_ent(${$mdocvars}{parabuf}); 391133094Ssimon ${$mdocvars}{parabuf} = ""; 392133094Ssimon if(defined($archlist{${$mdocvars}{Nm}})) { 393166778Sbmah if ($compat_mode) { 394166778Sbmah $para_arch = ' arch="' . $archlist{${$mdocvars}{Nm}} . '"'; 395166778Sbmah } else { 396166778Sbmah $para_arch = '[' . $archlist{${$mdocvars}{Nm}} . '] '; 397166778Sbmah } 398133094Ssimon } 399166778Sbmah if ($compat_mode) { 400257814Sgjb $out = "<para xmlns=\"http://docbook.org/ns/docbook\"".$para_arch.">&".$entity_name.";</para>"; 401166778Sbmah } else { 402183621Ssimon if (${$mdocvars}{first_para}) { 403257814Sgjb $out = "<para xmlns=\"http://docbook.org/ns/docbook\">".$para_arch."&".$entity_name.";</para>"; 404183621Ssimon } else { 405257814Sgjb $out = "<para xmlns=\"http://docbook.org/ns/docbook\">&".$entity_name.";</para>"; 406183621Ssimon } 407183621Ssimon ${$mdocvars}{first_para} = 0; 408166778Sbmah } 409133094Ssimon 410133094Ssimon dlog(4, "Flushing parabuf"); 411133094Ssimon add_sgmltag($mdocvars, $out); 412133094Ssimon} 413133094Ssimon 414133094Ssimon# Add a new list item from the "parabuf". 415133094Ssimonsub add_listitem { 416133094Ssimon my ($mdocvars) = (@_); 417133094Ssimon my ($listitem, $entity_name); 418133094Ssimon my $para_arch = ""; 419133094Ssimon 420133094Ssimon $entity_name = add_txt_ent(${$mdocvars}{parabuf}); 421133094Ssimon ${$mdocvars}{parabuf} = ""; 422133094Ssimon 423166778Sbmah if ($compat_mode) { 424166778Sbmah if(defined($archlist{${$mdocvars}{Nm}})) { 425166778Sbmah $para_arch = ' arch="' . $archlist{${$mdocvars}{Nm}} . '"'; 426166778Sbmah } 427133094Ssimon } 428133094Ssimon $listitem = "<listitem><para".$para_arch.">&".$entity_name.";</para></listitem>"; 429133094Ssimon dlog(4, "Adding '$listitem' to out_dev"); 430133094Ssimon push(@out_dev, $listitem); 431133094Ssimon 432133094Ssimon} 433133094Ssimon 434133094Ssimon# Add a line to the "paragraph buffer" 435133094Ssimonsub parabuf_addline { 436133094Ssimon my $mdocvars = shift; 437133094Ssimon my ($txt) = (@_); 438133094Ssimon 439160802Ssimon dlog(5, "Now in parabuf_addline for '$txt'"); 440133094Ssimon 441133094Ssimon # We only care about the HW list for now. 442133094Ssimon if (!${$mdocvars}{isin_hwlist}) { 443160802Ssimon dlog(6, "Exiting parabuf_addline due to: !\${\$mdocvars}{isin_hwlist}"); 444133094Ssimon return; 445133094Ssimon } 446133094Ssimon if ($txt eq "") { 447160802Ssimon dlog(6, "Exiting parabuf_addline due to: \$txt eq \"\""); 448133094Ssimon return; 449133094Ssimon } 450133094Ssimon 451133094Ssimon if ($only_list_out && !${$mdocvars}{isin_list}) { 452160802Ssimon dlog(6, "Exiting parabuf_addline due to: ". 453160802Ssimon "\$only_list_out && !\${\$mdocvars}{isin_list}"); 454133094Ssimon return; 455133094Ssimon } 456133094Ssimon 457133094Ssimon # We only add the first line for "tag" lists 458133094Ssimon if (${$mdocvars}{parabuf} ne "" && ${$mdocvars}{isin_list} && 459133094Ssimon ${$mdocvars}{listtype} eq "tag") { 460160802Ssimon dlog(6, "Exiting parabuf_addline due to: ". 461160802Ssimon "\${\$mdocvars}{parabuf} ne \"\" && \${\$mdocvars}{isin_list} && ". 462160802Ssimon "\${\$mdocvars}{listtype} eq \"tag\""); 463133094Ssimon return; 464133094Ssimon } 465133094Ssimon 466133094Ssimon if (${$mdocvars}{parabuf} ne "") { 467133094Ssimon ${$mdocvars}{parabuf} .= " "; 468133094Ssimon } 469133094Ssimon 470133094Ssimon dlog(4, "Adding '$txt' to parabuf"); 471133094Ssimon 472133094Ssimon ${$mdocvars}{parabuf} .= $txt; 473133094Ssimon} 474133094Ssimon 475133094Ssimonsub load_archlist { 476133094Ssimon my ($file) = (@_); 477133094Ssimon 478133094Ssimon my $lineno = 0; 479133094Ssimon 480133094Ssimon dlog(2, "Parsing archlist $file"); 481133094Ssimon 482133322Shrs open(FILE, "$file") || die("$!: Could not open archlist $file in ", __LINE__, ".\n"); 483133094Ssimon while(<FILE>) { 484133094Ssimon chomp; 485133094Ssimon $lineno++; 486133094Ssimon 487133094Ssimon if (/^#/ || $_ eq "") { 488133094Ssimon next; 489133094Ssimon } 490133094Ssimon 491133094Ssimon if (/(\w+)\t([\w,]+)/) { 492133094Ssimon dlog(4, "For driver $1 setting arch to $2"); 493133094Ssimon $archlist{$1} = $2; 494133094Ssimon } else { 495135080Ssimon dlog(1, "Warning: Could not parse archlist line $lineno"); 496133094Ssimon } 497133094Ssimon } 498133094Ssimon 499133094Ssimon close(FILE); 500133094Ssimon} 501133334Ssimon 502133334Ssimon# Check if a character is a mdoc(7) punctuation character. 503133334Ssimonsub is_punct_char { 504133334Ssimon my ($str) = (@_); 505133334Ssimon 506134397Ssimon return (length($str) == 1 && $str =~ /[\.,:;()\[\]\?!]/); 507133334Ssimon} 508134397Ssimon 509134397Ssimon# Split out the punctuation characters of a mdoc(7) line. 510134397Ssimonsub split_punct_chars { 511134397Ssimon my ($str) = (@_); 512134397Ssimon my (@stritems, $stritem, $punct_str); 513134397Ssimon 514134397Ssimon $punct_str = ""; 515134397Ssimon @stritems = split(/ /, $str); 516134397Ssimon 517134397Ssimon while (defined($stritem = $stritems[$#stritems]) && 518134397Ssimon is_punct_char($stritem)) { 519134397Ssimon $punct_str = $stritem . $punct_str; 520134397Ssimon pop(@stritems); 521134397Ssimon } 522134397Ssimon 523134397Ssimon return (join(' ', @stritems), $punct_str); 524134397Ssimon} 525134397Ssimon 526134397Ssimon# Create a ulink, if the string contains an URL. 527134397Ssimonsub make_ulink { 528134397Ssimon my ($str) = (@_); 529134397Ssimon 530257814Sgjb $str =~ s,(http://[^ ]+),<link xmlns=\"http://docbook.org/ns/docbook\" xlink:href="$1"></link>,; 531134397Ssimon 532134397Ssimon return $str; 533134397Ssimon} 534