diff options
Diffstat (limited to 'doc/rdsrc.pl')
-rw-r--r-- | doc/rdsrc.pl | 1509 |
1 files changed, 1509 insertions, 0 deletions
diff --git a/doc/rdsrc.pl b/doc/rdsrc.pl new file mode 100644 index 0000000..de3a862 --- /dev/null +++ b/doc/rdsrc.pl @@ -0,0 +1,1509 @@ +#!/usr/bin/perl +## -------------------------------------------------------------------------- +## +## Copyright 1996-2009 The NASM Authors - All Rights Reserved +## See the file AUTHORS included with the NASM distribution for +## the specific copyright holders. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following +## conditions are met: +## +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. +## +## -------------------------------------------------------------------------- + + +# Read the source-form of the NASM manual and generate the various +# output forms. + +# TODO: +# +# Ellipsis support would be nice. + +# Source-form features: +# --------------------- +# +# Bullet \b +# Bullets the paragraph. Rest of paragraph is indented to cope. In +# HTML, consecutive groups of bulleted paragraphs become unordered +# lists. +# +# Emphasis \e{foobar} +# produces `_foobar_' in text and italics in HTML, PS, RTF +# +# Inline code \c{foobar} +# produces ``foobar'' in text, and fixed-pitch font in HTML, PS, RTF +# +# Display code +# \c line one +# \c line two +# produces fixed-pitch font where appropriate, and doesn't break +# pages except sufficiently far into the middle of a display. +# +# Chapter, header and subheader +# \C{intro} Introduction +# \H{whatsnasm} What is NASM? +# \S{free} NASM Is Free +# dealt with as appropriate. Chapters begin on new sides, possibly +# even new _pages_. (Sub)?headers are good places to begin new +# pages. Just _after_ a (sub)?header isn't. +# The keywords can be substituted with \K and \k. +# +# Keyword \K{cintro} \k{cintro} +# Expands to `Chapter 1', `Section 1.1', `Section 1.1.1'. \K has an +# initial capital whereas \k doesn't. In HTML, will produce +# hyperlinks. +# +# Web link \W{http://foobar/}{text} or \W{mailto:me@here}\c{me@here} +# the \W prefix is ignored except in HTML; in HTML the last part +# becomes a hyperlink to the first part. +# +# Literals \{ \} \\ +# In case it's necessary, they expand to the real versions. +# +# Nonbreaking hyphen \- +# Need more be said? +# +# Source comment \# +# Causes everything after it on the line to be ignored by the +# source-form processor. +# +# Indexable word \i{foobar} (or \i\e{foobar} or \i\c{foobar}, equally) +# makes word appear in index, referenced to that point +# \i\c comes up in code style even in the index; \i\e doesn't come +# up in emphasised style. +# +# Indexable non-displayed word \I{foobar} or \I\c{foobar} +# just as \i{foobar} except that nothing is displayed for it +# +# Index rewrite +# \IR{foobar} \c{foobar} operator, uses of +# tidies up the appearance in the index of something the \i or \I +# operator was applied to +# +# Index alias +# \IA{foobar}{bazquux} +# aliases one index tag (as might be supplied to \i or \I) to +# another, so that \I{foobar} has the effect of \I{bazquux}, and +# \i{foobar} has the effect of \I{bazquux}foobar +# +# Metadata +# \M{key}{something} +# defines document metadata, such as authorship, title and copyright; +# different output formats use this differently. +# +# Include subfile +# \&{filename} +# Includes filename. Recursion is allowed. +# + +use IO::File; + +$diag = 1, shift @ARGV if $ARGV[0] eq "-d"; + +($out_format) = @ARGV; + +$| = 1; + +$tstruct_previtem = $node = "Top"; +$nodes = ($node); +$tstruct_level{$tstruct_previtem} = 0; +$tstruct_last[$tstruct_level{$tstruct_previtem}] = $tstruct_previtem; +$MAXLEVEL = 10; # really 3, but play safe ;-) + +# Read the file; pass a paragraph at a time to the paragraph processor. +print "Reading input..."; +$pname = "para000000"; +@pnames = @pflags = (); +$para = undef; +while (defined($_ = <STDIN>)) { + $_ = &untabify($_); + &check_include($_); +} +&got_para($para); +print "done.\n"; + +# Now we've read in the entire document and we know what all the +# heading keywords refer to. Go through and fix up the \k references. +print "Fixing up cross-references..."; +&fixup_xrefs; +print "done.\n"; + +# Sort the index tags, according to the slightly odd order I've decided on. +print "Sorting index tags..."; +&indexsort; +print "done.\n"; + +if ($diag) { + print "Writing index-diagnostic file..."; + &indexdiag; + print "done.\n"; +} + +# OK. Write out the various output files. +if ($out_format eq 'txt') { + print "Producing text output: "; + &write_txt; + print "done.\n"; +} elsif ($out_format eq 'html') { + print "Producing HTML output: "; + &write_html; + print "done.\n"; +} elsif ($out_format eq 'texi') { + print "Producing Texinfo output: "; + &write_texi; + print "done.\n"; +} elsif ($out_format eq 'hlp') { + print "Producing WinHelp output: "; + &write_hlp; + print "done.\n"; +} elsif ($out_format eq 'dip') { + print "Producing Documentation Intermediate Paragraphs: "; + &write_dip; + print "done.\n"; +} else { + die "$0: unknown output format: $out_format\n"; +} + +sub untabify($) { + my($s) = @_; + my $o = ''; + my($c, $i, $p); + + $p = 0; + for ($i = 0; $i < length($s); $i++) { + $c = substr($s, $i, 1); + if ($c eq "\t") { + do { + $o .= ' '; + $p++; + } while ($p & 7); + } else { + $o .= $c; + $p++; + } + } + return $o; +} +sub check_include { + local $_ = shift; + if (/\\& (\S+)/) { + &include($1); + } else { + &get_para($_); + } +} +sub get_para($_) { + chomp; + if (!/\S/ || /^\\(IA|IR|M)/) { # special case: \IA \IR \M imply new-paragraph + &got_para($para); + $para = undef; + } + if (/\S/) { + s/\\#.*$//; # strip comments + $para .= " " . $_; + } +} +sub include { + my $name = shift; + my $F = IO::File->new($name) + or die "Cannot open $name: $!"; + while (<$F>) { + &check_include($_); + } +} +sub got_para { + local ($_) = @_; + my $pflags = "", $i, $w, $l, $t; + return if !/\S/; + + @$pname = (); + + # Strip off _leading_ spaces, then determine type of paragraph. + s/^\s*//; + $irewrite = undef; + if (/^\\c[^{]/) { + # A code paragraph. The paragraph-array will contain the simple + # strings which form each line of the paragraph. + $pflags = "code"; + while (/^\\c (([^\\]|\\[^c])*)(.*)$/) { + $l = $1; + $_ = $3; + $l =~ s/\\{/{/g; + $l =~ s/\\}/}/g; + $l =~ s/\\\\/\\/g; + push @$pname, $l; + } + $_ = ''; # suppress word-by-word code + } elsif (/^\\C/) { + # A chapter heading. Define the keyword and allocate a chapter + # number. + $cnum++; + $hnum = 0; + $snum = 0; + $xref = "chapter-$cnum"; + $pflags = "chap $cnum :$xref"; + die "badly formatted chapter heading: $_\n" if !/^\\C{([^}]*)}\s*(.*)$/; + $refs{$1} = "chapter $cnum"; + $node = "Chapter $cnum"; + &add_item($node, 1); + $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node; + $xrefs{$1} = $xref; + $_ = $2; + # the standard word-by-word code will happen next + } elsif (/^\\A/) { + # An appendix heading. Define the keyword and allocate an appendix + # letter. + $cnum++; + $cnum = 'A' if $cnum =~ /[0-9]+/; + $hnum = 0; + $snum = 0; + $xref = "appendix-$cnum"; + $pflags = "appn $cnum :$xref"; + die "badly formatted appendix heading: $_\n" if !/^\\A{([^}]*)}\s*(.*)$/; + $refs{$1} = "appendix $cnum"; + $node = "Appendix $cnum"; + &add_item($node, 1); + $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node; + $xrefs{$1} = $xref; + $_ = $2; + # the standard word-by-word code will happen next + } elsif (/^\\H/) { + # A major heading. Define the keyword and allocate a section number. + $hnum++; + $snum = 0; + $xref = "section-$cnum.$hnum"; + $pflags = "head $cnum.$hnum :$xref"; + die "badly formatted heading: $_\n" if !/^\\[HP]{([^}]*)}\s*(.*)$/; + $refs{$1} = "section $cnum.$hnum"; + $node = "Section $cnum.$hnum"; + &add_item($node, 2); + $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node; + $xrefs{$1} = $xref; + $_ = $2; + # the standard word-by-word code will happen next + } elsif (/^\\S/) { + # A sub-heading. Define the keyword and allocate a section number. + $snum++; + $xref = "section-$cnum.$hnum.$snum"; + $pflags = "subh $cnum.$hnum.$snum :$xref"; + die "badly formatted subheading: $_\n" if !/^\\S{([^}]*)}\s*(.*)$/; + $refs{$1} = "section $cnum.$hnum.$snum"; + $node = "Section $cnum.$hnum.$snum"; + &add_item($node, 3); + $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node; + $xrefs{$1} = $xref; + $_ = $2; + # the standard word-by-word code will happen next + } elsif (/^\\IR/) { + # An index-rewrite. + die "badly formatted index rewrite: $_\n" if !/^\\IR{([^}]*)}\s*(.*)$/; + $irewrite = $1; + $_ = $2; + # the standard word-by-word code will happen next + } elsif (/^\\IA/) { + # An index-alias. + die "badly formatted index alias: $_\n" if !/^\\IA{([^}]*)}{([^}]*)}\s*$/; + $idxalias{$1} = $2; + return; # avoid word-by-word code + } elsif (/^\\M/) { + # Metadata + die "badly formed metadata: $_\n" if !/^\\M{([^}]*)}{([^}]*)}\s*$/; + $metadata{$1} = $2; + return; # avoid word-by-word code + } elsif (/^\\b/) { + # A bulleted paragraph. Strip off the initial \b and let the + # word-by-word code take care of the rest. + $pflags = "bull"; + s/^\\b\s*//; + } else { + # A normal paragraph. Just set $pflags: the word-by-word code does + # the rest. + $pflags = "norm"; + } + + # The word-by-word code: unless @$pname is already defined (which it + # will be in the case of a code paragraph), split the paragraph up + # into words and push each on @$pname. + # + # Each thing pushed on @$pname should have a two-character type + # code followed by the text. + # + # Type codes are: + # "n " for normal + # "da" for a dash + # "es" for first emphasised word in emphasised bit + # "e " for emphasised in mid-emphasised-bit + # "ee" for last emphasised word in emphasised bit + # "eo" for single (only) emphasised word + # "c " for code + # "k " for cross-ref + # "kK" for capitalised cross-ref + # "w " for Web link + # "wc" for code-type Web link + # "x " for beginning of resolved cross-ref; generates no visible output, + # and the text is the cross-reference code + # "xe" for end of resolved cross-ref; text is same as for "x ". + # "i " for point to be indexed: the text is the internal index into the + # index-items arrays + # "sp" for space + while (/\S/) { + s/^\s*//, push @$pname, "sp" if /^\s/; + $indexing = $qindex = 0; + if (/^(\\[iI])?\\c/) { + $qindex = 1 if $1 eq "\\I"; + $indexing = 1, s/^\\[iI]// if $1; + s/^\\c//; + die "badly formatted \\c: \\c$_\n" if !/{(([^\\}]|\\.)*)}(.*)$/; + $w = $1; + $_ = $3; + $w =~ s/\\{/{/g; + $w =~ s/\\}/}/g; + $w =~ s/\\-/-/g; + $w =~ s/\\\\/\\/g; + (push @$pname,"i"),$lastp = $#$pname if $indexing; + push @$pname,"c $w" if !$qindex; + $$pname[$lastp] = &addidx($node, $w, "c $w") if $indexing; + } elsif (/^\\[iIe]/) { + /^(\\[iI])?(\\e)?/; + $emph = 0; + $qindex = 1 if $1 eq "\\I"; + $indexing = 1, $type = "\\i" if $1; + $emph = 1, $type = "\\e" if $2; + s/^(\\[iI])?(\\e?)//; + die "badly formatted $type: $type$_\n" if !/{(([^\\}]|\\.)*)}(.*)$/; + $w = $1; + $_ = $3; + $w =~ s/\\{/{/g; + $w =~ s/\\}/}/g; + $w =~ s/\\-/-/g; + $w =~ s/\\\\/\\/g; + $t = $emph ? "es" : "n "; + @ientry = (); + (push @$pname,"i"),$lastp = $#$pname if $indexing; + foreach $i (split /\s+/,$w) { # \e and \i can be multiple words + push @$pname,"$t$i","sp" if !$qindex; + ($ii=$i) =~ tr/A-Z/a-z/, push @ientry,"n $ii","sp" if $indexing; + $t = $emph ? "e " : "n "; + } + $w =~ tr/A-Z/a-z/, pop @ientry if $indexing; + $$pname[$lastp] = &addidx($node, $w, @ientry) if $indexing; + pop @$pname if !$qindex; # remove final space + if (substr($$pname[$#$pname],0,2) eq "es" && !$qindex) { + substr($$pname[$#$pname],0,2) = "eo"; + } elsif ($emph && !$qindex) { + substr($$pname[$#$pname],0,2) = "ee"; + } + } elsif (/^\\[kK]/) { + $t = "k "; + $t = "kK" if /^\\K/; + s/^\\[kK]//; + die "badly formatted \\k: \\c$_\n" if !/{([^}]*)}(.*)$/; + $_ = $2; + push @$pname,"$t$1"; + } elsif (/^\\W/) { + s/^\\W//; + die "badly formatted \\W: \\W$_\n" + if !/{([^}]*)}(\\i)?(\\c)?{(([^\\}]|\\.)*)}(.*)$/; + $l = $1; + $w = $4; + $_ = $6; + $t = "w "; + $t = "wc" if $3 eq "\\c"; + $indexing = 1 if $2; + $w =~ s/\\{/{/g; + $w =~ s/\\}/}/g; + $w =~ s/\\-/-/g; + $w =~ s/\\\\/\\/g; + (push @$pname,"i"),$lastp = $#$pname if $indexing; + push @$pname,"$t<$l>$w"; + $$pname[$lastp] = &addidx($node, $w, "c $w") if $indexing; + } else { + die "what the hell? $_\n" if !/^(([^\s\\\-]|\\[\\{}\-])*-?)(.*)$/; + die "painful death! $_\n" if !length $1; + $w = $1; + $_ = $3; + $w =~ s/\\{/{/g; + $w =~ s/\\}/}/g; + $w =~ s/\\-/-/g; + $w =~ s/\\\\/\\/g; + if ($w eq "-") { + push @$pname,"da"; + } else { + push @$pname,"n $w"; + } + } + } + if ($irewrite ne undef) { + &addidx(undef, $irewrite, @$pname); + @$pname = (); + } else { + push @pnames, $pname; + push @pflags, $pflags; + $pname++; + } +} + +sub addidx { + my ($node, $text, @ientry) = @_; + $text = $idxalias{$text} || $text; + if ($node eq undef || !$idxmap{$text}) { + @$ientry = @ientry; + $idxmap{$text} = $ientry; + $ientry++; + } + if ($node) { + $idxnodes{$node,$text} = 1; + return "i $text"; + } +} + +sub indexsort { + my $iitem, $ientry, $i, $piitem, $pcval, $cval, $clrcval; + + @itags = map { # get back the original data as the 1st elt of each list + $_->[0] + } sort { # compare auxiliary (non-first) elements of lists + $a->[1] cmp $b->[1] || + $a->[2] cmp $b->[2] || + $a->[0] cmp $b->[0] + } map { # transform array into list of 3-element lists + my $ientry = $idxmap{$_}; + my $a = substr($$ientry[0],2); + $a =~ tr/A-Za-z0-9//cd; + [$_, uc($a), substr($$ientry[0],0,2)] + } keys %idxmap; + + # Having done that, check for comma-hood. + $cval = 0; + foreach $iitem (@itags) { + $ientry = $idxmap{$iitem}; + $clrcval = 1; + $pcval = $cval; + FL:for ($i=0; $i <= $#$ientry; $i++) { + if ($$ientry[$i] =~ /^(n .*,)(.*)/) { + $$ientry[$i] = $1; + splice @$ientry,$i+1,0,"n $2" if length $2; + $commapos{$iitem} = $i+1; + $cval = join("\002", @$ientry[0..$i]); + $clrcval = 0; + last FL; + } + } + $cval = undef if $clrcval; + $commanext{$iitem} = $commaafter{$piitem} = 1 + if $cval and ($cval eq $pcval); + $piitem = $iitem; + } +} + +sub indexdiag { + my $iitem,$ientry,$w,$ww,$foo,$node; + open INDEXDIAG,">index.diag"; + foreach $iitem (@itags) { + $ientry = $idxmap{$iitem}; + print INDEXDIAG "<$iitem> "; + foreach $w (@$ientry) { + $ww = &word_txt($w); + print INDEXDIAG $ww unless $ww eq "\001"; + } + print INDEXDIAG ":"; + $foo = " "; + foreach $node (@nodes) { + (print INDEXDIAG $foo,$node), $foo = ", " if $idxnodes{$node,$iitem}; + } + print INDEXDIAG "\n"; + } + close INDEXDIAG; +} + +sub fixup_xrefs { + my $pname, $p, $i, $j, $k, $caps, @repl; + + for ($p=0; $p<=$#pnames; $p++) { + next if $pflags[$p] eq "code"; + $pname = $pnames[$p]; + for ($i=$#$pname; $i >= 0; $i--) { + if ($$pname[$i] =~ /^k/) { + $k = $$pname[$i]; + $caps = ($k =~ /^kK/); + $k = substr($k,2); + $repl = $refs{$k}; + die "undefined keyword `$k'\n" unless $repl; + substr($repl,0,1) =~ tr/a-z/A-Z/ if $caps; + @repl = (); + push @repl,"x $xrefs{$k}"; + foreach $j (split /\s+/,$repl) { + push @repl,"n $j"; + push @repl,"sp"; + } + pop @repl; # remove final space + push @repl,"xe$xrefs{$k}"; + splice @$pname,$i,1,@repl; + } + } + } +} + +sub write_txt { + # This is called from the top level, so I won't bother using + # my or local. + + # Open file. + print "writing file..."; + open TEXT,">nasmdoc.txt"; + select TEXT; + + # Preamble. + $title = "The Netwide Assembler: NASM"; + $spaces = ' ' x ((75-(length $title))/2); + ($underscore = $title) =~ s/./=/g; + print "$spaces$title\n$spaces$underscore\n"; + + for ($para = 0; $para <= $#pnames; $para++) { + $pname = $pnames[$para]; + $pflags = $pflags[$para]; + $ptype = substr($pflags,0,4); + + print "\n"; # always one of these before a new paragraph + + if ($ptype eq "chap") { + # Chapter heading. "Chapter N: Title" followed by a line of + # minus signs. + $pflags =~ /chap (.*) :(.*)/; + $title = "Chapter $1: "; + foreach $i (@$pname) { + $ww = &word_txt($i); + $title .= $ww unless $ww eq "\001"; + } + print "$title\n"; + $title =~ s/./-/g; + print "$title\n"; + } elsif ($ptype eq "appn") { + # Appendix heading. "Appendix N: Title" followed by a line of + # minus signs. + $pflags =~ /appn (.*) :(.*)/; + $title = "Appendix $1: "; + foreach $i (@$pname) { + $ww = &word_txt($i); + $title .= $ww unless $ww eq "\001"; + } + print "$title\n"; + $title =~ s/./-/g; + print "$title\n"; + } elsif ($ptype eq "head" || $ptype eq "subh") { + # Heading or subheading. Just a number and some text. + $pflags =~ /.... (.*) :(.*)/; + $title = sprintf "%6s ", $1; + foreach $i (@$pname) { + $ww = &word_txt($i); + $title .= $ww unless $ww eq "\001"; + } + print "$title\n"; + } elsif ($ptype eq "code") { + # Code paragraph. Emit each line with a seven character indent. + foreach $i (@$pname) { + warn "code line longer than 68 chars: $i\n" if length $i > 68; + print ' 'x7, $i, "\n"; + } + } elsif ($ptype eq "bull" || $ptype eq "norm") { + # Ordinary paragraph, optionally bulleted. We wrap, with ragged + # 75-char right margin and either 7 or 11 char left margin + # depending on bullets. + if ($ptype eq "bull") { + $line = ' 'x7 . '(*) '; + $next = ' 'x11; + } else { + $line = $next = ' 'x7; + } + @a = @$pname; + $wd = $wprev = ''; + do { + do { $w = &word_txt(shift @a) } while $w eq "\001"; # nasty hack + $wd .= $wprev; + if ($wprev =~ /-$/ || $w eq ' ' || $w eq '' || $w eq undef) { + if (length ($line . $wd) > 75) { + $line =~ s/\s*$//; # trim trailing spaces + print "$line\n"; + $line = $next; + $wd =~ s/^\s*//; # trim leading spaces + } + $line .= $wd; + $wd = ''; + } + $wprev = $w; + } while ($w ne '' && $w ne undef); + if ($line =~ /\S/) { + $line =~ s/\s*$//; # trim trailing spaces + print "$line\n"; + } + } + } + + # Close file. + select STDOUT; + close TEXT; +} + +sub word_txt { + my ($w) = @_; + my $wtype, $wmajt; + + return undef if $w eq '' || $w eq undef; + $wtype = substr($w,0,2); + $wmajt = substr($wtype,0,1); + $w = substr($w,2); + $w =~ s/<.*>// if $wmajt eq "w"; # remove web links + if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") { + return $w; + } elsif ($wtype eq "sp") { + return ' '; + } elsif ($wtype eq "da") { + return '-'; + } elsif ($wmajt eq "c" || $wtype eq "wc") { + return "`${w}'"; + } elsif ($wtype eq "es") { + return "_${w}"; + } elsif ($wtype eq "ee") { + return "${w}_"; + } elsif ($wtype eq "eo") { + return "_${w}_"; + } elsif ($wmajt eq "x" || $wmajt eq "i") { + return "\001"; + } else { + die "panic in word_txt: $wtype$w\n"; + } +} + +sub write_html { + # This is called from the top level, so I won't bother using + # my or local. + + # Write contents file. Just the preamble, then a menu of links to the + # separate chapter files and the nodes therein. + print "writing contents file..."; + open TEXT,">nasmdoc0.html"; + select TEXT; + &html_preamble(0); + print "<p>This manual documents NASM, the Netwide Assembler: an assembler\n"; + print "targetting the Intel x86 series of processors, with portable source.\n"; + print "<p>"; + for ($node = $tstruct_next{'Top'}; $node; $node = $tstruct_next{$node}) { + if ($tstruct_level{$node} == 1) { + # Invent a file name. + ($number = lc($xrefnodes{$node})) =~ s/.*-//; + $fname="nasmdocx.html"; + substr($fname,8 - length $number, length $number) = $number; + $html_fnames{$node} = $fname; + $link = $fname; + print "<p>"; + } else { + # Use the preceding filename plus a marker point. + $link = $fname . "#$xrefnodes{$node}"; + } + $title = "$node: "; + $pname = $tstruct_pname{$node}; + foreach $i (@$pname) { + $ww = &word_html($i); + $title .= $ww unless $ww eq "\001"; + } + print "<a href=\"$link\">$title</a><br>\n"; + } + print "<p><a href=\"nasmdoci.html\">Index</a>\n"; + print "</body></html>\n"; + select STDOUT; + close TEXT; + + # Open a null file, to ensure output (eg random &html_jumppoints calls) + # goes _somewhere_. + print "writing chapter files..."; + open TEXT,">/dev/null"; + select TEXT; + $html_lastf = ''; + + $in_list = 0; + + for ($para = 0; $para <= $#pnames; $para++) { + $pname = $pnames[$para]; + $pflags = $pflags[$para]; + $ptype = substr($pflags,0,4); + + $in_list = 0, print "</ul>\n" if $in_list && $ptype ne "bull"; + if ($ptype eq "chap") { + # Chapter heading. Begin a new file. + $pflags =~ /chap (.*) :(.*)/; + $title = "Chapter $1: "; + $xref = $2; + &html_jumppoints; print "</body></html>\n"; select STDOUT; close TEXT; + $html_lastf = $html_fnames{$chapternode}; + $chapternode = $nodexrefs{$xref}; + $html_nextf = $html_fnames{$tstruct_mnext{$chapternode}}; + open TEXT,">$html_fnames{$chapternode}"; select TEXT; &html_preamble(1); + foreach $i (@$pname) { + $ww = &word_html($i); + $title .= $ww unless $ww eq "\001"; + } + $h = "<h2><a name=\"$xref\">$title</a></h2>\n"; + print $h; print FULL $h; + } elsif ($ptype eq "appn") { + # Appendix heading. Begin a new file. + $pflags =~ /appn (.*) :(.*)/; + $title = "Appendix $1: "; + $xref = $2; + &html_jumppoints; print "</body></html>\n"; select STDOUT; close TEXT; + $html_lastf = $html_fnames{$chapternode}; + $chapternode = $nodexrefs{$xref}; + $html_nextf = $html_fnames{$tstruct_mnext{$chapternode}}; + open TEXT,">$html_fnames{$chapternode}"; select TEXT; &html_preamble(1); + foreach $i (@$pname) { + $ww = &word_html($i); + $title .= $ww unless $ww eq "\001"; + } + print "<h2><a name=\"$xref\">$title</a></h2>\n"; + } elsif ($ptype eq "head" || $ptype eq "subh") { + # Heading or subheading. + $pflags =~ /.... (.*) :(.*)/; + $hdr = ($ptype eq "subh" ? "h4" : "h3"); + $title = $1 . " "; + $xref = $2; + foreach $i (@$pname) { + $ww = &word_html($i); + $title .= $ww unless $ww eq "\001"; + } + print "<$hdr><a name=\"$xref\">$title</a></$hdr>\n"; + } elsif ($ptype eq "code") { + # Code paragraph. + print "<p><pre>\n"; + foreach $i (@$pname) { + $w = $i; + $w =~ s/&/&/g; + $w =~ s/</</g; + $w =~ s/>/>/g; + print $w, "\n"; + } + print "</pre>\n"; + } elsif ($ptype eq "bull" || $ptype eq "norm") { + # Ordinary paragraph, optionally bulleted. We wrap, with ragged + # 75-char right margin and either 7 or 11 char left margin + # depending on bullets. + if ($ptype eq "bull") { + $in_list = 1, print "<ul>\n" unless $in_list; + $line = '<li>'; + } else { + $line = '<p>'; + } + @a = @$pname; + $wd = $wprev = ''; + do { + do { $w = &word_html(shift @a) } while $w eq "\001"; # nasty hack + $wd .= $wprev; + if ($w eq ' ' || $w eq '' || $w eq undef) { + if (length ($line . $wd) > 75) { + $line =~ s/\s*$//; # trim trailing spaces + print "$line\n"; + $line = ''; + $wd =~ s/^\s*//; # trim leading spaces + } + $line .= $wd; + $wd = ''; + } + $wprev = $w; + } while ($w ne '' && $w ne undef); + if ($line =~ /\S/) { + $line =~ s/\s*$//; # trim trailing spaces + print "$line\n"; + } + } + } + + # Close whichever file was open. + &html_jumppoints; + print "</body></html>\n"; + select STDOUT; + close TEXT; + + print "\n writing index file..."; + open TEXT,">nasmdoci.html"; + select TEXT; + &html_preamble(0); + print "<p align=center><a href=\"nasmdoc0.html\">Contents</a>\n"; + print "<p>"; + &html_index; + print "<p align=center><a href=\"nasmdoc0.html\">Contents</a>\n"; + print "</body></html>\n"; + select STDOUT; + close TEXT; +} + +sub html_preamble { + print "<html><head><title>NASM Manual</title></head>\n"; + print "<body><h1 align=center>The Netwide Assembler: NASM</h1>\n\n"; + &html_jumppoints if $_[0]; +} + +sub html_jumppoints { + print "<p align=center>"; + print "<a href=\"$html_nextf\">Next Chapter</a> |\n" if $html_nextf; + print "<a href=\"$html_lastf\">Previous Chapter</a> |\n" if $html_lastf; + print "<a href=\"nasmdoc0.html\">Contents</a> |\n"; + print "<a href=\"nasmdoci.html\">Index</a>\n"; +} + +sub html_index { + my $itag, $a, @ientry, $sep, $w, $wd, $wprev, $line; + + $chapternode = ''; + foreach $itag (@itags) { + $ientry = $idxmap{$itag}; + @a = @$ientry; + push @a, "n :"; + $sep = 0; + foreach $node (@nodes) { + next if !$idxnodes{$node,$itag}; + push @a, "n ," if $sep; + push @a, "sp", "x $xrefnodes{$node}", "n $node", "xe$xrefnodes{$node}"; + $sep = 1; + } + $line = ''; + do { + do { $w = &word_html(shift @a) } while $w eq "\001"; # nasty hack + $wd .= $wprev; + if ($w eq ' ' || $w eq '' || $w eq undef) { + if (length ($line . $wd) > 75) { + $line =~ s/\s*$//; # trim trailing spaces + print "$line\n"; + $line = ''; + $wd =~ s/^\s*//; # trim leading spaces + } + $line .= $wd; + $wd = ''; + } + $wprev = $w; + } while ($w ne '' && $w ne undef); + if ($line =~ /\S/) { + $line =~ s/\s*$//; # trim trailing spaces + print "$line\n"; + } + print "<br>\n"; + } +} + +sub word_html { + my ($w) = @_; + my $wtype, $wmajt, $pfx, $sfx; + + return undef if $w eq '' || $w eq undef; + + $wtype = substr($w,0,2); + $wmajt = substr($wtype,0,1); + $w = substr($w,2); + $pfx = $sfx = ''; + $pfx = "<a href=\"$1\">", $sfx = "</a>", $w = $2 + if $wmajt eq "w" && $w =~ /^<(.*)>(.*)$/; + $w =~ s/&/&/g; + $w =~ s/</</g; + $w =~ s/>/>/g; + if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") { + return $pfx . $w . $sfx; + } elsif ($wtype eq "sp") { + return ' '; + } elsif ($wtype eq "da") { + return '-'; # sadly, en-dashes are non-standard in HTML + } elsif ($wmajt eq "c" || $wtype eq "wc") { + return $pfx . "<code><nobr>${w}</nobr></code>" . $sfx; + } elsif ($wtype eq "es") { + return "<em>${w}"; + } elsif ($wtype eq "ee") { + return "${w}</em>"; + } elsif ($wtype eq "eo") { + return "<em>${w}</em>"; + } elsif ($wtype eq "x ") { + # Magic: we must resolve the cross reference into file and marker + # parts, then dispose of the file part if it's us, and dispose of + # the marker part if the cross reference describes the top node of + # another file. + my $node = $nodexrefs{$w}; # find the node we're aiming at + my $level = $tstruct_level{$node}; # and its level + my $up = $node, $uplev = $level-1; + $up = $tstruct_up{$up} while $uplev--; # get top node of containing file + my $file = ($up ne $chapternode) ? $html_fnames{$up} : ""; + my $marker = ($level == 1 and $file) ? "" : "#$w"; + return "<a href=\"$file$marker\">"; + } elsif ($wtype eq "xe") { + return "</a>"; + } elsif ($wmajt eq "i") { + return "\001"; + } else { + die "panic in word_html: $wtype$w\n"; + } +} + +sub write_texi { + # This is called from the top level, so I won't bother using + # my or local. + + # Open file. + print "writing file..."; + open TEXT,">nasmdoc.texi"; + select TEXT; + + # Preamble. + print "\\input texinfo \@c -*-texinfo-*-\n"; + print "\@c \%**start of header\n"; + print "\@setfilename ",$metadata{'infofile'},".info\n"; + print "\@dircategory ",$metadata{'category'},"\n"; + print "\@direntry\n"; + printf "* %-28s %s.\n", + sprintf('%s: (%s).', $metadata{'infoname'}, $metadata{'infofile'}), + $metadata{'infotitle'}; + print "\@end direntry\n"; + print "\@settitle ", $metadata{'title'},"\n"; + print "\@setchapternewpage odd\n"; + print "\@c \%**end of header\n"; + print "\n"; + print "\@ifinfo\n"; + print $metadata{'summary'}, "\n"; + print "\n"; + print "Copyright ",$metadata{'year'}," ",$metadata{'author'},"\n"; + print "\n"; + print $metadata{'license'}, "\n"; + print "\@end ifinfo\n"; + print "\n"; + print "\@titlepage\n"; + $title = $metadata{'title'}; + $title =~ s/ - / --- /g; + print "\@title ${title}\n"; + print "\@author ",$metadata{'author'},"\n"; + print "\n"; + print "\@page\n"; + print "\@vskip 0pt plus 1filll\n"; + print "Copyright \@copyright{} ",$metadata{'year'},' ',$metadata{'author'},"\n"; + print "\n"; + print $metadata{'license'}, "\n"; + print "\@end titlepage\n"; + print "\n"; + print "\@node Top, $tstruct_next{'Top'}, (dir), (dir)\n"; + print "\@top ",$metadata{'infotitle'},"\n"; + print "\n"; + print "\@ifinfo\n"; + print $metadata{'summary'}, "\n"; + print "\@end ifinfo\n"; + + $node = "Top"; + + $bulleting = 0; + for ($para = 0; $para <= $#pnames; $para++) { + $pname = $pnames[$para]; + $pflags = $pflags[$para]; + $ptype = substr($pflags,0,4); + + $bulleting = 0, print "\@end itemize\n" if $bulleting && $ptype ne "bull"; + print "\n"; # always one of these before a new paragraph + + if ($ptype eq "chap") { + # Chapter heading. Begin a new node. + &texi_menu($node) + if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node}; + $pflags =~ /chap (.*) :(.*)/; + $node = "Chapter $1"; + $title = "Chapter $1: "; + foreach $i (@$pname) { + $ww = &word_texi($i); + $title .= $ww unless $ww eq "\001"; + } + print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},"; + print " $tstruct_up{$node}\n\@unnumbered $title\n"; + } elsif ($ptype eq "appn") { + # Appendix heading. Begin a new node. + &texi_menu($node) + if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node}; + $pflags =~ /appn (.*) :(.*)/; + $node = "Appendix $1"; + $title = "Appendix $1: "; + foreach $i (@$pname) { + $ww = &word_texi($i); + $title .= $ww unless $ww eq "\001"; + } + print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},"; + print " $tstruct_up{$node}\n\@unnumbered $title\n"; + } elsif ($ptype eq "head" || $ptype eq "subh") { + # Heading or subheading. Begin a new node. + &texi_menu($node) + if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node}; + $pflags =~ /.... (.*) :(.*)/; + $node = "Section $1"; + $title = "$1. "; + foreach $i (@$pname) { + $ww = &word_texi($i); + $title .= $ww unless $ww eq "\001"; + } + print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},"; + print " $tstruct_up{$node}\n"; + $hdr = ($ptype eq "subh" ? "\@unnumberedsubsec" : "\@unnumberedsec"); + print "$hdr $title\n"; + } elsif ($ptype eq "code") { + # Code paragraph. Surround with @example / @end example. + print "\@example\n"; + foreach $i (@$pname) { + warn "code line longer than 68 chars: $i\n" if length $i > 68; + $i =~ s/\@/\@\@/g; + $i =~ s/\{/\@\{/g; + $i =~ s/\}/\@\}/g; + print "$i\n"; + } + print "\@end example\n"; + } elsif ($ptype eq "bull" || $ptype eq "norm") { + # Ordinary paragraph, optionally bulleted. We wrap, FWIW. + if ($ptype eq "bull") { + $bulleting = 1, print "\@itemize \@bullet\n" if !$bulleting; + print "\@item\n"; + } + $line = ''; + @a = @$pname; + $wd = $wprev = ''; + do { + do { $w = &word_texi(shift @a); } while $w eq "\001"; # hack + $wd .= $wprev; + if ($wprev =~ /-$/ || $w eq ' ' || $w eq '' || $w eq undef) { + if (length ($line . $wd) > 75) { + $line =~ s/\s*$//; # trim trailing spaces + print "$line\n"; + $line = ''; + $wd =~ s/^\s*//; # trim leading spaces + } + $line .= $wd; + $wd = ''; + } + $wprev = $w; + } while ($w ne '' && $w ne undef); + if ($line =~ /\S/) { + $line =~ s/\s*$//; # trim trailing spaces + print "$line\n"; + } + } + } + + # Write index. + &texi_index; + + # Close file. + print "\n\@contents\n\@bye\n"; + select STDOUT; + close TEXT; +} + +# Side effect of this procedure: update global `texiwdlen' to be the length +# in chars of the formatted version of the word. +sub word_texi { + my ($w) = @_; + my $wtype, $wmajt; + + return undef if $w eq '' || $w eq undef; + $wtype = substr($w,0,2); + $wmajt = substr($wtype,0,1); + $w = substr($w,2); + $wlen = length $w; + $w =~ s/\@/\@\@/g; + $w =~ s/\{/\@\{/g; + $w =~ s/\}/\@\}/g; + $w =~ s/<.*>// if $wmajt eq "w"; # remove web links + substr($w,0,1) =~ tr/a-z/A-Z/, $capital = 0 if $capital; + if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") { + $texiwdlen = $wlen; + return $w; + } elsif ($wtype eq "sp") { + $texiwdlen = 1; + return ' '; + } elsif ($wtype eq "da") { + $texiwdlen = 2; + return '--'; + } elsif ($wmajt eq "c" || $wtype eq "wc") { + $texiwdlen = 2 + $wlen; + return "\@code\{$w\}"; + } elsif ($wtype eq "es") { + $texiwdlen = 1 + $wlen; + return "\@emph\{${w}"; + } elsif ($wtype eq "ee") { + $texiwdlen = 1 + $wlen; + return "${w}\}"; + } elsif ($wtype eq "eo") { + $texiwdlen = 2 + $wlen; + return "\@emph\{${w}\}"; + } elsif ($wtype eq "x ") { + $texiwdlen = 0; # we don't need it in this case + $capital = 1; # hack + return "\@ref\{"; + } elsif ($wtype eq "xe") { + $texiwdlen = 0; # we don't need it in this case + return "\}"; + } elsif ($wmajt eq "i") { + $texiwdlen = 0; # we don't need it in this case + return "\001"; + } else { + die "panic in word_texi: $wtype$w\n"; + } +} + +sub texi_menu { + my ($topitem) = @_; + my $item, $i, $mpname, $title, $wd; + + $item = $tstruct_next{$topitem}; + print "\@menu\n"; + while ($item) { + $title = ""; + $mpname = $tstruct_pname{$item}; + foreach $i (@$mpname) { + $wd = &word_texi($i); + $title .= $wd unless $wd eq "\001"; + } + print "* ${item}:: $title\n"; + $item = $tstruct_mnext{$item}; + } + print "* Index::\n" if $topitem eq "Top"; + print "\@end menu\n"; +} + +sub texi_index { + my $itag, $ientry, @a, $wd, $item, $len; + my $subnums = "123456789ABCDEFGHIJKLMNOPQRSTU" . + "VWXYZabcdefghijklmnopqrstuvwxyz"; + + print "\@ifinfo\n\@node Index, , $FIXMElastnode, Top\n"; + print "\@unnumbered Index\n\n\@menu\n"; + + foreach $itag (@itags) { + $ientry = $idxmap{$itag}; + @a = @$ientry; + $item = ''; + $len = 0; + foreach $i (@a) { + $wd = &word_texi($i); + $item .= $wd, $len += $texiwdlen unless $wd eq "\001"; + } + $i = 0; + foreach $node (@nodes) { + next if !$idxnodes{$node,$itag}; + printf "* %s%s (%s): %s.\n", + $item, " " x (40-$len), substr($subnums,$i++,1), $node; + } + } + print "\@end menu\n\@end ifinfo\n"; +} + +sub write_hlp { + # This is called from the top level, so I won't bother using + # my or local. + + # Build the index-tag text forms. + print "building index entries..."; + @hlp_index = map { + my $i,$ww; + my $ientry = $idxmap{$_}; + my $title = ""; + foreach $i (@$ientry) { + $ww = &word_hlp($i,0); + $title .= $ww unless $ww eq "\001"; + } + $title; + } @itags; + + # Write the HPJ project-description file. + print "writing .hpj file..."; + open HPJ,">nasmdoc.hpj"; + print HPJ "[OPTIONS]\ncompress=true\n"; + print HPJ "title=NASM: The Netwide Assembler\noldkeyphrase=no\n\n"; + print HPJ "[FILES]\nnasmdoc.rtf\n\n"; + print HPJ "[CONFIG]\n"; + print HPJ 'CreateButton("btn_up", "&Up",'. + ' "JumpContents(`nasmdoc.hlp'."'".')")'; + print HPJ "\nBrowseButtons()\n"; + close HPJ; + + # Open file. + print "\n writing .rtf file..."; + open TEXT,">nasmdoc.rtf"; + select TEXT; + + # Preamble. + print "{\\rtf1\\ansi{\\fonttbl\n"; + print "\\f0\\froman Times New Roman;\\f1\\fmodern Courier New;\n"; + print "\\f2\\fswiss Arial;\\f3\\ftech Wingdings}\\deff0\n"; + print "#{\\footnote Top}\n"; + print "\${\\footnote Contents}\n"; + print "+{\\footnote browse:00000}\n"; + print "!{\\footnote DisableButton(\"btn_up\")}\n"; + print "\\keepn\\f2\\b\\fs30\\sb0\n"; + print "NASM: The Netwide Assembler\n"; + print "\\par\\pard\\plain\\sb120\n"; + print "This file documents NASM, the Netwide Assembler: an assembler \n"; + print "targetting the Intel x86 series of processors, with portable source.\n"; + + $node = "Top"; + $browse = 0; + + $newpar = "\\par\\sb120\n"; + for ($para = 0; $para <= $#pnames; $para++) { + $pname = $pnames[$para]; + $pflags = $pflags[$para]; + $ptype = substr($pflags,0,4); + + print $newpar; + $newpar = "\\par\\sb120\n"; + + if ($ptype eq "chap") { + # Chapter heading. Begin a new node. + &hlp_menu($node) + if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node}; + $pflags =~ /chap (.*) :(.*)/; + $node = "Chapter $1"; + $title = $footnotetitle = "Chapter $1: "; + foreach $i (@$pname) { + $ww = &word_hlp($i,1); + $title .= $ww, $footnotetitle .= &word_hlp($i,0) unless $ww eq "\001"; + } + print "\\page\n"; + printf "#{\\footnote %s}\n", &hlp_sectkw($node); + print "\${\\footnote $footnotetitle}\n"; + printf "+{\\footnote browse:%05d}\n", ++$browse; + printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," . + "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n", + &hlp_sectkw($tstruct_up{$node}); + print "EnableButton(\"btn_up\")}\n"; + &hlp_keywords($node); + print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n"; + print "$title\n"; + $newpar = "\\par\\pard\\plain\\sb120\n"; + } elsif ($ptype eq "appn") { + # Appendix heading. Begin a new node. + &hlp_menu($node) + if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node}; + $pflags =~ /appn (.*) :(.*)/; + $node = "Appendix $1"; + $title = $footnotetitle = "Appendix $1: "; + foreach $i (@$pname) { + $ww = &word_hlp($i,1); + $title .= $ww, $footnotetitle .= &word_hlp($i,0) unless $ww eq "\001"; + } + print "\\page\n"; + printf "#{\\footnote %s}\n", &hlp_sectkw($node); + print "\${\\footnote $footnotetitle}\n"; + printf "+{\\footnote browse:%05d}\n", ++$browse; + printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," . + "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n", + &hlp_sectkw($tstruct_up{$node}); + print "EnableButton(\"btn_up\")}\n"; + &hlp_keywords($node); + print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n"; + print "$title\n"; + $newpar = "\\par\\pard\\plain\\sb120\n"; + } elsif ($ptype eq "head" || $ptype eq "subh") { + # Heading or subheading. Begin a new node. + &hlp_menu($node) + if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node}; + $pflags =~ /.... (.*) :(.*)/; + $node = "Section $1"; + $title = $footnotetitle = "$1. "; + foreach $i (@$pname) { + $ww = &word_hlp($i,1); + $title .= $ww, $footnotetitle .= &word_hlp($i,0) unless $ww eq "\001"; + } + print "\\page\n"; + printf "#{\\footnote %s}\n", &hlp_sectkw($node); + print "\${\\footnote $footnotetitle}\n"; + printf "+{\\footnote browse:%05d}\n", ++$browse; + printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," . + "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n", + &hlp_sectkw($tstruct_up{$node}); + print "EnableButton(\"btn_up\")}\n"; + &hlp_keywords($node); + print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n"; + print "$title\n"; + $newpar = "\\par\\pard\\plain\\sb120\n"; + } elsif ($ptype eq "code") { + # Code paragraph. + print "\\keep\\f1\\sb120\n"; + foreach $i (@$pname) { + my $x = $i; + warn "code line longer than 68 chars: $i\n" if length $i > 68; + $x =~ s/\\/\\\\/g; + $x =~ s/\{/\\\{/g; + $x =~ s/\}/\\\}/g; + print "$x\\par\\sb0\n"; + } + $newpar = "\\pard\\f0\\sb120\n"; + } elsif ($ptype eq "bull" || $ptype eq "norm") { + # Ordinary paragraph, optionally bulleted. We wrap, FWIW. + if ($ptype eq "bull") { + print "\\tx360\\li360\\fi-360{\\f3\\'9F}\\tab\n"; + $newpar = "\\par\\pard\\sb120\n"; + } else { + $newpar = "\\par\\sb120\n"; + } + $line = ''; + @a = @$pname; + $wd = $wprev = ''; + do { + do { $w = &word_hlp((shift @a),1); } while $w eq "\001"; # hack + $wd .= $wprev; + if ($w eq ' ' || $w eq '' || $w eq undef) { + if (length ($line . $wd) > 75) { + $line =~ s/\s*$//; # trim trailing spaces + print "$line \n"; # and put one back + $line = ''; + $wd =~ s/^\s*//; # trim leading spaces + } + $line .= $wd; + $wd = ''; + } + $wprev = $w; + } while ($w ne '' && $w ne undef); + if ($line =~ /\S/) { + $line =~ s/\s*$//; # trim trailing spaces + print "$line\n"; + } + } + } + + # Close file. + print "\\page}\n"; + select STDOUT; + close TEXT; +} + +sub word_hlp { + my ($w, $docode) = @_; + my $wtype, $wmajt; + + return undef if $w eq '' || $w eq undef; + $wtype = substr($w,0,2); + $wmajt = substr($wtype,0,1); + $w = substr($w,2); + $w =~ s/\\/\\\\/g; + $w =~ s/\{/\\\{/g; + $w =~ s/\}/\\\}/g; + $w =~ s/<.*>// if $wmajt eq "w"; # remove web links + substr($w,0,length($w)-1) =~ s/-/\\\'AD/g if $wmajt ne "x"; #nonbreakhyphens + if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") { + return $w; + } elsif ($wtype eq "sp") { + return ' '; + } elsif ($wtype eq "da") { + return "\\'96"; + } elsif ($wmajt eq "c" || $wtype eq "wc") { + $w =~ s/ /\\\'A0/g; # make spaces non-breaking + return $docode ? "{\\f1 ${w}}" : $w; + } elsif ($wtype eq "es") { + return "{\\i ${w}"; + } elsif ($wtype eq "ee") { + return "${w}}"; + } elsif ($wtype eq "eo") { + return "{\\i ${w}}"; + } elsif ($wtype eq "x ") { + return "{\\uldb "; + } elsif ($wtype eq "xe") { + $w = &hlp_sectkw($w); + return "}{\\v ${w}}"; + } elsif ($wmajt eq "i") { + return "\001"; + } else { + die "panic in word_hlp: $wtype$w\n"; + } +} + +sub hlp_menu { + my ($topitem) = @_; + my $item, $kword, $i, $mpname, $title; + + $item = $tstruct_next{$topitem}; + print "\\li360\\fi-360\n"; + while ($item) { + $title = ""; + $mpname = $tstruct_pname{$item}; + foreach $i (@$mpname) { + $ww = &word_hlp($i, 0); + $title .= $ww unless $ww eq "\001"; + } + $kword = &hlp_sectkw($item); + print "{\\uldb ${item}: $title}{\\v $kword}\\par\\sb0\n"; + $item = $tstruct_mnext{$item}; + } + print "\\pard\\sb120\n"; +} + +sub hlp_sectkw { + my ($node) = @_; + $node =~ tr/A-Z/a-z/; + $node =~ tr/- ./___/; + $node; +} + +sub hlp_keywords { + my ($node) = @_; + my $pfx = "K{\\footnote "; + my $done = 0; + foreach $i (0..$#itags) { + (print $pfx,$hlp_index[$i]), $pfx = ";\n", $done++ + if $idxnodes{$node,$itags[$i]}; + } + print "}\n" if $done; +} + +# Make tree structures. $tstruct_* is top-level and global. +sub add_item { + my ($item, $level) = @_; + my $i; + + $tstruct_pname{$item} = $pname; + $tstruct_next{$tstruct_previtem} = $item; + $tstruct_prev{$item} = $tstruct_previtem; + $tstruct_level{$item} = $level; + $tstruct_up{$item} = $tstruct_last[$level-1]; + $tstruct_mnext{$tstruct_last[$level]} = $item; + $tstruct_last[$level] = $item; + for ($i=$level+1; $i<$MAXLEVEL; $i++) { $tstruct_last[$i] = undef; } + $tstruct_previtem = $item; + push @nodes, $item; +} + +# +# This produces documentation intermediate paragraph format; this is +# basically the digested output of the front end. Intended for use +# by future backends, instead of putting it all in the same script. +# +sub write_dip { + open(PARAS, "> nasmdoc.dip"); + foreach $k (keys(%metadata)) { + print PARAS 'meta :', $k, "\n"; + print PARAS $metadata{$k},"\n"; + } + for ($para = 0; $para <= $#pnames; $para++) { + print PARAS $pflags[$para], "\n"; + print PARAS join("\037", @{$pnames[$para]}, "\n"); + } + foreach $k (@itags) { + print PARAS 'indx :', $k, "\n"; + print PARAS join("\037", @{$idxmap{$k}}), "\n"; + } + close(PARAS); +} |