| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112 |
- #!/usr/bin/perl
- ## --------------------------------------------------------------------------
- ##
- ## Copyright 1996-2018 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.
- #
- # Indent \>
- # Indents the paragraph equvalently to a bulleted paragraph. In HTML,
- # an indented paragraph following a bulleted paragraph is included in the
- # same list item.
- #
- # Blockquote \q
- # Marks the paragraph as a block quote.
- #
- # 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 File::Spec;
- @include_path = ();
- $out_path = File::Spec->curdir();
- while ($ARGV[0] =~ /^-/) {
- my $opt = shift @ARGV;
- if ($opt eq '-d') {
- $diag = 1;
- } elsif ($opt =~ /^\-[Ii](.*)$/) {
- push(@include_path, $1);
- } elsif ($opt =~ /^\-[Oo](.*)$/) {
- $out_path = $1;
- }
- }
- $out_format = shift(@ARGV);
- @files = @ARGV;
- @files = ('-') unless(scalar(@files));
- $| = 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;
- foreach $file (@files) {
- &include($file);
- }
- &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";
- # Make output directory if necessary
- mkdir($out_path);
- 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 '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 read_line {
- local $_ = shift;
- $_ = &untabify($_);
- 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/(^|[^\\])\\#.*$/\1/; # strip comments
- $para .= " " . $_;
- }
- }
- sub include {
- my $name = shift;
- my $F;
- if ($name eq '-') {
- open($F, '<-'); # stdin
- } else {
- my $found = 0;
- foreach my $idir ( File::Spec->curdir, @include_path ) {
- my $fpath = File::Spec->catfile($idir, $name);
- if (open($F, '<', $fpath)) {
- $found = 1;
- last;
- }
- }
- die "Cannot open $name: $!\n" unless ($found);
- }
- while (defined($_ = <$F>)) {
- &read_line($_);
- }
- close($F);
- }
- 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\>q])/) {
- # An indented paragraph of some sort. Strip off the initial \b and let the
- # word-by-word code take care of the rest.
- my %ipar = (
- 'b' => 'bull',
- '>' => 'indt',
- 'q' => 'bquo',
- );
- $pflags = $ipar{$1};
- s/^\\[b\>q]\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 an en dash
- # "dm" for an em desh
- # "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: \\k$_\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, 'dm';
- } elsif ($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, '>', File::Spec->catfile($out_path, '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, '>', File::Spec->catfile($out_path, 'nasmdoc.txt');
- select TEXT;
- # Preamble.
- $title = $metadata{'title'};
- $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 =~ /^(norm|bull|indt|bquo)$/) {
- # Ordinary paragraph, optionally indented. We wrap, with ragged
- # 75-char right margin and either 7 or 11 char left margin
- # depending on bullets.
- if ($ptype ne 'norm') {
- $line = ' 'x7 . (($ptype eq 'bull') ? '(*) ' : ' ');
- $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' || $wtype eq 'dm') {
- 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, '>', File::Spec->catfile($out_path, '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</p>";
- print "<div class=\"toc\">\n";
- $level = 0;
- for ($node = $tstruct_next{'Top'}; $node; $node = $tstruct_next{$node}) {
- my $lastlevel = $level;
- while ($tstruct_level{$node} < $level) {
- print "</li>\n</ol>\n";
- $level--;
- }
- while ($tstruct_level{$node} > $level) {
- print "<ol class=\"toc", ++$level, "\">\n";
- }
- if ($lastlevel >= $level) {
- print "</li>\n";
- }
- $level = $tstruct_level{$node};
- if ($level == 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;
- } else {
- # Use the preceding filename plus a marker point.
- $link = $fname . "#$xrefnodes{$node}";
- }
- $title = '';
- $pname = $tstruct_pname{$node};
- foreach $i (@$pname) {
- $ww = &word_html($i);
- $title .= $ww unless $ww eq "\001";
- }
- print "<li class=\"toc${level}\">\n";
- print "<span class=\"node\">$node: </span><a href=\"$link\">$title</a>\n";
- }
- while ($level--) {
- print "</li>\n</ol>\n";
- }
- print "</div>\n";
- print "</body>\n";
- print "</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, '>', File::Spec->devnull();
- select TEXT;
- undef $html_nav_last;
- undef $html_nav_next;
- $in_list = 0;
- $in_bquo = 0;
- $in_code = 0;
- for ($para = 0; $para <= $#pnames; $para++) {
- $pname = $pnames[$para];
- $pflags = $pflags[$para];
- $ptype = substr($pflags,0,4);
- $in_code = 0, print "</pre>\n" if ($in_code && $ptype ne 'code');
- $in_list = 0, print "</li>\n</ul>\n" if ($in_list && $ptype !~ /^(bull|indt|code)$/);
- $in_bquo = 0, print "</blockquote>\n" if ($in_bquo && $ptype ne 'bquo');
- $endtag = '';
- if ($ptype eq "chap") {
- # Chapter heading. Begin a new file.
- $pflags =~ /chap (.*) :(.*)/;
- $title = "Chapter $1: ";
- $xref = $2;
- &html_postamble; select STDOUT; close TEXT;
- $html_nav_last = $chapternode;
- $chapternode = $nodexrefs{$xref};
- $html_nav_next = $tstruct_mnext{$chapternode};
- open(TEXT, '>', File::Spec->catfile($out_path, $html_fnames{$chapternode}));
- select TEXT;
- &html_preamble(1);
- foreach $i (@$pname) {
- $ww = &word_html($i);
- $title .= $ww unless $ww eq "\001";
- }
- $h = "<h2 id=\"$xref\">$title</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_postamble; select STDOUT; close TEXT;
- $html_nav_last = $chapternode;
- $chapternode = $nodexrefs{$xref};
- $html_nav_next = $tstruct_mnext{$chapternode};
- open(TEXT, '>', File::Spec->catfile($out_path, $html_fnames{$chapternode}));
- select TEXT;
- &html_preamble(1);
- foreach $i (@$pname) {
- $ww = &word_html($i);
- $title .= $ww unless $ww eq "\001";
- }
- print "<h2 id=\"$xref\">$title</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 id=\"$xref\">$title</$hdr>\n";
- } elsif ($ptype eq "code") {
- # Code paragraph.
- $in_code = 1, print "<pre>" unless $in_code;
- print "\n";
- foreach $i (@$pname) {
- $w = $i;
- $w =~ s/&/&/g;
- $w =~ s/</</g;
- $w =~ s/>/>/g;
- print $w, "\n";
- }
- } elsif ($ptype =~ /^(norm|bull|indt|bquo)$/) {
- # Ordinary paragraph, optionally indented.
- if ($ptype eq 'bull') {
- if (!$in_list) {
- $in_list = 1;
- print "<ul>\n";
- } else {
- print "</li>\n";
- }
- print "<li>\n";
- $line = '<p>';
- $endtag = '</p>';
- } elsif ($ptype eq 'indt') {
- if (!$in_list) {
- $in_list = 1;
- print "<ul>\n";
- print "<li class=\"indt\">\n"; # This is such a hack
- }
- $line = '<p>';
- $endtag = '</p>';
- } elsif ($ptype eq 'bquo') {
- $in_bquo = 1, print "<blockquote>\n" unless $in_bquo;
- $line = '<p>';
- $endtag = '</p>';
- } else {
- $line = '<p>';
- $endtag = '</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;
- }
- print $endtag, "\n";
- }
- }
- # Close whichever file was open.
- print "</pre>\n" if ($in_code);
- print "</li>\n</ul>\n" if ($in_list);
- print "</blockquote>\n" if ($in_bquo);
- &html_postamble; select STDOUT; close TEXT;
- print "\n writing index file...";
- open TEXT, '>', File::Spec->catfile($out_path, 'nasmdoci.html');
- select TEXT;
- &html_preamble(0);
- print "<h2 class=\"index\">Index</h2>\n";
- print "<ul class=\"index\">\n";
- &html_index;
- print "</ul>\n</body>\n</html>\n";
- select STDOUT;
- close TEXT;
- }
- sub html_preamble {
- print "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n";
- print "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" ";
- print "\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n";
- print "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n";
- print "<head>\n";
- print "<title>", $metadata{'title'}, "</title>\n";
- print "<link href=\"nasmdoc.css\" rel=\"stylesheet\" type=\"text/css\" />\n";
- print "<link href=\"local.css\" rel=\"stylesheet\" type=\"text/css\" />\n";
- print "</head>\n";
- print "<body>\n";
- # Navigation bar
- print "<ul class=\"navbar\">\n";
- if (defined($html_nav_last)) {
- my $lastf = $html_fnames{$html_nav_last};
- print "<li class=\"first\"><a class=\"prev\" href=\"$lastf\">$html_nav_last</a></li>\n";
- }
- if (defined($html_nav_next)) {
- my $nextf = $html_fnames{$html_nav_next};
- print "<li><a class=\"next\" href=\"$nextf\">$html_nav_next</a></li>\n";
- }
- print "<li><a class=\"toc\" href=\"nasmdoc0.html\">Contents</a></li>\n";
- print "<li class=\"last\"><a class=\"index\" href=\"nasmdoci.html\">Index</a></li>\n";
- print "</ul>\n";
- print "<div class=\"title\">\n";
- print "<h1>", $metadata{'title'}, "</h1>\n";
- print '<span class="subtitle">', $metadata{'subtitle'}, "</span>\n";
- print "</div>\n";
- print "<div class=\"contents\"\n>\n";
- }
- sub html_postamble {
- # Common closing tags
- print "</div>\n</body>\n</html>\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;
- }
- print "<li class=\"index\">\n";
- $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 "</li>\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 '–';
- } elsif ($wtype eq "dm") {
- return '—';
- } elsif ($wmajt eq "c" || $wtype eq "wc") {
- return $pfx . "<code>${w}</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";
- }
- }
- # 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, '>', File::Spec->catfile($out_path, 'nasmdoc.dip'));
- foreach $k (sort(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);
- }
|