3 # Read the source-form of the NASM manual and generate the various
8 # Ellipsis support would be nice.
10 # Source-form features:
11 # ---------------------
14 # Bullets the paragraph. Rest of paragraph is indented to cope. In
15 # HTML, consecutive groups of bulleted paragraphs become unordered
19 # produces `_foobar_' in text and italics in HTML, PS, RTF
21 # Inline code \c{foobar}
22 # produces ``foobar'' in text, and fixed-pitch font in HTML, PS, RTF
27 # produces fixed-pitch font where appropriate, and doesn't break
28 # pages except sufficiently far into the middle of a display.
30 # Chapter, header and subheader
31 # \C{intro} Introduction
32 # \H{whatsnasm} What is NASM?
33 # \S{free} NASM Is Free
34 # dealt with as appropriate. Chapters begin on new sides, possibly
35 # even new _pages_. (Sub)?headers are good places to begin new
36 # pages. Just _after_ a (sub)?header isn't.
37 # The keywords can be substituted with \K and \k.
39 # Keyword \K{cintro} \k{cintro}
40 # Expands to `Chapter 1', `Section 1.1', `Section 1.1.1'. \K has an
41 # initial capital whereas \k doesn't. In HTML, will produce
44 # Web link \W{http://foobar/}{text} or \W{mailto:me@here}\c{me@here}
45 # the \W prefix is ignored except in HTML; in HTML the last part
46 # becomes a hyperlink to the first part.
49 # In case it's necessary, they expand to the real versions.
51 # Nonbreaking hyphen \-
55 # Causes everything after it on the line to be ignored by the
56 # source-form processor.
58 # Indexable word \i{foobar} (or \i\e{foobar} or \i\c{foobar}, equally)
59 # makes word appear in index, referenced to that point
60 # \i\c comes up in code style even in the index; \i\e doesn't come
61 # up in emphasised style.
63 # Indexable non-displayed word \I{foobar} or \I\c{foobar}
64 # just as \i{foobar} except that nothing is displayed for it
67 # \IR{foobar} \c{foobar} operator, uses of
68 # tidies up the appearance in the index of something the \i or \I
69 # operator was applied to
72 # \IA{foobar}{bazquux}
73 # aliases one index tag (as might be supplied to \i or \I) to
74 # another, so that \I{foobar} has the effect of \I{bazquux}, and
75 # \i{foobar} has the effect of \I{bazquux}foobar
77 $diag = 1, shift @ARGV if $ARGV[0] eq "-d";
81 $tstruct_previtem = $node = "Top";
83 $tstruct_level{$tstruct_previtem} = 0;
84 $tstruct_last[$tstruct_level{$tstruct_previtem}] = $tstruct_previtem;
85 $MAXLEVEL = 10; # really 3, but play safe ;-)
87 # Read the file; pass a paragraph at a time to the paragraph processor.
88 print "Reading input...";
89 $pname = "para000000";
90 @pnames = @pflags = ();
94 if (!/\S/ || /^\\I[AR]/) { # special case: \I[AR] implies new-paragraph
99 s/\\#.*$//; # strip comments
106 # Now we've read in the entire document and we know what all the
107 # heading keywords refer to. Go through and fix up the \k references.
108 print "Fixing up cross-references...";
112 # Sort the index tags, according to the slightly odd order I've decided on.
113 print "Sorting index tags...";
118 print "Writing index-diagnostic file...";
123 # OK. Write out the various output files.
124 print "Producing text output: ";
127 print "Producing HTML output: ";
130 print "Producing PostScript output: ";
133 print "Producing Texinfo output: ";
136 print "Producing WinHelp output: ";
142 my $pflags = "", $i, $w, $l, $t;
147 # Strip off _leading_ spaces, then determine type of paragraph.
151 # A code paragraph. The paragraph-array will contain the simple
152 # strings which form each line of the paragraph.
154 while (/^\\c (([^\\]|\\[^c])*)(.*)$/) {
162 $_ = ''; # suppress word-by-word code
164 # A chapter heading. Define the keyword and allocate a chapter
169 $xref = "chapter-$cnum";
170 $pflags = "chap $cnum :$xref";
171 die "badly formatted chapter heading: $_\n" if !/^\\C{([^}]*)}\s*(.*)$/;
172 $refs{$1} = "chapter $cnum";
173 $node = "Chapter $cnum";
175 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
178 # the standard word-by-word code will happen next
180 # An appendix heading. Define the keyword and allocate an appendix
183 $cnum = 'A' if $cnum =~ /[0-9]+/;
186 $xref = "appendix-$cnum";
187 $pflags = "appn $cnum :$xref";
188 die "badly formatted appendix heading: $_\n" if !/^\\A{([^}]*)}\s*(.*)$/;
189 $refs{$1} = "appendix $cnum";
190 $node = "Appendix $cnum";
192 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
195 # the standard word-by-word code will happen next
197 # A major heading. Define the keyword and allocate a section number.
200 $xref = "section-$cnum.$hnum";
201 $pflags = "head $cnum.$hnum :$xref";
202 die "badly formatted heading: $_\n" if !/^\\[HP]{([^}]*)}\s*(.*)$/;
203 $refs{$1} = "section $cnum.$hnum";
204 $node = "Section $cnum.$hnum";
206 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
209 # the standard word-by-word code will happen next
211 # A sub-heading. Define the keyword and allocate a section number.
213 $xref = "section-$cnum.$hnum.$snum";
214 $pflags = "subh $cnum.$hnum.$snum :$xref";
215 die "badly formatted subheading: $_\n" if !/^\\S{([^}]*)}\s*(.*)$/;
216 $refs{$1} = "section $cnum.$hnum.$snum";
217 $node = "Section $cnum.$hnum.$snum";
219 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
222 # the standard word-by-word code will happen next
225 die "badly formatted index rewrite: $_\n" if !/^\\IR{([^}]*)}\s*(.*)$/;
228 # the standard word-by-word code will happen next
231 die "badly formatted index alias: $_\n" if !/^\\IA{([^}]*)}{([^}]*)}\s*$/;
233 return; # avoid word-by-word code
235 # A bulleted paragraph. Strip off the initial \b and let the
236 # word-by-word code take care of the rest.
240 # A normal paragraph. Just set $pflags: the word-by-word code does
245 # The word-by-word code: unless @$pname is already defined (which it
246 # will be in the case of a code paragraph), split the paragraph up
247 # into words and push each on @$pname.
249 # Each thing pushed on @$pname should have a two-character type
250 # code followed by the text.
255 # "es" for first emphasised word in emphasised bit
256 # "e " for emphasised in mid-emphasised-bit
257 # "ee" for last emphasised word in emphasised bit
258 # "eo" for single (only) emphasised word
261 # "kK" for capitalised cross-ref
263 # "wc" for code-type Web link
264 # "x " for beginning of resolved cross-ref; generates no visible output,
265 # and the text is the cross-reference code
266 # "xe" for end of resolved cross-ref; text is same as for "x ".
267 # "i " for point to be indexed: the text is the internal index into the
271 s/^\s*//, push @
$pname, "sp" if /^\s/;
272 $indexing = $qindex = 0;
273 if (/^(\\[iI])?\\c/) {
274 $qindex = 1 if $1 eq "\\I";
275 $indexing = 1, s/^\\[iI]// if $1;
277 die "badly formatted \\c: \\c$_\n" if !/{(([^\\}]|\\.)*)}(.*)$/;
284 (push @
$pname,"i"),$lastp = $#$pname if $indexing;
285 push @
$pname,"c $w" if !$qindex;
286 $$pname[$lastp] = &addidx
($node, $w, "c $w") if $indexing;
287 } elsif (/^\\[iIe]/) {
290 $qindex = 1 if $1 eq "\\I";
291 $indexing = 1, $type = "\\i" if $1;
292 $emph = 1, $type = "\\e" if $2;
293 s/^(\\[iI])?(\\e?)//;
294 die "badly formatted $type: $type$_\n" if !/{(([^\\}]|\\.)*)}(.*)$/;
301 $t = $emph ?
"es" : "n ";
303 (push @
$pname,"i"),$lastp = $#$pname if $indexing;
304 foreach $i (split /\s+/,$w) { # \e and \i can be multiple words
305 push @
$pname,"$t$i","sp" if !$qindex;
306 ($ii=$i) =~ tr/A-Z/a-z/, push @ientry,"n $ii","sp" if $indexing;
307 $t = $emph ?
"e " : "n ";
309 $w =~ tr/A-Z/a-z/, pop @ientry if $indexing;
310 $$pname[$lastp] = &addidx
($node, $w, @ientry) if $indexing;
311 pop @
$pname if !$qindex; # remove final space
312 if (substr($$pname[$#$pname],0,2) eq "es" && !$qindex) {
313 substr($$pname[$#$pname],0,2) = "eo";
314 } elsif ($emph && !$qindex) {
315 substr($$pname[$#$pname],0,2) = "ee";
317 } elsif (/^\\[kK]/) {
321 die "badly formatted \\k: \\c$_\n" if !/{([^}]*)}(.*)$/;
326 die "badly formatted \\W: \\W$_\n"
327 if !/{([^}]*)}(\\i)?(\\c)?{(([^\\}]|\\.)*)}(.*)$/;
332 $t = "wc" if $3 eq "\\c";
338 (push @
$pname,"i"),$lastp = $#$pname if $indexing;
339 push @
$pname,"$t<$l>$w";
340 $$pname[$lastp] = &addidx
($node, $w, "c $w") if $indexing;
342 die "what the hell? $_\n" if !/^(([^\s\\\-]|\\[\\{}\-])*-?)(.*)$/;
343 die "painful death! $_\n" if !length $1;
357 if ($irewrite ne undef) {
358 &addidx
(undef, $irewrite, @
$pname);
361 push @pnames, $pname;
362 push @pflags, $pflags;
368 my ($node, $text, @ientry) = @_;
369 $text = $idxalias{$text} || $text;
370 if ($node eq undef || !$idxmap{$text}) {
372 $idxmap{$text} = $ientry;
376 $idxnodes{$node,$text} = 1;
382 my $iitem, $ientry, $i, $piitem, $pcval, $cval, $clrcval;
384 @itags = map { # get back the original data as the 1st elt of each list
386 } sort { # compare auxiliary (non-first) elements of lists
387 $a->[1] cmp $b->[1] ||
388 $a->[2] cmp $b->[2] ||
390 } map { # transform array into list of 3-element lists
391 my $ientry = $idxmap{$_};
392 my $a = substr($$ientry[0],2);
394 [$_, uc($a), substr($$ientry[0],0,2)]
397 # Having done that, check for comma-hood.
399 foreach $iitem (@itags) {
400 $ientry = $idxmap{$iitem};
403 FL
:for ($i=0; $i <= $#$ientry; $i++) {
404 if ($$ientry[$i] =~ /^(n .*,)(.*)/) {
406 splice @
$ientry,$i+1,0,"n $2" if length $2;
407 $commapos{$iitem} = $i+1;
408 $cval = join("\002", @
$ientry[0..$i]);
413 $cval = undef if $clrcval;
414 $commanext{$iitem} = $commaafter{$piitem} = 1
415 if $cval and ($cval eq $pcval);
421 my $iitem,$ientry,$w,$ww,$foo,$node;
422 open INDEXDIAG
,">index.diag";
423 foreach $iitem (@itags) {
424 $ientry = $idxmap{$iitem};
425 print INDEXDIAG
"<$iitem> ";
426 foreach $w (@
$ientry) {
428 print INDEXDIAG
$ww unless $ww eq "\001";
432 foreach $node (@nodes) {
433 (print INDEXDIAG
$foo,$node), $foo = ", " if $idxnodes{$node,$iitem};
435 print INDEXDIAG
"\n";
441 my $pname, $p, $i, $j, $k, $caps, @repl;
443 for ($p=0; $p<=$#pnames; $p++) {
444 next if $pflags[$p] eq "code";
445 $pname = $pnames[$p];
446 for ($i=$#$pname; $i >= 0; $i--) {
447 if ($$pname[$i] =~ /^k/) {
449 $caps = ($k =~ /^kK/);
452 die "undefined keyword `$k'\n" unless $repl;
453 substr($repl,0,1) =~ tr/a-z/A-Z/ if $caps;
455 push @repl,"x $xrefs{$k}";
456 foreach $j (split /\s+/,$repl) {
460 pop @repl; # remove final space
461 push @repl,"xe$xrefs{$k}";
462 splice @
$pname,$i,1,@repl;
469 # This is called from the top level, so I won't bother using
473 print "writing file...";
474 open TEXT
,">nasmdoc.txt";
478 $title = "The Netwide Assembler: NASM";
479 $spaces = ' ' x
((75-(length $title))/2);
480 ($underscore = $title) =~ s/./=/g;
481 print "$spaces$title\n$spaces$underscore\n";
483 for ($para = 0; $para <= $#pnames; $para++) {
484 $pname = $pnames[$para];
485 $pflags = $pflags[$para];
486 $ptype = substr($pflags,0,4);
488 print "\n"; # always one of these before a new paragraph
490 if ($ptype eq "chap") {
491 # Chapter heading. "Chapter N: Title" followed by a line of
493 $pflags =~ /chap (.*) :(.*)/;
494 $title = "Chapter $1: ";
495 foreach $i (@
$pname) {
497 $title .= $ww unless $ww eq "\001";
502 } elsif ($ptype eq "appn") {
503 # Appendix heading. "Appendix N: Title" followed by a line of
505 $pflags =~ /appn (.*) :(.*)/;
506 $title = "Appendix $1: ";
507 foreach $i (@
$pname) {
509 $title .= $ww unless $ww eq "\001";
514 } elsif ($ptype eq "head" || $ptype eq "subh") {
515 # Heading or subheading. Just a number and some text.
516 $pflags =~ /.... (.*) :(.*)/;
517 $title = sprintf "%6s ", $1;
518 foreach $i (@
$pname) {
520 $title .= $ww unless $ww eq "\001";
523 } elsif ($ptype eq "code") {
524 # Code paragraph. Emit each line with a seven character indent.
525 foreach $i (@
$pname) {
526 warn "code line longer than 68 chars: $i\n" if length $i > 68;
527 print ' 'x7
, $i, "\n";
529 } elsif ($ptype eq "bull" || $ptype eq "norm") {
530 # Ordinary paragraph, optionally bulleted. We wrap, with ragged
531 # 75-char right margin and either 7 or 11 char left margin
532 # depending on bullets.
533 if ($ptype eq "bull") {
534 $line = ' 'x7
. '(*) ';
537 $line = $next = ' 'x7
;
542 do { $w = &word_txt
(shift @a) } while $w eq "\001"; # nasty hack
544 if ($wprev =~ /-$/ || $w eq ' ' || $w eq '' || $w eq undef) {
545 if (length ($line . $wd) > 75) {
546 $line =~ s/\s*$//; # trim trailing spaces
549 $wd =~ s/^\s*//; # trim leading spaces
555 } while ($w ne '' && $w ne undef);
557 $line =~ s/\s*$//; # trim trailing spaces
572 return undef if $w eq '' || $w eq undef;
573 $wtype = substr($w,0,2);
574 $wmajt = substr($wtype,0,1);
576 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
577 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
579 } elsif ($wtype eq "sp") {
581 } elsif ($wtype eq "da") {
583 } elsif ($wmajt eq "c" || $wtype eq "wc") {
585 } elsif ($wtype eq "es") {
587 } elsif ($wtype eq "ee") {
589 } elsif ($wtype eq "eo") {
591 } elsif ($wmajt eq "x" || $wmajt eq "i") {
594 die "panic in word_txt: $wtype$w\n";
599 # This is called from the top level, so I won't bother using
602 # Write contents file. Just the preamble, then a menu of links to the
603 # separate chapter files and the nodes therein.
604 print "writing contents file...";
605 open TEXT
,">nasmdoc0.html";
608 print "<p>This manual documents NASM, the Netwide Assembler: an assembler\n";
609 print "targetting the Intel x86 series of processors, with portable source.\n";
611 for ($node = $tstruct_next{'Top'}; $node; $node = $tstruct_next{$node}) {
612 if ($tstruct_level{$node} == 1) {
613 # Invent a file name.
614 ($number = lc($xrefnodes{$node})) =~ s/.*-//;
615 $fname="nasmdocx.html";
616 substr($fname,8 - length $number, length $number) = $number;
617 $html_fnames{$node} = $fname;
621 # Use the preceding filename plus a marker point.
622 $link = $fname . "#$xrefnodes{$node}";
625 $pname = $tstruct_pname{$node};
626 foreach $i (@
$pname) {
627 $ww = &word_html
($i);
628 $title .= $ww unless $ww eq "\001";
630 print "<a href=\"$link\">$title</a><br>\n";
632 print "<p><a href=\"nasmdoci.html\">Index</a>\n";
633 print "</body></html>\n";
637 # Open a null file, to ensure output (eg random &html_jumppoints calls)
639 print "writing chapter files...";
640 open TEXT
,">/dev/null";
646 for ($para = 0; $para <= $#pnames; $para++) {
647 $pname = $pnames[$para];
648 $pflags = $pflags[$para];
649 $ptype = substr($pflags,0,4);
651 $in_list = 0, print "</ul>\n" if $in_list && $ptype ne "bull";
652 if ($ptype eq "chap") {
653 # Chapter heading. Begin a new file.
654 $pflags =~ /chap (.*) :(.*)/;
655 $title = "Chapter $1: ";
657 &html_jumppoints
; print "</body></html>\n"; select STDOUT
; close TEXT
;
658 $html_lastf = $html_fnames{$chapternode};
659 $chapternode = $nodexrefs{$xref};
660 $html_nextf = $html_fnames{$tstruct_mnext{$chapternode}};
661 open TEXT
,">$html_fnames{$chapternode}"; select TEXT
; &html_preamble
(1);
662 foreach $i (@
$pname) {
663 $ww = &word_html
($i);
664 $title .= $ww unless $ww eq "\001";
666 $h = "<h2><a name=\"$xref\">$title</a></h2>\n";
667 print $h; print FULL
$h;
668 } elsif ($ptype eq "appn") {
669 # Appendix heading. Begin a new file.
670 $pflags =~ /appn (.*) :(.*)/;
671 $title = "Appendix $1: ";
673 &html_jumppoints
; print "</body></html>\n"; select STDOUT
; close TEXT
;
674 $html_lastf = $html_fnames{$chapternode};
675 $chapternode = $nodexrefs{$xref};
676 $html_nextf = $html_fnames{$tstruct_mnext{$chapternode}};
677 open TEXT
,">$html_fnames{$chapternode}"; select TEXT
; &html_preamble
(1);
678 foreach $i (@
$pname) {
679 $ww = &word_html
($i);
680 $title .= $ww unless $ww eq "\001";
682 print "<h2><a name=\"$xref\">$title</a></h2>\n";
683 } elsif ($ptype eq "head" || $ptype eq "subh") {
684 # Heading or subheading.
685 $pflags =~ /.... (.*) :(.*)/;
686 $hdr = ($ptype eq "subh" ?
"h4" : "h3");
689 foreach $i (@
$pname) {
690 $ww = &word_html
($i);
691 $title .= $ww unless $ww eq "\001";
693 print "<$hdr><a name=\"$xref\">$title</a></$hdr>\n";
694 } elsif ($ptype eq "code") {
697 foreach $i (@
$pname) {
705 } elsif ($ptype eq "bull" || $ptype eq "norm") {
706 # Ordinary paragraph, optionally bulleted. We wrap, with ragged
707 # 75-char right margin and either 7 or 11 char left margin
708 # depending on bullets.
709 if ($ptype eq "bull") {
710 $in_list = 1, print "<ul>\n" unless $in_list;
718 do { $w = &word_html
(shift @a) } while $w eq "\001"; # nasty hack
720 if ($w eq ' ' || $w eq '' || $w eq undef) {
721 if (length ($line . $wd) > 75) {
722 $line =~ s/\s*$//; # trim trailing spaces
725 $wd =~ s/^\s*//; # trim leading spaces
731 } while ($w ne '' && $w ne undef);
733 $line =~ s/\s*$//; # trim trailing spaces
739 # Close whichever file was open.
741 print "</body></html>\n";
745 print "\n writing index file...";
746 open TEXT
,">nasmdoci.html";
749 print "<p align=center><a href=\"nasmdoc0.html\">Contents</a>\n";
752 print "<p align=center><a href=\"nasmdoc0.html\">Contents</a>\n";
753 print "</body></html>\n";
759 print "<html><head><title>NASM Manual</title></head>\n";
760 print "<body><h1 align=center>The Netwide Assembler: NASM</h1>\n\n";
761 &html_jumppoints
if $_[0];
764 sub html_jumppoints
{
765 print "<p align=center>";
766 print "<a href=\"$html_nextf\">Next Chapter</a> |\n" if $html_nextf;
767 print "<a href=\"$html_lastf\">Previous Chapter</a> |\n" if $html_lastf;
768 print "<a href=\"nasmdoc0.html\">Contents</a> |\n";
769 print "<a href=\"nasmdoci.html\">Index</a>\n";
773 my $itag, $a, @ientry, $sep, $w, $wd, $wprev, $line;
776 foreach $itag (@itags) {
777 $ientry = $idxmap{$itag};
781 foreach $node (@nodes) {
782 next if !$idxnodes{$node,$itag};
783 push @a, "n ," if $sep;
784 push @a, "sp", "x $xrefnodes{$node}", "n $node", "xe$xrefnodes{$node}";
789 do { $w = &word_html
(shift @a) } while $w eq "\001"; # nasty hack
791 if ($w eq ' ' || $w eq '' || $w eq undef) {
792 if (length ($line . $wd) > 75) {
793 $line =~ s/\s*$//; # trim trailing spaces
796 $wd =~ s/^\s*//; # trim leading spaces
802 } while ($w ne '' && $w ne undef);
804 $line =~ s/\s*$//; # trim trailing spaces
813 my $wtype, $wmajt, $pfx, $sfx;
815 return undef if $w eq '' || $w eq undef;
817 $wtype = substr($w,0,2);
818 $wmajt = substr($wtype,0,1);
821 $pfx = "<a href=\"$1\">", $sfx = "</a>", $w = $2
822 if $wmajt eq "w" && $w =~ /^<(.*)>(.*)$/;
826 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
827 return $pfx . $w . $sfx;
828 } elsif ($wtype eq "sp") {
830 } elsif ($wtype eq "da") {
831 return '-'; # sadly, en-dashes are non-standard in HTML
832 } elsif ($wmajt eq "c" || $wtype eq "wc") {
833 return $pfx . "<code><nobr>${w}</nobr></code>" . $sfx;
834 } elsif ($wtype eq "es") {
836 } elsif ($wtype eq "ee") {
838 } elsif ($wtype eq "eo") {
839 return "<em>${w}</em>";
840 } elsif ($wtype eq "x ") {
841 # Magic: we must resolve the cross reference into file and marker
842 # parts, then dispose of the file part if it's us, and dispose of
843 # the marker part if the cross reference describes the top node of
845 my $node = $nodexrefs{$w}; # find the node we're aiming at
846 my $level = $tstruct_level{$node}; # and its level
847 my $up = $node, $uplev = $level-1;
848 $up = $tstruct_up{$up} while $uplev--; # get top node of containing file
849 my $file = ($up ne $chapternode) ?
$html_fnames{$up} : "";
850 my $marker = ($level == 1 and $file) ?
"" : "#$w";
851 return "<a href=\"$file$marker\">";
852 } elsif ($wtype eq "xe") {
854 } elsif ($wmajt eq "i") {
857 die "panic in word_html: $wtype$w\n";
862 # This is called from the top level, so I won't bother using
865 # First, set up the font metric arrays.
868 # First stage: reprocess the source arrays into a list of
869 # lines, each of which is a list of word-strings, each of
870 # which has a single-letter font code followed by text.
871 # Each line also has an associated type, which will be
872 # used for final alignment and font selection and things.
878 # ' ' == space (no following text required)
879 # '-' == dash (no following text required)
882 # chap == Chapter or appendix heading.
883 # head == Major heading.
884 # subh == Sub-heading.
885 # Ccha == Contents entry for a chapter.
886 # Chea == Contents entry for a heading.
887 # Csub == Contents entry for a subheading.
888 # cone == Code paragraph with just this one line on it.
889 # cbeg == First line of multi-line code paragraph.
890 # cbdy == Interior line of multi-line code paragraph.
891 # cend == Final line of multi-line code paragraph.
892 # none == Normal paragraph with just this one line on it.
893 # nbeg == First line of multi-line normal paragraph.
894 # nbdy == Interior line of multi-line normal paragraph.
895 # nend == Final line of multi-line normal paragraph.
896 # bone == Bulleted paragraph with just this one line on it.
897 # bbeg == First line of multi-line bulleted paragraph.
898 # bbdy == Interior line of multi-line bulleted paragraph.
899 # bend == Final line of multi-line bulleted paragraph.
900 print "line-breaks...";
901 $lname = "psline000000";
902 $lnamei = "idx" . $lname;
903 @lnames = @ltypes = ();
905 for ($para = 0; $para <= $#pnames; $para++) {
906 $pname = $pnames[$para];
907 $pflags = $pflags[$para];
908 $ptype = substr($pflags,0,4);
910 # New paragraph _ergo_ new line.
912 @lindex = (); # list of index tags referenced to this line
914 if ($ptype eq "chap") {
915 # Chapter heading. "Chapter N: Title" followed by a line of
917 $pflags =~ /chap (.*) :(.*)/;
918 push @line, "nChapter", " ", "n$1:", " ";
919 foreach $i (@
$pname) {
921 push @line, $ww unless $ww eq "x";
923 @
$lname = @line; @
$lnamei = @lindex;
924 push @lnames, $lname++;
925 $lnamei = "idx" . $lname;
926 push @ltypes, "chap";
927 } elsif ($ptype eq "appn") {
928 # Appendix heading. "Appendix N: Title" followed by a line of
930 $pflags =~ /appn (.*) :(.*)/;
931 push @line, "nAppendix", " ", "n$1:", " ";
932 foreach $i (@
$pname) {
934 push @line, $ww unless $ww eq "x";
936 @
$lname = @line; @
$lnamei = @lindex;
937 push @lnames, $lname++;
938 $lnamei = "idx" . $lname;
939 push @ltypes, "chap";
940 } elsif ($ptype eq "head") {
941 # Heading. Just a number and some text.
942 $pflags =~ /.... (.*) :(.*)/;
944 foreach $i (@
$pname) {
946 push @line, $ww unless $ww eq "x";
948 @
$lname = @line; @
$lnamei = @lindex;
949 push @lnames, $lname++;
950 $lnamei = "idx" . $lname;
951 push @ltypes, $ptype;
952 } elsif ($ptype eq "subh") {
953 # Subheading. Just a number and some text.
954 $pflags =~ /subh (.*) :(.*)/;
956 foreach $i (@
$pname) {
957 push @line, &word_ps
($i);
959 @
$lname = @line; @
$lnamei = @lindex;
960 push @lnames, $lname++;
961 $lnamei = "idx" . $lname;
962 push @ltypes, "subh";
963 } elsif ($ptype eq "code") {
964 # Code paragraph. Emit lines one at a time.
966 foreach $i (@
$pname) {
968 push @lnames, $lname++;
969 $lnamei = "idx" . $lname;
973 $ltypes[$#ltypes] = ($ltypes[$#ltypes] eq "cbeg" ?
"cone" : "cend");
974 } elsif ($ptype eq "bull" || $ptype eq "norm") {
975 # Ordinary paragraph, optionally bulleted. We wrap, with ragged
976 # 75-char right margin and either 7 or 11 char left margin
977 # depending on bullets.
978 if ($ptype eq "bull") {
979 $width = 456; # leave 12-pt left indent for the bullet
980 $type = $begtype = "bbeg";
986 $type = $begtype = "nbeg";
996 do { $w = &word_ps
(shift @a) } while ($w eq "x");
997 push @wd, $wprev if $wprev;
998 if ($wprev =~ /^n.*-$/ || $w eq ' ' || $w eq '' || $w eq undef) {
999 $wdlen = &len_ps
(@wd);
1000 if ($linelen + $wdlen > $width) {
1001 pop @line while $line[$#line] eq ' '; # trim trailing spaces
1002 @
$lname = @line; @
$lnamei = @lindex;
1003 push @lnames, $lname++;
1004 $lnamei = "idx" . $lname;
1005 push @ltypes, $type;
1007 @line = @lindex = ();
1009 shift @wd while $wd[0] eq ' '; # trim leading spaces
1016 } while ($w ne '' && $w ne undef);
1018 pop @line while $line[$#line] eq ' '; # trim trailing spaces
1019 @
$lname = @line; @
$lnamei = @lindex;
1020 push @lnames, $lname++;
1021 $lnamei = "idx" . $lname;
1022 push @ltypes, $type;
1026 ($ltypes[$#ltypes] eq $begtype ?
$onetype : $endtype);
1030 # We've now processed the document source into lines. Before we
1031 # go on and do the page breaking, we'll fabricate a table of contents,
1032 # line by line, and then after doing page breaks we'll go back and
1033 # insert the page numbers into the contents entries.
1034 print "building contents...";
1035 @clnames = @cltypes = ();
1036 $clname = "pscont000000";
1037 @
$clname = ("nContents"); # "chapter heading" for TOC
1038 push @clnames,$clname++;
1039 push @cltypes,"chap";
1040 for ($i=0; $i<=$#lnames; $i++) {
1041 $lname = $lnames[$i];
1042 if ($ltypes[$i] =~ /^(chap|head|subh)/) {
1044 splice @
$clname,1,0," " if ($ltypes[$i] !~ /chap/);
1045 push @
$clname,$i; # placeholder for page number
1046 push @clnames,$clname++;
1047 push @cltypes,"C" . substr($ltypes[$i],0,3);
1050 @
$clname = ("nIndex"); # contents entry for Index
1051 push @
$clname,$i; # placeholder for page number
1052 $idx_clname = $clname;
1053 push @clnames,$clname++;
1054 push @cltypes,"Ccha";
1055 $contlen = $#clnames + 1;
1056 unshift @lnames,@clnames;
1057 unshift @ltypes,@cltypes;
1059 # Second stage: now we have a list of lines, break them into pages.
1060 # We do this by means of adding a third array in parallel with
1061 # @lnames and @ltypes, called @lpages, in which we store the page
1062 # number that each line resides on. We also add @ycoord which
1063 # stores the vertical position of each line on the page.
1065 # Page breaks may not come after line-types:
1066 # chap head subh cbeg nbeg bbeg
1067 # and may not come before line-types:
1069 # They are forced before line-types:
1071 print "page-breaks...";
1072 $pmax = 600; # ADJUSTABLE: maximum length of a page in points
1073 $textht = 11; # ADJUSTABLE: height of a normal line in points
1074 $spacing = 6; # ADJUSTABLE: space between paragraphs, in points
1075 $headht = 14; # ADJUSTABLE: height of a major heading in points
1076 $subht = 12; # ADJUSTABLE: height of a sub-heading in points
1077 $pstart = 0; # start line of current page
1078 $plen = 0; # current length of current page
1079 $pnum = 1; # number of current page
1080 $bpt = -1; # last feasible break point
1081 $i = 0; # line number
1082 while ($i <= $#lnames) {
1083 $lname = $lnames[$i];
1084 # Add the height of this line (computed the last time we went round
1085 # the loop, unless we're a chapter heading in which case we do it
1086 # now) to the length of the current page. Also, _put_ this line on
1087 # the current page, and allocate it a y-coordinate.
1088 if ($ltypes[$i] =~ /^chap$/) {
1089 $pnum += 1 - ($pnum & 1); # advance to odd numbered page if necessary
1090 $plen = 100; # ADJUSTABLE: space taken up by a chapter heading
1091 $ycoord[$i] = 0; # chapter heading: y-coord doesn't matter
1093 $ycoord[$i] = $plen + $space;
1094 $plen += $space + $ht;
1096 # See if we can break after this line.
1097 $bpt = $i if $ltypes[$i] !~ /^chap|head|subh|cbeg|nbeg|bbeg$/ &&
1098 $ltypes[$i+1] !~ /^cend|nend|bend$/;
1099 # Assume, to start with, that we don't break after this line.
1101 # See if a break is forced.
1102 $break = 1, $bpt = $i if $ltypes[$i+1] eq "chap" || !$ltypes[$i+1];
1103 # Otherwise, compute the height of the next line, and break if
1104 # it would make this page too long.
1105 $ht = $textht, $space = 0 if $ltypes[$i+1] =~ /^[nbc](bdy|end)$/;
1106 $ht = $textht, $space = $spacing if $ltypes[$i+1] =~ /^[nbc](one|beg)$/;
1107 $ht = $textht, $space = $spacing if $ltypes[$i+1] =~ /^C/;
1108 $ht = $subht, $space = $spacing if $ltypes[$i+1] eq "subh";
1109 $ht = $headht, $space = $spacing if $ltypes[$i+1] eq "head";
1110 $break = 1 if $plen + $space + $ht > $pmax;
1111 # Now, if we're breaking, assign page number $pnum to all lines up
1112 # to $bpt, set $i == $bpt+1, and zero $space since we are at the
1113 # start of a new page and don't want leading space.
1115 die "no feasible break point at all on page $pnum\n" if $bpt == -1;
1116 for ($j = $pstart; $j <= $bpt; $j++) {
1117 $lnamei = "idx" . $lnames[$j];
1118 foreach $k (@
$lnamei) {
1119 ${$psidxpp{$k}}{$pnum} = 1;
1121 $lpages[$j] = $pnum;
1133 # Now fix up the TOC with page numbers.
1134 print "\n fixing up contents...";
1135 for ($i=0; $i<=$#lnames; $i++) {
1136 $lname = $lnames[$i];
1137 if ($ltypes[$i] =~ /^C/) {
1139 push @
$lname, "n" . $lpages[$j+$contlen];
1143 # Having got page numbers for most stuff, generate an index.
1144 print "building index...";
1148 foreach $k (@itags) {
1151 @idxentry = @
{$idxmap{$k}};
1152 if ($commaafter{$k} and !$commanext{$k}) {
1153 # This line is a null line beginning a multiple entry. We must
1154 # output the prefix on a line by itself.
1156 @idxhead = splice @idxentry,0,$commapos{$k};
1158 foreach $i (@idxhead) {
1160 push @line, $ww unless $ww eq "x";
1162 &ps_idxout
("index",\
@line,[]);
1166 $cmd = "iindex", splice @idxentry,0,$commapos{$k} if $commanext{$k};
1167 foreach $i (@idxentry) {
1169 push @line, $ww unless $ww eq "x";
1171 $len = $iwid - $sep - &len_ps
(@line);
1172 warn "text for index tag `%s' is longer than one index line!\n"
1175 $inums = join(',',sort { $a <=> $b } keys %{$psidxpp{$k}});
1176 while (length $inums) {
1177 $inums =~ /^([^,]+,?)(.*)$/;
1178 $inums = $2, $inum = $1;
1179 @pnum = (" ", "n$inum");
1180 $pnumlen = &len_ps
(@pnum);
1181 if ($pnumlen > $len) {
1182 &ps_idxout
($cmd,\
@line,\
@pp);
1186 $len = $iwid - $sep;
1191 &ps_idxout
($cmd,\
@line,\
@pp) if (length @pp);
1192 $l1 = &len_ps
(@line);
1195 $$idx_clname[$#$idx_clname] = "n" . $pnum; # fix up TOC entry for index
1197 print "writing file...";
1198 open PS
,">nasmdoc.ps";
1202 for ($i=0; $i<=$#lnames; $i++) {
1203 &ps_throw_pg
($page,$lpages[$i]) if $page != $lpages[$i];
1204 $page = $lpages[$i];
1205 &ps_out_line
($ycoord[$i],$ltypes[$i],$lnames[$i]);
1208 while ($i <= $#psindex) {
1209 &ps_throw_pg
($page, $pnum) if $page != $pnum;
1212 $ypos = 100, &ps_out_line
(0, "chap", ["nIndex"]) if !$i;
1213 $lines = ($pmax - $ypos) / $textht;
1214 my $col; # ps_out_line hits this variable
1215 PAGE
:for ($col = 1; $col <= 2; $col++) {
1216 $y = $ypos; $l = $lines;
1217 COL
: while ($l > 0) {
1219 $j++ while $psindex[$j] and ($psindex[$j][3] == 0); # find next break
1220 last COL
if $j-$i > $l or $i > $#psindex;
1222 &ps_out_line
($y, $psindex[$i][0] eq "index" ?
"idl$col" : "ldl$col",
1224 &ps_out_line
($y,"idr$col",$psindex[$i][2]);
1230 last PAGE
if $i > $#psindex;
1239 my ($cmd, $left, $right) = @_;
1242 if ($#psindex >= 0) and ( ($#$left < 0) or ($cmd eq "iindex") );
1243 push @psindex,[$cmd,[@
$left],[@
$right],$break];
1248 '/sp (n ) def', # here it's sure not to get wrapped inside ()
1249 '/nf /Times-Roman findfont 11 scalefont def',
1250 '/ef /Times-Italic findfont 11 scalefont def',
1251 '/cf /Courier findfont 11 scalefont def',
1252 '/nc /Helvetica-Bold findfont 18 scalefont def',
1253 '/ec /Helvetica-Oblique findfont 18 scalefont def',
1254 '/cc /Courier-Bold findfont 18 scalefont def',
1255 '/nh /Helvetica-Bold findfont 14 scalefont def',
1256 '/eh /Helvetica-Oblique findfont 14 scalefont def',
1257 '/ch /Courier-Bold findfont 14 scalefont def',
1258 '/ns /Helvetica-Bold findfont 12 scalefont def',
1259 '/es /Helvetica-Oblique findfont 12 scalefont def',
1260 '/cs /Courier-Bold findfont 12 scalefont def',
1261 '/n 16#6E def /e 16#65 def /c 16#63 def',
1263 ' 550 50 moveto ns setfont dup stringwidth pop neg 0 rmoveto show',
1265 '/pageeven { 50 50 moveto ns setfont show } def',
1270 ' dup n eq {pop nc setfont} {',
1271 ' e eq {ec setfont} {cc setfont} ifelse',
1273 ' dup length 1 sub 1 exch getinterval show',
1275 ' 0 setlinecap 3 setlinewidth',
1276 ' newpath 100 610 moveto 468 0 rlineto stroke',
1279 ' 686 exch sub /y exch def /a exch def',
1280 ' 90 y moveto a 0 get dup length 1 sub 1 exch getinterval',
1281 ' nh setfont dup stringwidth pop neg 0 rmoveto show',
1283 ' a dup length 1 sub 1 exch getinterval {',
1286 ' dup n eq {pop nh setfont} {',
1287 ' e eq {eh setfont} {ch setfont} ifelse',
1289 ' s s length 1 sub 1 exch getinterval show',
1293 ' 688 exch sub /y exch def /a exch def',
1294 ' 90 y moveto a 0 get dup length 1 sub 1 exch getinterval',
1295 ' ns setfont dup stringwidth pop neg 0 rmoveto show',
1297 ' a dup length 1 sub 1 exch getinterval {',
1300 ' dup n eq {pop ns setfont} {',
1301 ' e eq {es setfont} {cs setfont} ifelse',
1303 ' s s length 1 sub 1 exch getinterval show',
1306 '/disp { /j exch def',
1307 ' 568 exch sub exch 689 exch sub moveto',
1311 ' dup n eq {pop nf setfont} {',
1312 ' e eq {ef setfont} {cf setfont} ifelse',
1314 ' s s length 1 sub 1 exch getinterval show',
1315 ' s sp eq {j 0 rmoveto} if',
1318 '/contents { /w exch def /y exch def /a exch def',
1319 ' /yy 689 y sub def',
1320 ' a a length 1 sub get dup length 1 sub 1 exch getinterval /s exch def',
1321 ' nf setfont 568 s stringwidth pop sub /ex exch def',
1322 ' ex yy moveto s show',
1323 ' a 0 a length 1 sub getinterval y w 0 disp',
1324 ' /sx currentpoint pop def nf setfont',
1325 ' 100 10 568 { /i exch def',
1326 ' i 5 sub sx gt i 5 add ex lt and {',
1327 ' i yy moveto (.) show',
1331 '/just { /w exch def /y exch def /a exch def',
1332 ' /jj w def /spaces 0 def',
1336 ' dup n eq {pop nf setfont} {',
1337 ' e eq {ef setfont} {cf setfont} ifelse',
1339 ' s s length 1 sub 1 exch getinterval stringwidth pop',
1340 ' jj exch sub /jj exch def',
1341 ' s sp eq {/spaces spaces 1 add def} if',
1343 ' a y w jj spaces spaces 0 eq {pop pop 0} {div} ifelse disp',
1345 '/idl { 468 exch sub 0 disp } def',
1346 '/ldl { 436 exch sub 0 disp } def',
1347 '/idr { 222 add 468 exch sub /x exch def /y exch def /a exch def',
1351 ' dup n eq {pop nf setfont} {',
1352 ' e eq {ef setfont} {cf setfont} ifelse',
1354 ' s s length 1 sub 1 exch getinterval stringwidth pop',
1355 ' x add /x exch def',
1359 '/left {0 disp} def',
1361 ' nf setfont dup 100 exch 689 exch sub moveto (\267) show',
1364 print "%!PS-Adobe-3.0\n";
1365 print "%%BoundingBox: 95 95 590 705\n";
1366 print "%%Creator: a nasty Perl script\n";
1367 print "%%DocumentData: Clean7Bit\n";
1368 print "%%Orientation: Portrait\n";
1369 print "%%Pages: $lpages[$#lpages]\n";
1370 print "%%DocumentNeededResources: font Times-Roman Times-Italic\n";
1371 print "%%+ font Helvetica-Bold Courier Courier-Bold\n";
1372 print "%%EndComments\n%%BeginProlog\n%%EndProlog\n%%BeginSetup\nsave\n";
1373 $pshdr = join(' ',@pshdr);
1374 $pshdr =~ s/\s+/ /g;
1375 while ($pshdr =~ /\S/) {
1376 last if length($pshdr) < 72 || $pshdr !~ /^(.{0,72}\S)\s(.*)$/;
1380 print "$pshdr\n" if $pshdr =~ /\S/;
1381 print "%%EndSetup\n";
1382 &ps_initpg
($lpages[0]);
1388 print "%%Trailer\nrestore\n%%EOF\n";
1392 my ($oldpg, $newpg) = @_;
1393 while ($oldpg < $newpg) {
1402 print "%%Page: $pgnum $pgnum\n";
1403 print "%%BeginPageSetup\nsave\n%%EndPageSetup\n";
1409 print "%%PageTrailer\n($pgnum)pageodd restore showpage\n";
1411 print "%%PageTrailer\n($pgnum)pageeven restore showpage\n";
1416 my ($ypos,$ltype,$lname) = @_;
1421 foreach $c (@
$lname) {#
1422 $c= "n " if $c eq " ";
1423 $c = "n\261" if $c eq "-";
1426 $d .= $1, $c = $2 while $c =~ /^([ -'\*-\[\]-~]+)(.*)$/;
1428 $d .= "\\$1", $c = $2, next if $c =~ /^([\\\(\)])(.*)$/;
1429 ($d .= sprintf "\\%3o",unpack("C",$1)), $c = $2, next
1430 if $c =~ /^([^ -~])(.*)$/;
1435 $col = 0, print "\n" if $col>0 && $col+length $d > 77;
1439 print "\n" if $col > 60;
1441 if ($ltype =~ /^[nb](beg|bdy)$/) {
1442 printf "%d %s%d just\n",
1443 $ypos, ($ltype eq "bbeg" ?
"bullet " : ""),
1444 ($ltype =~ /^b/ ?
456 : 468);
1445 } elsif ($ltype =~ /^[nb](one|end)$/) {
1446 printf "%d %s%d left\n",
1447 $ypos, ($ltype eq "bone" ?
"bullet " : ""),
1448 ($ltype =~ /^b/ ?
456 : 468);
1449 } elsif ($ltype =~ /^c(one|beg|bdy|end)$/) {
1450 printf "$ypos 468 left\n";
1451 } elsif ($ltype =~ /^C/) {
1453 $wid = 456 if $ltype eq "Chea";
1454 $wid = 444 if $ltype eq "Csub";
1455 printf "$ypos $wid contents\n";
1456 } elsif ($ltype eq "chap") {
1458 } elsif ($ltype eq "head") {
1459 printf "$ypos heading\n";
1460 } elsif ($ltype eq "subh") {
1461 printf "$ypos subhead\n";
1462 } elsif ($ltype =~ /([il]d[lr])([12])/) {
1463 $left = ($2 eq "2" ?
468-222 : 0);
1464 printf "$ypos $left $1\n";
1472 return undef if $w eq '' || $w eq undef;
1474 $wtype = substr($w,0,2);
1475 $wmajt = substr($wtype,0,1);
1477 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
1478 if ($wmajt eq "n" || $wtype eq "w ") {
1480 } elsif ($wtype eq "sp") {
1482 } elsif ($wtype eq "da") {
1484 } elsif ($wmajt eq "c" || $wtype eq "wc") {
1486 } elsif ($wmajt eq "e") {
1488 } elsif ($wmajt eq "x") {
1490 } elsif ($wtype eq "i ") {
1494 die "panic in word_ps: $wtype$w\n";
1503 $size = 11/1000; # used only for length calculations
1504 while ($w = shift @line) {
1505 $w = "n " if $w eq " ";
1506 $w = "n\261" if $w eq "-";
1507 $f = substr($w,0,1);
1508 $f = "timesr" if $f eq "n";
1509 $f = "timesi" if $f eq "e";
1510 $f = "courr" if $f eq "c";
1511 foreach $c (unpack 'C*',substr($w,1)) {
1512 $l += $size * $$f[$c];
1519 # This is called from the top level, so I won't bother using
1523 print "writing file...";
1524 open TEXT
,">nasmdoc.texi";
1528 print "\\input texinfo \@c -*-texinfo-*-\n";
1529 print "\@c \%**start of header\n";
1530 print "\@setfilename nasm.info\n";
1531 print "\@dircategory Programming\n";
1532 print "\@direntry\n";
1533 print "* NASM: (nasm). The Netwide Assembler for x86.\n";
1534 print "\@end direntry\n";
1535 print "\@settitle NASM: The Netwide Assembler\n";
1536 print "\@setchapternewpage odd\n";
1537 print "\@c \%**end of header\n";
1540 print "This file documents NASM, the Netwide Assembler: an assembler\n";
1541 print "targetting the Intel x86 series of processors, with portable source.\n";
1543 print "Copyright 1997 Simon Tatham\n";
1545 print "All rights reserved. This document is redistributable under the\n";
1546 print "licence given in the file \"Licence\" distributed in the NASM archive.\n";
1547 print "\@end ifinfo\n";
1549 print "\@titlepage\n";
1550 print "\@title NASM: The Netwide Assembler\n";
1551 print "\@author Simon Tatham\n";
1554 print "\@vskip 0pt plus 1filll\n";
1555 print "Copyright \@copyright{} 1997 Simon Tatham\n";
1557 print "All rights reserved. This document is redistributable under the\n";
1558 print "licence given in the file \"Licence\" distributed in the NASM archive.\n";
1559 print "\@end titlepage\n";
1561 print "\@node Top, $tstruct_next{'Top'}, (dir), (dir)\n";
1562 print "\@top Netwide Assembler\n";
1565 print "This file documents NASM, the Netwide Assembler: an assembler\n";
1566 print "targetting the Intel x86 series of processors, with portable source.\n";
1567 print "\@end ifinfo\n";
1572 for ($para = 0; $para <= $#pnames; $para++) {
1573 $pname = $pnames[$para];
1574 $pflags = $pflags[$para];
1575 $ptype = substr($pflags,0,4);
1577 $bulleting = 0, print "\@end itemize\n" if $bulleting && $ptype ne "bull";
1578 print "\n"; # always one of these before a new paragraph
1580 if ($ptype eq "chap") {
1581 # Chapter heading. Begin a new node.
1583 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1584 $pflags =~ /chap (.*) :(.*)/;
1585 $node = "Chapter $1";
1586 $title = "Chapter $1: ";
1587 foreach $i (@
$pname) {
1588 $ww = &word_texi
($i);
1589 $title .= $ww unless $ww eq "\001";
1591 print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},";
1592 print " $tstruct_up{$node}\n\@unnumbered $title\n";
1593 } elsif ($ptype eq "appn") {
1594 # Appendix heading. Begin a new node.
1596 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1597 $pflags =~ /appn (.*) :(.*)/;
1598 $node = "Appendix $1";
1599 $title = "Appendix $1: ";
1600 foreach $i (@
$pname) {
1601 $ww = &word_texi
($i);
1602 $title .= $ww unless $ww eq "\001";
1604 print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},";
1605 print " $tstruct_up{$node}\n\@unnumbered $title\n";
1606 } elsif ($ptype eq "head" || $ptype eq "subh") {
1607 # Heading or subheading. Begin a new node.
1609 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1610 $pflags =~ /.... (.*) :(.*)/;
1611 $node = "Section $1";
1613 foreach $i (@
$pname) {
1614 $ww = &word_texi
($i);
1615 $title .= $ww unless $ww eq "\001";
1617 print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},";
1618 print " $tstruct_up{$node}\n";
1619 $hdr = ($ptype eq "subh" ?
"\@unnumberedsubsec" : "\@unnumberedsec");
1620 print "$hdr $title\n";
1621 } elsif ($ptype eq "code") {
1622 # Code paragraph. Surround with @example / @end example.
1623 print "\@example\n";
1624 foreach $i (@
$pname) {
1625 warn "code line longer than 68 chars: $i\n" if length $i > 68;
1631 print "\@end example\n";
1632 } elsif ($ptype eq "bull" || $ptype eq "norm") {
1633 # Ordinary paragraph, optionally bulleted. We wrap, FWIW.
1634 if ($ptype eq "bull") {
1635 $bulleting = 1, print "\@itemize \@bullet\n" if !$bulleting;
1642 do { $w = &word_texi
(shift @a); } while $w eq "\001"; # hack
1644 if ($wprev =~ /-$/ || $w eq ' ' || $w eq '' || $w eq undef) {
1645 if (length ($line . $wd) > 75) {
1646 $line =~ s/\s*$//; # trim trailing spaces
1649 $wd =~ s/^\s*//; # trim leading spaces
1655 } while ($w ne '' && $w ne undef);
1656 if ($line =~ /\S/) {
1657 $line =~ s/\s*$//; # trim trailing spaces
1667 print "\n\@contents\n\@bye\n";
1672 # Side effect of this procedure: update global `texiwdlen' to be the length
1673 # in chars of the formatted version of the word.
1678 return undef if $w eq '' || $w eq undef;
1679 $wtype = substr($w,0,2);
1680 $wmajt = substr($wtype,0,1);
1686 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
1687 substr($w,0,1) =~ tr/a-z/A-Z/, $capital = 0 if $capital;
1688 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
1691 } elsif ($wtype eq "sp") {
1694 } elsif ($wtype eq "da") {
1697 } elsif ($wmajt eq "c" || $wtype eq "wc") {
1698 $texiwdlen = 2 + $wlen;
1699 return "\@code\{$w\}";
1700 } elsif ($wtype eq "es") {
1701 $texiwdlen = 1 + $wlen;
1702 return "\@emph\{${w}";
1703 } elsif ($wtype eq "ee") {
1704 $texiwdlen = 1 + $wlen;
1706 } elsif ($wtype eq "eo") {
1707 $texiwdlen = 2 + $wlen;
1708 return "\@emph\{${w}\}";
1709 } elsif ($wtype eq "x ") {
1710 $texiwdlen = 0; # we don't need it in this case
1711 $capital = 1; # hack
1713 } elsif ($wtype eq "xe") {
1714 $texiwdlen = 0; # we don't need it in this case
1716 } elsif ($wmajt eq "i") {
1717 $texiwdlen = 0; # we don't need it in this case
1720 die "panic in word_texi: $wtype$w\n";
1726 my $item, $i, $mpname, $title, $wd;
1728 $item = $tstruct_next{$topitem};
1732 $mpname = $tstruct_pname{$item};
1733 foreach $i (@
$mpname) {
1734 $wd = &word_texi
($i);
1735 $title .= $wd unless $wd eq "\001";
1737 print "* ${item}:: $title\n";
1738 $item = $tstruct_mnext{$item};
1740 print "* Index::\n" if $topitem eq "Top";
1741 print "\@end menu\n";
1745 my $itag, $ientry, @a, $wd, $item, $len;
1746 my $subnums = "123456789ABCDEFGHIJKLMNOPQRSTU" .
1747 "VWXYZabcdefghijklmnopqrstuvwxyz";
1749 print "\@ifinfo\n\@node Index, , $FIXMElastnode, Top\n";
1750 print "\@unnumbered Index\n\n\@menu\n";
1752 foreach $itag (@itags) {
1753 $ientry = $idxmap{$itag};
1758 $wd = &word_texi
($i);
1759 $item .= $wd, $len += $texiwdlen unless $wd eq "\001";
1762 foreach $node (@nodes) {
1763 next if !$idxnodes{$node,$itag};
1764 printf "* %s%s (%s): %s.\n",
1765 $item, " " x
(40-$len), substr($subnums,$i++,1), $node;
1768 print "\@end menu\n\@end ifinfo\n";
1772 # This is called from the top level, so I won't bother using
1775 # Build the index-tag text forms.
1776 print "building index entries...";
1779 my $ientry = $idxmap{$_};
1781 foreach $i (@
$ientry) {
1782 $ww = &word_hlp
($i,0);
1783 $title .= $ww unless $ww eq "\001";
1788 # Write the HPJ project-description file.
1789 print "writing .hpj file...";
1790 open HPJ
,">nasmdoc.hpj";
1791 print HPJ
"[OPTIONS]\ncompress=true\n";
1792 print HPJ
"title=NASM: The Netwide Assembler\noldkeyphrase=no\n\n";
1793 print HPJ
"[FILES]\nnasmdoc.rtf\n\n";
1794 print HPJ
"[CONFIG]\n";
1795 print HPJ
'CreateButton("btn_up", "&Up",'.
1796 ' "JumpContents(`nasmdoc.hlp'."'".')")';
1797 print HPJ
"\nBrowseButtons()\n";
1801 print "\n writing .rtf file...";
1802 open TEXT
,">nasmdoc.rtf";
1806 print "{\\rtf1\\ansi{\\fonttbl\n";
1807 print "\\f0\\froman Times New Roman;\\f1\\fmodern Courier New;\n";
1808 print "\\f2\\fswiss Arial;\\f3\\ftech Wingdings}\\deff0\n";
1809 print "#{\\footnote Top}\n";
1810 print "\${\\footnote Contents}\n";
1811 print "+{\\footnote browse:00000}\n";
1812 print "!{\\footnote DisableButton(\"btn_up\")}\n";
1813 print "\\keepn\\f2\\b\\fs30\\sb0\n";
1814 print "NASM: The Netwide Assembler\n";
1815 print "\\par\\pard\\plain\\sb120\n";
1816 print "This file documents NASM, the Netwide Assembler: an assembler \n";
1817 print "targetting the Intel x86 series of processors, with portable source.\n";
1822 $newpar = "\\par\\sb120\n";
1823 for ($para = 0; $para <= $#pnames; $para++) {
1824 $pname = $pnames[$para];
1825 $pflags = $pflags[$para];
1826 $ptype = substr($pflags,0,4);
1829 $newpar = "\\par\\sb120\n";
1831 if ($ptype eq "chap") {
1832 # Chapter heading. Begin a new node.
1834 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1835 $pflags =~ /chap (.*) :(.*)/;
1836 $node = "Chapter $1";
1837 $title = $footnotetitle = "Chapter $1: ";
1838 foreach $i (@
$pname) {
1839 $ww = &word_hlp
($i,1);
1840 $title .= $ww, $footnotetitle .= &word_hlp
($i,0) unless $ww eq "\001";
1843 printf "#{\\footnote %s}\n", &hlp_sectkw
($node);
1844 print "\${\\footnote $footnotetitle}\n";
1845 printf "+{\\footnote browse:%05d}\n", ++$browse;
1846 printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," .
1847 "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n",
1848 &hlp_sectkw
($tstruct_up{$node});
1849 print "EnableButton(\"btn_up\")}\n";
1850 &hlp_keywords
($node);
1851 print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n";
1853 $newpar = "\\par\\pard\\plain\\sb120\n";
1854 } elsif ($ptype eq "appn") {
1855 # Appendix heading. Begin a new node.
1857 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1858 $pflags =~ /appn (.*) :(.*)/;
1859 $node = "Appendix $1";
1860 $title = $footnotetitle = "Appendix $1: ";
1861 foreach $i (@
$pname) {
1862 $ww = &word_hlp
($i,1);
1863 $title .= $ww, $footnotetitle .= &word_hlp
($i,0) unless $ww eq "\001";
1866 printf "#{\\footnote %s}\n", &hlp_sectkw
($node);
1867 print "\${\\footnote $footnotetitle}\n";
1868 printf "+{\\footnote browse:%05d}\n", ++$browse;
1869 printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," .
1870 "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n",
1871 &hlp_sectkw
($tstruct_up{$node});
1872 print "EnableButton(\"btn_up\")}\n";
1873 &hlp_keywords
($node);
1874 print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n";
1876 $newpar = "\\par\\pard\\plain\\sb120\n";
1877 } elsif ($ptype eq "head" || $ptype eq "subh") {
1878 # Heading or subheading. Begin a new node.
1880 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1881 $pflags =~ /.... (.*) :(.*)/;
1882 $node = "Section $1";
1883 $title = $footnotetitle = "$1. ";
1884 foreach $i (@
$pname) {
1885 $ww = &word_hlp
($i,1);
1886 $title .= $ww, $footnotetitle .= &word_hlp
($i,0) unless $ww eq "\001";
1889 printf "#{\\footnote %s}\n", &hlp_sectkw
($node);
1890 print "\${\\footnote $footnotetitle}\n";
1891 printf "+{\\footnote browse:%05d}\n", ++$browse;
1892 printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," .
1893 "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n",
1894 &hlp_sectkw
($tstruct_up{$node});
1895 print "EnableButton(\"btn_up\")}\n";
1896 &hlp_keywords
($node);
1897 print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n";
1899 $newpar = "\\par\\pard\\plain\\sb120\n";
1900 } elsif ($ptype eq "code") {
1902 print "\\keep\\f1\\sb120\n";
1903 foreach $i (@
$pname) {
1904 warn "code line longer than 68 chars: $i\n" if length $i > 68;
1908 print "$i\\par\\sb0\n";
1910 $newpar = "\\pard\\f0\\sb120\n";
1911 } elsif ($ptype eq "bull" || $ptype eq "norm") {
1912 # Ordinary paragraph, optionally bulleted. We wrap, FWIW.
1913 if ($ptype eq "bull") {
1914 print "\\tx360\\li360\\fi-360{\\f3\\'9F}\\tab\n";
1915 $newpar = "\\par\\pard\\sb120\n";
1917 $newpar = "\\par\\sb120\n";
1923 do { $w = &word_hlp
((shift @a),1); } while $w eq "\001"; # hack
1925 if ($w eq ' ' || $w eq '' || $w eq undef) {
1926 if (length ($line . $wd) > 75) {
1927 $line =~ s/\s*$//; # trim trailing spaces
1928 print "$line \n"; # and put one back
1930 $wd =~ s/^\s*//; # trim leading spaces
1936 } while ($w ne '' && $w ne undef);
1937 if ($line =~ /\S/) {
1938 $line =~ s/\s*$//; # trim trailing spaces
1951 my ($w, $docode) = @_;
1954 return undef if $w eq '' || $w eq undef;
1955 $wtype = substr($w,0,2);
1956 $wmajt = substr($wtype,0,1);
1961 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
1962 substr($w,0,length($w)-1) =~ s/-/\\'AD/g if $wmajt ne "x"; #nonbreakhyphens
1963 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
1965 } elsif ($wtype eq "sp") {
1967 } elsif ($wtype eq "da") {
1969 } elsif ($wmajt eq "c" || $wtype eq "wc") {
1970 $w =~ s/ /\\'A0/g; # make spaces non-breaking
1971 return $docode ?
"{\\f1 ${w}}" : $w;
1972 } elsif ($wtype eq "es") {
1974 } elsif ($wtype eq "ee") {
1976 } elsif ($wtype eq "eo") {
1977 return "{\\i ${w}}";
1978 } elsif ($wtype eq "x ") {
1980 } elsif ($wtype eq "xe") {
1981 $w = &hlp_sectkw
($w);
1982 return "}{\\v ${w}}";
1983 } elsif ($wmajt eq "i") {
1986 die "panic in word_hlp: $wtype$w\n";
1992 my $item, $kword, $i, $mpname, $title;
1994 $item = $tstruct_next{$topitem};
1995 print "\\li360\\fi-360\n";
1998 $mpname = $tstruct_pname{$item};
1999 foreach $i (@
$mpname) {
2000 $ww = &word_hlp
($i, 0);
2001 $title .= $ww unless $ww eq "\001";
2003 $kword = &hlp_sectkw
($item);
2004 print "{\\uldb ${item}: $title}{\\v $kword}\\par\\sb0\n";
2005 $item = $tstruct_mnext{$item};
2007 print "\\pard\\sb120\n";
2012 $node =~ tr/A-Z/a-z/;
2013 $node =~ tr/- ./___/;
2019 my $pfx = "K{\\footnote ";
2021 foreach $i (0..$#itags) {
2022 (print $pfx,$hlp_index[$i]), $pfx = ";\n", $done++
2023 if $idxnodes{$node,$itags[$i]};
2025 print "}\n" if $done;
2028 # Make tree structures. $tstruct_* is top-level and global.
2030 my ($item, $level) = @_;
2033 $tstruct_pname{$item} = $pname;
2034 $tstruct_next{$tstruct_previtem} = $item;
2035 $tstruct_prev{$item} = $tstruct_previtem;
2036 $tstruct_level{$item} = $level;
2037 $tstruct_up{$item} = $tstruct_last[$level-1];
2038 $tstruct_mnext{$tstruct_last[$level]} = $item;
2039 $tstruct_last[$level] = $item;
2040 for ($i=$level+1; $i<$MAXLEVEL; $i++) { $tstruct_last[$i] = undef; }
2041 $tstruct_previtem = $item;
2045 # PostScript font metric data. Used for line breaking.
2048 250, 0, 0, 0, 0, 0, 0, 0,
2049 0, 0, 0, 0, 0, 0, 0, 0,
2050 0, 0, 0, 0, 0, 0, 0, 0,
2051 0, 0, 0, 0, 0, 0, 0, 0,
2052 250, 333, 408, 500, 500, 833, 778, 333,
2053 333, 333, 500, 564, 250, 333, 250, 278,
2054 500, 500, 500, 500, 500, 500, 500, 500,
2055 500, 500, 278, 278, 564, 564, 564, 444,
2056 921, 722, 667, 667, 722, 611, 556, 722,
2057 722, 333, 389, 722, 611, 889, 722, 722,
2058 556, 722, 667, 556, 611, 722, 722, 944,
2059 722, 722, 611, 333, 278, 333, 469, 500,
2060 333, 444, 500, 444, 500, 444, 333, 500,
2061 500, 278, 278, 500, 278, 778, 500, 500,
2062 500, 500, 333, 389, 278, 500, 500, 722,
2063 500, 500, 444, 480, 200, 480, 541, 0,
2064 0, 0, 0, 0, 0, 0, 0, 0,
2065 0, 0, 0, 0, 0, 0, 0, 0,
2066 0, 0, 0, 0, 0, 0, 0, 0,
2067 0, 0, 0, 0, 0, 0, 0, 0,
2068 0, 333, 500, 500, 167, 500, 500, 500,
2069 500, 180, 444, 500, 333, 333, 556, 556,
2070 0, 500, 500, 500, 250, 0, 453, 350,
2071 333, 444, 444, 500,1000,1000, 0, 444,
2072 0, 333, 333, 333, 333, 333, 333, 333,
2073 333, 0, 333, 333, 0, 333, 333, 333,
2074 1000, 0, 0, 0, 0, 0, 0, 0,
2075 0, 0, 0, 0, 0, 0, 0, 0,
2076 0, 889, 0, 276, 0, 0, 0, 0,
2077 611, 722, 889, 310, 0, 0, 0, 0,
2078 0, 667, 0, 0, 0, 278, 0, 0,
2079 278, 500, 722, 500, 0, 0, 0, 0
2082 250, 0, 0, 0, 0, 0, 0, 0,
2083 0, 0, 0, 0, 0, 0, 0, 0,
2084 0, 0, 0, 0, 0, 0, 0, 0,
2085 0, 0, 0, 0, 0, 0, 0, 0,
2086 250, 333, 420, 500, 500, 833, 778, 333,
2087 333, 333, 500, 675, 250, 333, 250, 278,
2088 500, 500, 500, 500, 500, 500, 500, 500,
2089 500, 500, 333, 333, 675, 675, 675, 500,
2090 920, 611, 611, 667, 722, 611, 611, 722,
2091 722, 333, 444, 667, 556, 833, 667, 722,
2092 611, 722, 611, 500, 556, 722, 611, 833,
2093 611, 556, 556, 389, 278, 389, 422, 500,
2094 333, 500, 500, 444, 500, 444, 278, 500,
2095 500, 278, 278, 444, 278, 722, 500, 500,
2096 500, 500, 389, 389, 278, 500, 444, 667,
2097 444, 444, 389, 400, 275, 400, 541, 0,
2098 0, 0, 0, 0, 0, 0, 0, 0,
2099 0, 0, 0, 0, 0, 0, 0, 0,
2100 0, 0, 0, 0, 0, 0, 0, 0,
2101 0, 0, 0, 0, 0, 0, 0, 0,
2102 0, 389, 500, 500, 167, 500, 500, 500,
2103 500, 214, 556, 500, 333, 333, 500, 500,
2104 0, 500, 500, 500, 250, 0, 523, 350,
2105 333, 556, 556, 500, 889,1000, 0, 500,
2106 0, 333, 333, 333, 333, 333, 333, 333,
2107 333, 0, 333, 333, 0, 333, 333, 333,
2108 889, 0, 0, 0, 0, 0, 0, 0,
2109 0, 0, 0, 0, 0, 0, 0, 0,
2110 0, 889, 0, 276, 0, 0, 0, 0,
2111 556, 722, 944, 310, 0, 0, 0, 0,
2112 0, 667, 0, 0, 0, 278, 0, 0,
2113 278, 500, 667, 500, 0, 0, 0, 0
2116 600, 0, 0, 0, 0, 0, 0, 0,
2117 0, 0, 0, 0, 0, 0, 0, 0,
2118 0, 0, 0, 0, 0, 0, 0, 0,
2119 0, 0, 0, 0, 0, 0, 0, 0,
2120 600, 600, 600, 600, 600, 600, 600, 600,
2121 600, 600, 600, 600, 600, 600, 600, 600,
2122 600, 600, 600, 600, 600, 600, 600, 600,
2123 600, 600, 600, 600, 600, 600, 600, 600,
2124 600, 600, 600, 600, 600, 600, 600, 600,
2125 600, 600, 600, 600, 600, 600, 600, 600,
2126 600, 600, 600, 600, 600, 600, 600, 600,
2127 600, 600, 600, 600, 600, 600, 600, 600,
2128 600, 600, 600, 600, 600, 600, 600, 600,
2129 600, 600, 600, 600, 600, 600, 600, 600,
2130 600, 600, 600, 600, 600, 600, 600, 600,
2131 600, 600, 600, 600, 600, 600, 600, 0,
2132 0, 0, 0, 0, 0, 0, 0, 0,
2133 0, 0, 0, 0, 0, 0, 0, 0,
2134 0, 0, 0, 0, 0, 0, 0, 0,
2135 0, 0, 0, 0, 0, 0, 0, 0,
2136 0, 600, 600, 600, 600, 600, 600, 600,
2137 600, 600, 600, 600, 600, 600, 600, 600,
2138 0, 600, 600, 600, 600, 0, 600, 600,
2139 600, 600, 600, 600, 600, 600, 0, 600,
2140 0, 600, 600, 600, 600, 600, 600, 600,
2141 600, 0, 600, 600, 0, 600, 600, 600,
2142 600, 0, 0, 0, 0, 0, 0, 0,
2143 0, 0, 0, 0, 0, 0, 0, 0,
2144 0, 600, 0, 600, 0, 0, 0, 0,
2145 600, 600, 600, 600, 0, 0, 0, 0,
2146 0, 600, 0, 0, 0, 600, 0, 0,
2147 600, 600, 600, 600, 0, 0, 0, 0