3 # Read the source-form of the NASM manual and generate the various
9 # - show page numbers in printed output
10 # - think about double-sided support (start all chapters on RHS,
11 # ie odd-numbered, pages).
13 # Ellipsis support would be nice.
15 # Source-form features:
16 # ---------------------
19 # Bullets the paragraph. Rest of paragraph is indented to cope. In
20 # HTML, consecutive groups of bulleted paragraphs become unordered
24 # produces `_foobar_' in text and italics in HTML, PS, RTF
26 # Inline code \c{foobar}
27 # produces ``foobar'' in text, and fixed-pitch font in HTML, PS, RTF
32 # produces fixed-pitch font where appropriate, and doesn't break
33 # pages except sufficiently far into the middle of a display.
35 # Chapter, header and subheader
36 # \C{intro} Introduction
37 # \H{whatsnasm} What is NASM?
38 # \S{free} NASM Is Free
39 # dealt with as appropriate. Chapters begin on new sides, possibly
40 # even new _pages_. (Sub)?headers are good places to begin new
41 # pages. Just _after_ a (sub)?header isn't.
42 # The keywords can be substituted with \K and \k.
44 # Keyword \K{cintro} \k{cintro}
45 # Expands to `Chapter 1', `Section 1.1', `Section 1.1.1'. \K has an
46 # initial capital whereas \k doesn't. In HTML, will produce
49 # Web link \W{http://foobar/}{text} or \W{mailto:me@here}\c{me@here}
50 # the \W prefix is ignored except in HTML; in HTML the last part
51 # becomes a hyperlink to the first part.
54 # In case it's necessary, they expand to the real versions.
56 # Nonbreaking hyphen \-
60 # Causes everything after it on the line to be ignored by the
61 # source-form processor.
63 # Indexable word \i{foobar} (or \i\e{foobar} or \i\c{foobar}, equally)
64 # makes word appear in index, referenced to that point
65 # \i\c comes up in code style even in the index; \i\e doesn't come
66 # up in emphasised style.
68 # Indexable non-displayed word \I{foobar} or \I\c{foobar}
69 # just as \i{foobar} except that nothing is displayed for it
72 # \IR{foobar} \c{foobar} operator, uses of
73 # tidies up the appearance in the index of something the \i or \I
74 # operator was applied to
77 # \IA{foobar}{bazquux}
78 # aliases one index tag (as might be supplied to \i or \I) to
79 # another, so that \I{foobar} has the effect of \I{bazquux}, and
80 # \i{foobar} has the effect of \I{bazquux}foobar
82 $diag = 1, shift @ARGV if $ARGV[0] eq "-d";
86 $tstruct_previtem = $node = "Top";
88 $tstruct_level{$tstruct_previtem} = 0;
89 $tstruct_last[$tstruct_level{$tstruct_previtem}] = $tstruct_previtem;
90 $MAXLEVEL = 10; # really 3, but play safe ;-)
92 # Read the file; pass a paragraph at a time to the paragraph processor.
93 print "Reading input...";
94 $pname = "para000000";
95 @pnames = @pflags = ();
99 if (!/\S/ || /^\\I[AR]/) { # special case: \I[AR] implies new-paragraph
104 s/\\#.*$//; # strip comments
111 # Now we've read in the entire document and we know what all the
112 # heading keywords refer to. Go through and fix up the \k references.
113 print "Fixing up cross-references...";
117 # Sort the index tags, according to the slightly odd order I've decided on.
118 print "Sorting index tags...";
123 print "Writing index-diagnostic file...";
128 # OK. Write out the various output files.
129 print "Producing text output: ";
132 print "Producing HTML output: ";
135 print "Producing PostScript output: ";
138 print "Producing Texinfo output: ";
141 print "Producing WinHelp output: ";
147 my $pflags = "", $i, $w, $l, $t;
152 # Strip off _leading_ spaces, then determine type of paragraph.
156 # A code paragraph. The paragraph-array will contain the simple
157 # strings which form each line of the paragraph.
159 while (/^\\c (([^\\]|\\[^c])*)(.*)$/) {
167 $_ = ''; # suppress word-by-word code
169 # A chapter heading. Define the keyword and allocate a chapter
174 $xref = "chapter-$cnum";
175 $pflags = "chap $cnum :$xref";
176 die "badly formatted chapter heading: $_\n" if !/^\\C{([^}]*)}\s*(.*)$/;
177 $refs{$1} = "chapter $cnum";
178 $node = "Chapter $cnum";
180 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
183 # the standard word-by-word code will happen next
185 # An appendix heading. Define the keyword and allocate an appendix
188 $cnum = 'A' if $cnum =~ /[0-9]+/;
191 $xref = "appendix-$cnum";
192 $pflags = "appn $cnum :$xref";
193 die "badly formatted appendix heading: $_\n" if !/^\\A{([^}]*)}\s*(.*)$/;
194 $refs{$1} = "appendix $cnum";
195 $node = "Appendix $cnum";
197 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
200 # the standard word-by-word code will happen next
202 # A major heading. Define the keyword and allocate a section number.
205 $xref = "section-$cnum.$hnum";
206 $pflags = "head $cnum.$hnum :$xref";
207 die "badly formatted heading: $_\n" if !/^\\[HP]{([^}]*)}\s*(.*)$/;
208 $refs{$1} = "section $cnum.$hnum";
209 $node = "Section $cnum.$hnum";
211 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
214 # the standard word-by-word code will happen next
216 # A sub-heading. Define the keyword and allocate a section number.
218 $xref = "section-$cnum.$hnum.$snum";
219 $pflags = "subh $cnum.$hnum.$snum :$xref";
220 die "badly formatted subheading: $_\n" if !/^\\S{([^}]*)}\s*(.*)$/;
221 $refs{$1} = "section $cnum.$hnum.$snum";
222 $node = "Section $cnum.$hnum.$snum";
224 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
227 # the standard word-by-word code will happen next
230 die "badly formatted index rewrite: $_\n" if !/^\\IR{([^}]*)}\s*(.*)$/;
233 # the standard word-by-word code will happen next
236 die "badly formatted index alias: $_\n" if !/^\\IA{([^}]*)}{([^}]*)}\s*$/;
238 return; # avoid word-by-word code
240 # A bulleted paragraph. Strip off the initial \b and let the
241 # word-by-word code take care of the rest.
245 # A normal paragraph. Just set $pflags: the word-by-word code does
250 # The word-by-word code: unless @$pname is already defined (which it
251 # will be in the case of a code paragraph), split the paragraph up
252 # into words and push each on @$pname.
254 # Each thing pushed on @$pname should have a two-character type
255 # code followed by the text.
260 # "es" for first emphasised word in emphasised bit
261 # "e " for emphasised in mid-emphasised-bit
262 # "ee" for last emphasised word in emphasised bit
263 # "eo" for single (only) emphasised word
266 # "kK" for capitalised cross-ref
268 # "wc" for code-type Web link
269 # "x " for beginning of resolved cross-ref; generates no visible output,
270 # and the text is the cross-reference code
271 # "xe" for end of resolved cross-ref; text is same as for "x ".
272 # "i " for point to be indexed: the text is the internal index into the
276 s/^\s*//, push @
$pname, "sp" if /^\s/;
277 $indexing = $qindex = 0;
278 if (/^(\\[iI])?\\c/) {
279 $qindex = 1 if $1 eq "\\I";
280 $indexing = 1, s/^\\[iI]// if $1;
282 die "badly formatted \\c: \\c$_\n" if !/{(([^\\}]|\\.)*)}(.*)$/;
289 (push @
$pname,"i"),$lastp = $#$pname if $indexing;
290 push @
$pname,"c $w" if !$qindex;
291 $$pname[$lastp] = &addidx
($node, $w, "c $w") if $indexing;
292 } elsif (/^\\[iIe]/) {
295 $qindex = 1 if $1 eq "\\I";
296 $indexing = 1, $type = "\\i" if $1;
297 $emph = 1, $type = "\\e" if $2;
298 s/^(\\[iI])?(\\e?)//;
299 die "badly formatted $type: $type$_\n" if !/{(([^\\}]|\\.)*)}(.*)$/;
306 $t = $emph ?
"es" : "n ";
308 (push @
$pname,"i"),$lastp = $#$pname if $indexing;
309 foreach $i (split /\s+/,$w) { # \e and \i can be multiple words
310 push @
$pname,"$t$i","sp" if !$qindex;
311 ($ii=$i) =~ tr/A-Z/a-z/, push @ientry,"n $ii","sp" if $indexing;
312 $t = $emph ?
"e " : "n ";
314 $w =~ tr/A-Z/a-z/, pop @ientry if $indexing;
315 $$pname[$lastp] = &addidx
($node, $w, @ientry) if $indexing;
316 pop @
$pname if !$qindex; # remove final space
317 if (substr($$pname[$#$pname],0,2) eq "es" && !$qindex) {
318 substr($$pname[$#$pname],0,2) = "eo";
319 } elsif ($emph && !$qindex) {
320 substr($$pname[$#$pname],0,2) = "ee";
322 } elsif (/^\\[kK]/) {
326 die "badly formatted \\k: \\c$_\n" if !/{([^}]*)}(.*)$/;
331 die "badly formatted \\W: \\W$_\n"
332 if !/{([^}]*)}(\\i)?(\\c)?{(([^\\}]|\\.)*)}(.*)$/;
337 $t = "wc" if $3 eq "\\c";
343 (push @
$pname,"i"),$lastp = $#$pname if $indexing;
344 push @
$pname,"$t<$l>$w";
345 $$pname[$lastp] = &addidx
($node, $w, "c $w") if $indexing;
347 die "what the hell? $_\n" if !/^(([^\s\\\-]|\\[\\{}\-])*-?)(.*)$/;
348 die "painful death! $_\n" if !length $1;
362 if ($irewrite ne undef) {
363 &addidx
(undef, $irewrite, @
$pname);
366 push @pnames, $pname;
367 push @pflags, $pflags;
373 my ($node, $text, @ientry) = @_;
374 $text = $idxalias{$text} || $text;
375 if ($node eq undef || !$idxmap{$text}) {
377 $idxmap{$text} = $ientry;
381 $idxnodes{$node,$text} = 1;
387 my $iitem, $ientry, $i, $piitem, $pcval, $cval, $clrcval;
389 @itags = map { # get back the original data as the 1st elt of each list
391 } sort { # compare auxiliary (non-first) elements of lists
392 $a->[1] cmp $b->[1] ||
393 $a->[2] cmp $b->[2] ||
395 } map { # transform array into list of 3-element lists
396 my $ientry = $idxmap{$_};
397 my $a = substr($$ientry[0],2);
399 [$_, uc($a), substr($$ientry[0],0,2)]
402 # Having done that, check for comma-hood.
404 foreach $iitem (@itags) {
405 $ientry = $idxmap{$iitem};
408 FL
:for ($i=0; $i <= $#$ientry; $i++) {
409 if ($$ientry[$i] =~ /^(n .*,)(.*)/) {
411 splice @
$ientry,$i+1,0,"n $2" if length $2;
412 $commapos{$iitem} = $i+1;
413 $cval = join("\002", @
$ientry[0..$i]);
418 $cval = undef if $clrcval;
419 $commanext{$iitem} = $commaafter{$piitem} = 1
420 if $cval and ($cval eq $pcval);
426 my $iitem,$ientry,$w,$ww,$foo,$node;
427 open INDEXDIAG
,">index.diag";
428 foreach $iitem (@itags) {
429 $ientry = $idxmap{$iitem};
430 print INDEXDIAG
"<$iitem> ";
431 foreach $w (@
$ientry) {
433 print INDEXDIAG
$ww unless $ww eq "\001";
437 foreach $node (@nodes) {
438 (print INDEXDIAG
$foo,$node), $foo = ", " if $idxnodes{$node,$iitem};
440 print INDEXDIAG
"\n";
446 my $pname, $p, $i, $j, $k, $caps, @repl;
448 for ($p=0; $p<=$#pnames; $p++) {
449 next if $pflags[$p] eq "code";
450 $pname = $pnames[$p];
451 for ($i=$#$pname; $i >= 0; $i--) {
452 if ($$pname[$i] =~ /^k/) {
454 $caps = ($k =~ /^kK/);
457 die "undefined keyword `$k'\n" unless $repl;
458 substr($repl,0,1) =~ tr/a-z/A-Z/ if $caps;
460 push @repl,"x $xrefs{$k}";
461 foreach $j (split /\s+/,$repl) {
465 pop @repl; # remove final space
466 push @repl,"xe$xrefs{$k}";
467 splice @
$pname,$i,1,@repl;
474 # This is called from the top level, so I won't bother using
478 print "writing file...";
479 open TEXT
,">nasmdoc.txt";
483 $title = "The Netwide Assembler: NASM";
484 $spaces = ' ' x
((75-(length $title))/2);
485 ($underscore = $title) =~ s/./=/g;
486 print "$spaces$title\n$spaces$underscore\n";
488 for ($para = 0; $para <= $#pnames; $para++) {
489 $pname = $pnames[$para];
490 $pflags = $pflags[$para];
491 $ptype = substr($pflags,0,4);
493 print "\n"; # always one of these before a new paragraph
495 if ($ptype eq "chap") {
496 # Chapter heading. "Chapter N: Title" followed by a line of
498 $pflags =~ /chap (.*) :(.*)/;
499 $title = "Chapter $1: ";
500 foreach $i (@
$pname) {
502 $title .= $ww unless $ww eq "\001";
507 } elsif ($ptype eq "appn") {
508 # Appendix heading. "Appendix N: Title" followed by a line of
510 $pflags =~ /appn (.*) :(.*)/;
511 $title = "Appendix $1: ";
512 foreach $i (@
$pname) {
514 $title .= $ww unless $ww eq "\001";
519 } elsif ($ptype eq "head" || $ptype eq "subh") {
520 # Heading or subheading. Just a number and some text.
521 $pflags =~ /.... (.*) :(.*)/;
522 $title = sprintf "%6s ", $1;
523 foreach $i (@
$pname) {
525 $title .= $ww unless $ww eq "\001";
528 } elsif ($ptype eq "code") {
529 # Code paragraph. Emit each line with a seven character indent.
530 foreach $i (@
$pname) {
531 warn "code line longer than 68 chars: $i\n" if length $i > 68;
532 print ' 'x7
, $i, "\n";
534 } elsif ($ptype eq "bull" || $ptype eq "norm") {
535 # Ordinary paragraph, optionally bulleted. We wrap, with ragged
536 # 75-char right margin and either 7 or 11 char left margin
537 # depending on bullets.
538 if ($ptype eq "bull") {
539 $line = ' 'x7
. '(*) ';
542 $line = $next = ' 'x7
;
547 do { $w = &word_txt
(shift @a) } while $w eq "\001"; # nasty hack
549 if ($wprev =~ /-$/ || $w eq ' ' || $w eq '' || $w eq undef) {
550 if (length ($line . $wd) > 75) {
551 $line =~ s/\s*$//; # trim trailing spaces
554 $wd =~ s/^\s*//; # trim leading spaces
560 } while ($w ne '' && $w ne undef);
562 $line =~ s/\s*$//; # trim trailing spaces
577 return undef if $w eq '' || $w eq undef;
578 $wtype = substr($w,0,2);
579 $wmajt = substr($wtype,0,1);
581 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
582 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
584 } elsif ($wtype eq "sp") {
586 } elsif ($wtype eq "da") {
588 } elsif ($wmajt eq "c" || $wtype eq "wc") {
590 } elsif ($wtype eq "es") {
592 } elsif ($wtype eq "ee") {
594 } elsif ($wtype eq "eo") {
596 } elsif ($wmajt eq "x" || $wmajt eq "i") {
599 die "panic in word_txt: $wtype$w\n";
604 # This is called from the top level, so I won't bother using
607 # Write contents file. Just the preamble, then a menu of links to the
608 # separate chapter files and the nodes therein.
609 print "writing contents file...";
610 open TEXT
,">nasmdoc0.html";
613 print "<p>This manual documents NASM, the Netwide Assembler: an assembler\n";
614 print "targetting the Intel x86 series of processors, with portable source.\n";
616 for ($node = $tstruct_next{'Top'}; $node; $node = $tstruct_next{$node}) {
617 if ($tstruct_level{$node} == 1) {
618 # Invent a file name.
619 ($number = lc($xrefnodes{$node})) =~ s/.*-//;
620 $fname="nasmdocx.html";
621 substr($fname,8 - length $number, length $number) = $number;
622 $html_fnames{$node} = $fname;
626 # Use the preceding filename plus a marker point.
627 $link = $fname . "#$xrefnodes{$node}";
630 $pname = $tstruct_pname{$node};
631 foreach $i (@
$pname) {
632 $ww = &word_html
($i);
633 $title .= $ww unless $ww eq "\001";
635 print "<a href=\"$link\">$title</a><br>\n";
637 print "<p><a href=\"nasmdoci.html\">Index</a>\n";
638 print "</body></html>\n";
642 # Open a null file, to ensure output (eg random &html_jumppoints calls)
644 print "writing chapter files...";
645 open TEXT
,">/dev/null";
651 for ($para = 0; $para <= $#pnames; $para++) {
652 $pname = $pnames[$para];
653 $pflags = $pflags[$para];
654 $ptype = substr($pflags,0,4);
656 $in_list = 0, print "</ul>\n" if $in_list && $ptype ne "bull";
657 if ($ptype eq "chap") {
658 # Chapter heading. Begin a new file.
659 $pflags =~ /chap (.*) :(.*)/;
660 $title = "Chapter $1: ";
662 &html_jumppoints
; print "</body></html>\n"; select STDOUT
; close TEXT
;
663 $html_lastf = $html_fnames{$chapternode};
664 $chapternode = $nodexrefs{$xref};
665 $html_nextf = $html_fnames{$tstruct_mnext{$chapternode}};
666 open TEXT
,">$html_fnames{$chapternode}"; select TEXT
; &html_preamble
(1);
667 foreach $i (@
$pname) {
668 $ww = &word_html
($i);
669 $title .= $ww unless $ww eq "\001";
671 $h = "<h2><a name=\"$xref\">$title</a></h2>\n";
672 print $h; print FULL
$h;
673 } elsif ($ptype eq "appn") {
674 # Appendix heading. Begin a new file.
675 $pflags =~ /appn (.*) :(.*)/;
676 $title = "Appendix $1: ";
678 &html_jumppoints
; print "</body></html>\n"; select STDOUT
; close TEXT
;
679 $html_lastf = $html_fnames{$chapternode};
680 $chapternode = $nodexrefs{$xref};
681 $html_nextf = $html_fnames{$tstruct_mnext{$chapternode}};
682 open TEXT
,">$html_fnames{$chapternode}"; select TEXT
; &html_preamble
(1);
683 foreach $i (@
$pname) {
684 $ww = &word_html
($i);
685 $title .= $ww unless $ww eq "\001";
687 print "<h2><a name=\"$xref\">$title</a></h2>\n";
688 } elsif ($ptype eq "head" || $ptype eq "subh") {
689 # Heading or subheading.
690 $pflags =~ /.... (.*) :(.*)/;
691 $hdr = ($ptype eq "subh" ?
"h4" : "h3");
694 foreach $i (@
$pname) {
695 $ww = &word_html
($i);
696 $title .= $ww unless $ww eq "\001";
698 print "<$hdr><a name=\"$xref\">$title</a></$hdr>\n";
699 } elsif ($ptype eq "code") {
702 foreach $i (@
$pname) {
710 } elsif ($ptype eq "bull" || $ptype eq "norm") {
711 # Ordinary paragraph, optionally bulleted. We wrap, with ragged
712 # 75-char right margin and either 7 or 11 char left margin
713 # depending on bullets.
714 if ($ptype eq "bull") {
715 $in_list = 1, print "<ul>\n" unless $in_list;
723 do { $w = &word_html
(shift @a) } while $w eq "\001"; # nasty hack
725 if ($w eq ' ' || $w eq '' || $w eq undef) {
726 if (length ($line . $wd) > 75) {
727 $line =~ s/\s*$//; # trim trailing spaces
730 $wd =~ s/^\s*//; # trim leading spaces
736 } while ($w ne '' && $w ne undef);
738 $line =~ s/\s*$//; # trim trailing spaces
744 # Close whichever file was open.
746 print "</body></html>\n";
750 print "\n writing index file...";
751 open TEXT
,">nasmdoci.html";
754 print "<p align=center><a href=\"nasmdoc0.html\">Contents</a>\n";
757 print "<p align=center><a href=\"nasmdoc0.html\">Contents</a>\n";
758 print "</body></html>\n";
764 print "<html><head><title>NASM Manual</title></head>\n";
765 print "<body><h1 align=center>The Netwide Assembler: NASM</h1>\n\n";
766 &html_jumppoints
if $_[0];
769 sub html_jumppoints
{
770 print "<p align=center>";
771 print "<a href=\"$html_nextf\">Next Chapter</a> |\n" if $html_nextf;
772 print "<a href=\"$html_lastf\">Previous Chapter</a> |\n" if $html_lastf;
773 print "<a href=\"nasmdoc0.html\">Contents</a> |\n";
774 print "<a href=\"nasmdoci.html\">Index</a>\n";
778 my $itag, $a, @ientry, $sep, $w, $wd, $wprev, $line;
781 foreach $itag (@itags) {
782 $ientry = $idxmap{$itag};
786 foreach $node (@nodes) {
787 next if !$idxnodes{$node,$itag};
788 push @a, "n ," if $sep;
789 push @a, "sp", "x $xrefnodes{$node}", "n $node", "xe$xrefnodes{$node}";
794 do { $w = &word_html
(shift @a) } while $w eq "\001"; # nasty hack
796 if ($w eq ' ' || $w eq '' || $w eq undef) {
797 if (length ($line . $wd) > 75) {
798 $line =~ s/\s*$//; # trim trailing spaces
801 $wd =~ s/^\s*//; # trim leading spaces
807 } while ($w ne '' && $w ne undef);
809 $line =~ s/\s*$//; # trim trailing spaces
818 my $wtype, $wmajt, $pfx, $sfx;
820 return undef if $w eq '' || $w eq undef;
822 $wtype = substr($w,0,2);
823 $wmajt = substr($wtype,0,1);
826 $pfx = "<a href=\"$1\">", $sfx = "</a>", $w = $2
827 if $wmajt eq "w" && $w =~ /^<(.*)>(.*)$/;
831 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
832 return $pfx . $w . $sfx;
833 } elsif ($wtype eq "sp") {
835 } elsif ($wtype eq "da") {
836 return '-'; # sadly, en-dashes are non-standard in HTML
837 } elsif ($wmajt eq "c" || $wtype eq "wc") {
838 return $pfx . "<code><nobr>${w}</nobr></code>" . $sfx;
839 } elsif ($wtype eq "es") {
841 } elsif ($wtype eq "ee") {
843 } elsif ($wtype eq "eo") {
844 return "<em>${w}</em>";
845 } elsif ($wtype eq "x ") {
846 # Magic: we must resolve the cross reference into file and marker
847 # parts, then dispose of the file part if it's us, and dispose of
848 # the marker part if the cross reference describes the top node of
850 my $node = $nodexrefs{$w}; # find the node we're aiming at
851 my $level = $tstruct_level{$node}; # and its level
852 my $up = $node, $uplev = $level-1;
853 $up = $tstruct_up{$up} while $uplev--; # get top node of containing file
854 my $file = ($up ne $chapternode) ?
$html_fnames{$up} : "";
855 my $marker = ($level == 1 and $file) ?
"" : "#$w";
856 return "<a href=\"$file$marker\">";
857 } elsif ($wtype eq "xe") {
859 } elsif ($wmajt eq "i") {
862 die "panic in word_html: $wtype$w\n";
867 # This is called from the top level, so I won't bother using
870 # First, set up the font metric arrays.
873 # First stage: reprocess the source arrays into a list of
874 # lines, each of which is a list of word-strings, each of
875 # which has a single-letter font code followed by text.
876 # Each line also has an associated type, which will be
877 # used for final alignment and font selection and things.
883 # ' ' == space (no following text required)
884 # '-' == dash (no following text required)
887 # chap == Chapter or appendix heading.
888 # head == Major heading.
889 # subh == Sub-heading.
890 # Ccha == Contents entry for a chapter.
891 # Chea == Contents entry for a heading.
892 # Csub == Contents entry for a subheading.
893 # cone == Code paragraph with just this one line on it.
894 # cbeg == First line of multi-line code paragraph.
895 # cbdy == Interior line of multi-line code paragraph.
896 # cend == Final line of multi-line code paragraph.
897 # none == Normal paragraph with just this one line on it.
898 # nbeg == First line of multi-line normal paragraph.
899 # nbdy == Interior line of multi-line normal paragraph.
900 # nend == Final line of multi-line normal paragraph.
901 # bone == Bulleted paragraph with just this one line on it.
902 # bbeg == First line of multi-line bulleted paragraph.
903 # bbdy == Interior line of multi-line bulleted paragraph.
904 # bend == Final line of multi-line bulleted paragraph.
905 print "line-breaks...";
906 $lname = "psline000000";
907 $lnamei = "idx" . $lname;
908 @lnames = @ltypes = ();
910 for ($para = 0; $para <= $#pnames; $para++) {
911 $pname = $pnames[$para];
912 $pflags = $pflags[$para];
913 $ptype = substr($pflags,0,4);
915 # New paragraph _ergo_ new line.
917 @lindex = (); # list of index tags referenced to this line
919 if ($ptype eq "chap") {
920 # Chapter heading. "Chapter N: Title" followed by a line of
922 $pflags =~ /chap (.*) :(.*)/;
923 push @line, "nChapter", " ", "n$1:", " ";
924 foreach $i (@
$pname) {
926 push @line, $ww unless $ww eq "x";
928 @
$lname = @line; @
$lnamei = @lindex;
929 push @lnames, $lname++;
930 $lnamei = "idx" . $lname;
931 push @ltypes, "chap";
932 } elsif ($ptype eq "appn") {
933 # Appendix heading. "Appendix N: Title" followed by a line of
935 $pflags =~ /appn (.*) :(.*)/;
936 push @line, "nAppendix", " ", "n$1:", " ";
937 foreach $i (@
$pname) {
939 push @line, $ww unless $ww eq "x";
941 @
$lname = @line; @
$lnamei = @lindex;
942 push @lnames, $lname++;
943 $lnamei = "idx" . $lname;
944 push @ltypes, "chap";
945 } elsif ($ptype eq "head") {
946 # Heading. Just a number and some text.
947 $pflags =~ /.... (.*) :(.*)/;
949 foreach $i (@
$pname) {
951 push @line, $ww unless $ww eq "x";
953 @
$lname = @line; @
$lnamei = @lindex;
954 push @lnames, $lname++;
955 $lnamei = "idx" . $lname;
956 push @ltypes, $ptype;
957 } elsif ($ptype eq "subh") {
958 # Subheading. Just a number and some text.
959 $pflags =~ /subh (.*) :(.*)/;
961 foreach $i (@
$pname) {
962 push @line, &word_ps
($i);
964 @
$lname = @line; @
$lnamei = @lindex;
965 push @lnames, $lname++;
966 $lnamei = "idx" . $lname;
967 push @ltypes, "subh";
968 } elsif ($ptype eq "code") {
969 # Code paragraph. Emit lines one at a time.
971 foreach $i (@
$pname) {
973 push @lnames, $lname++;
974 $lnamei = "idx" . $lname;
978 $ltypes[$#ltypes] = ($ltypes[$#ltypes] eq "cbeg" ?
"cone" : "cend");
979 } elsif ($ptype eq "bull" || $ptype eq "norm") {
980 # Ordinary paragraph, optionally bulleted. We wrap, with ragged
981 # 75-char right margin and either 7 or 11 char left margin
982 # depending on bullets.
983 if ($ptype eq "bull") {
984 $width = 456; # leave 12-pt left indent for the bullet
985 $type = $begtype = "bbeg";
991 $type = $begtype = "nbeg";
1001 do { $w = &word_ps
(shift @a) } while ($w eq "x");
1002 push @wd, $wprev if $wprev;
1003 if ($wprev =~ /^n.*-$/ || $w eq ' ' || $w eq '' || $w eq undef) {
1004 $wdlen = &len_ps
(@wd);
1005 if ($linelen + $wdlen > $width) {
1006 pop @line while $line[$#line] eq ' '; # trim trailing spaces
1007 @
$lname = @line; @
$lnamei = @lindex;
1008 push @lnames, $lname++;
1009 $lnamei = "idx" . $lname;
1010 push @ltypes, $type;
1012 @line = @lindex = ();
1014 shift @wd while $wd[0] eq ' '; # trim leading spaces
1021 } while ($w ne '' && $w ne undef);
1023 pop @line while $line[$#line] eq ' '; # trim trailing spaces
1024 @
$lname = @line; @
$lnamei = @lindex;
1025 push @lnames, $lname++;
1026 $lnamei = "idx" . $lname;
1027 push @ltypes, $type;
1031 ($ltypes[$#ltypes] eq $begtype ?
$onetype : $endtype);
1035 # We've now processed the document source into lines. Before we
1036 # go on and do the page breaking, we'll fabricate a table of contents,
1037 # line by line, and then after doing page breaks we'll go back and
1038 # insert the page numbers into the contents entries.
1039 print "building contents...";
1040 @clnames = @cltypes = ();
1041 $clname = "pscont000000";
1042 @
$clname = ("nContents"); # "chapter heading" for TOC
1043 push @clnames,$clname++;
1044 push @cltypes,"chap";
1045 for ($i=0; $i<=$#lnames; $i++) {
1046 $lname = $lnames[$i];
1047 if ($ltypes[$i] =~ /^(chap|head|subh)/) {
1049 splice @
$clname,1,0," " if ($ltypes[$i] !~ /chap/);
1050 push @
$clname,$i; # placeholder for page number
1051 push @clnames,$clname++;
1052 push @cltypes,"C" . substr($ltypes[$i],0,3);
1055 @
$clname = ("nIndex"); # contents entry for Index
1056 push @
$clname,$i; # placeholder for page number
1057 $idx_clname = $clname;
1058 push @clnames,$clname++;
1059 push @cltypes,"Ccha";
1060 $contlen = $#clnames + 1;
1061 unshift @lnames,@clnames;
1062 unshift @ltypes,@cltypes;
1064 # Second stage: now we have a list of lines, break them into pages.
1065 # We do this by means of adding a third array in parallel with
1066 # @lnames and @ltypes, called @lpages, in which we store the page
1067 # number that each line resides on. We also add @ycoord which
1068 # stores the vertical position of each line on the page.
1070 # Page breaks may not come after line-types:
1071 # chap head subh cbeg nbeg bbeg
1072 # and may not come before line-types:
1074 # They are forced before line-types:
1076 print "page-breaks...";
1077 $pmax = 600; # ADJUSTABLE: maximum length of a page in points
1078 $textht = 11; # ADJUSTABLE: height of a normal line in points
1079 $spacing = 6; # ADJUSTABLE: space between paragraphs, in points
1080 $headht = 14; # ADJUSTABLE: height of a major heading in points
1081 $subht = 12; # ADJUSTABLE: height of a sub-heading in points
1082 $pstart = 0; # start line of current page
1083 $plen = 0; # current length of current page
1084 $pnum = 1; # number of current page
1085 $bpt = -1; # last feasible break point
1086 $i = 0; # line number
1087 while ($i <= $#lnames) {
1088 $lname = $lnames[$i];
1089 # Add the height of this line (computed the last time we went round
1090 # the loop, unless we're a chapter heading in which case we do it
1091 # now) to the length of the current page. Also, _put_ this line on
1092 # the current page, and allocate it a y-coordinate.
1093 if ($ltypes[$i] =~ /^chap$/) {
1094 $plen = 100; # ADJUSTABLE: space taken up by a chapter heading
1095 $ycoord[$i] = 0; # chapter heading: y-coord doesn't matter
1097 $ycoord[$i] = $plen + $space;
1098 $plen += $space + $ht;
1100 # See if we can break after this line.
1101 $bpt = $i if $ltypes[$i] !~ /^chap|head|subh|cbeg|nbeg|bbeg$/ &&
1102 $ltypes[$i+1] !~ /^cend|nend|bend$/;
1103 # Assume, to start with, that we don't break after this line.
1105 # See if a break is forced.
1106 $break = 1, $bpt = $i if $ltypes[$i+1] eq "chap" || !$ltypes[$i+1];
1107 # Otherwise, compute the height of the next line, and break if
1108 # it would make this page too long.
1109 $ht = $textht, $space = 0 if $ltypes[$i+1] =~ /^[nbc](bdy|end)$/;
1110 $ht = $textht, $space = $spacing if $ltypes[$i+1] =~ /^[nbc](one|beg)$/;
1111 $ht = $textht, $space = $spacing if $ltypes[$i+1] =~ /^C/;
1112 $ht = $subht, $space = $spacing if $ltypes[$i+1] eq "subh";
1113 $ht = $headht, $space = $spacing if $ltypes[$i+1] eq "head";
1114 $break = 1 if $plen + $space + $ht > $pmax;
1115 # Now, if we're breaking, assign page number $pnum to all lines up
1116 # to $bpt, set $i == $bpt+1, and zero $space since we are at the
1117 # start of a new page and don't want leading space.
1119 die "no feasible break point at all on page $pnum\n" if $bpt == -1;
1120 for ($j = $pstart; $j <= $bpt; $j++) {
1121 $lnamei = "idx" . $lnames[$j];
1122 foreach $k (@
$lnamei) {
1123 ${$psidxpp{$k}}{$pnum} = 1;
1125 $lpages[$j] = $pnum;
1137 # Now fix up the TOC with page numbers.
1138 print "\n fixing up contents...";
1139 for ($i=0; $i<=$#lnames; $i++) {
1140 $lname = $lnames[$i];
1141 if ($ltypes[$i] =~ /^C/) {
1143 push @
$lname, "n" . $lpages[$j+$contlen];
1147 # Having got page numbers for most stuff, generate an index.
1148 print "building index...";
1152 foreach $k (@itags) {
1155 @idxentry = @
{$idxmap{$k}};
1156 if ($commaafter{$k} and !$commanext{$k}) {
1157 # This line is a null line beginning a multiple entry. We must
1158 # output the prefix on a line by itself.
1160 @idxhead = splice @idxentry,0,$commapos{$k};
1162 foreach $i (@idxhead) {
1164 push @line, $ww unless $ww eq "x";
1166 &ps_idxout
("index",\
@line,[]);
1170 $cmd = "iindex", splice @idxentry,0,$commapos{$k} if $commanext{$k};
1171 foreach $i (@idxentry) {
1173 push @line, $ww unless $ww eq "x";
1175 $len = $iwid - $sep - &len_ps
(@line);
1176 warn "text for index tag `%s' is longer than one index line!\n"
1179 $inums = join(',',sort { $a <=> $b } keys %{$psidxpp{$k}});
1180 while (length $inums) {
1181 $inums =~ /^([^,]+,?)(.*)$/;
1182 $inums = $2, $inum = $1;
1183 @pnum = (" ", "n$inum");
1184 $pnumlen = &len_ps
(@pnum);
1185 if ($pnumlen > $len) {
1186 &ps_idxout
($cmd,\
@line,\
@pp);
1190 $len = $iwid - $sep;
1195 &ps_idxout
($cmd,\
@line,\
@pp) if (length @pp);
1196 $l1 = &len_ps
(@line);
1199 $$idx_clname[$#$idx_clname] = "n" . $pnum; # fix up TOC entry for index
1201 print "writing file...";
1202 open PS
,">nasmdoc.ps";
1206 for ($i=0; $i<=$#lnames; $i++) {
1207 &ps_throw_pg
($page,$lpages[$i]) if $page != $lpages[$i];
1208 $page = $lpages[$i];
1209 &ps_out_line
($ycoord[$i],$ltypes[$i],$lnames[$i]);
1212 while ($i <= $#psindex) {
1213 &ps_throw_pg
($page, $pnum) if $page != $pnum;
1216 $ypos = 100, &ps_out_line
(0, "chap", ["nIndex"]) if !$i;
1217 $lines = ($pmax - $ypos) / $textht;
1218 my $col; # ps_out_line hits this variable
1219 PAGE
:for ($col = 1; $col <= 2; $col++) {
1220 $y = $ypos; $l = $lines;
1221 COL
: while ($l > 0) {
1223 $j++ while $psindex[$j] and ($psindex[$j][3] == 0); # find next break
1224 last COL
if $j-$i > $l or $i > $#psindex;
1226 &ps_out_line
($y, $psindex[$i][0] eq "index" ?
"idl$col" : "ldl$col",
1228 &ps_out_line
($y,"idr$col",$psindex[$i][2]);
1234 last PAGE
if $i > $#psindex;
1243 my ($cmd, $left, $right) = @_;
1246 if ($#psindex >= 0) and ( ($#$left < 0) or ($cmd eq "iindex") );
1247 push @psindex,[$cmd,[@
$left],[@
$right],$break];
1252 '/sp (n ) def', # here it's sure not to get wrapped inside ()
1253 '/nf /Times-Roman findfont 11 scalefont def',
1254 '/ef /Times-Italic findfont 11 scalefont def',
1255 '/cf /Courier findfont 11 scalefont def',
1256 '/nc /Helvetica-Bold findfont 18 scalefont def',
1257 '/ec /Helvetica-Oblique findfont 18 scalefont def',
1258 '/cc /Courier-Bold findfont 18 scalefont def',
1259 '/nh /Helvetica-Bold findfont 14 scalefont def',
1260 '/eh /Helvetica-Oblique findfont 14 scalefont def',
1261 '/ch /Courier-Bold findfont 14 scalefont def',
1262 '/ns /Helvetica-Bold findfont 12 scalefont def',
1263 '/es /Helvetica-Oblique findfont 12 scalefont def',
1264 '/cs /Courier-Bold findfont 12 scalefont def',
1265 '/n 16#6E def /e 16#65 def /c 16#63 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]);
1387 print "%%Trailer\nrestore\n%%EOF\n";
1391 my ($oldpg, $newpg) = @_;
1398 print "%%Page: $pgnum $pgnum\n";
1399 print "%%BeginPageSetup\nsave\n%%EndPageSetup\n";
1403 print "%%PageTrailer\nrestore showpage\n";
1407 my ($ypos,$ltype,$lname) = @_;
1412 foreach $c (@
$lname) {#
1413 $c= "n " if $c eq " ";
1414 $c = "n\261" if $c eq "-";
1417 $d .= $1, $c = $2 while $c =~ /^([ -'\*-\[\]-~]+)(.*)$/;
1419 $d .= "\\$1", $c = $2, next if $c =~ /^([\\\(\)])(.*)$/;
1420 ($d .= sprintf "\\%3o",unpack("C",$1)), $c = $2, next
1421 if $c =~ /^([^ -~])(.*)$/;
1426 $col = 0, print "\n" if $col>0 && $col+length $d > 77;
1430 print "\n" if $col > 60;
1432 if ($ltype =~ /^[nb](beg|bdy)$/) {
1433 printf "%d %s%d just\n",
1434 $ypos, ($ltype eq "bbeg" ?
"bullet " : ""),
1435 ($ltype =~ /^b/ ?
456 : 468);
1436 } elsif ($ltype =~ /^[nb](one|end)$/) {
1437 printf "%d %s%d left\n",
1438 $ypos, ($ltype eq "bone" ?
"bullet " : ""),
1439 ($ltype =~ /^b/ ?
456 : 468);
1440 } elsif ($ltype =~ /^c(one|beg|bdy|end)$/) {
1441 printf "$ypos 468 left\n";
1442 } elsif ($ltype =~ /^C/) {
1444 $wid = 456 if $ltype eq "Chea";
1445 $wid = 444 if $ltype eq "Csub";
1446 printf "$ypos $wid contents\n";
1447 } elsif ($ltype eq "chap") {
1449 } elsif ($ltype eq "head") {
1450 printf "$ypos heading\n";
1451 } elsif ($ltype eq "subh") {
1452 printf "$ypos subhead\n";
1453 } elsif ($ltype =~ /([il]d[lr])([12])/) {
1454 $left = ($2 eq "2" ?
468-222 : 0);
1455 printf "$ypos $left $1\n";
1463 return undef if $w eq '' || $w eq undef;
1465 $wtype = substr($w,0,2);
1466 $wmajt = substr($wtype,0,1);
1468 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
1469 if ($wmajt eq "n" || $wtype eq "w ") {
1471 } elsif ($wtype eq "sp") {
1473 } elsif ($wtype eq "da") {
1475 } elsif ($wmajt eq "c" || $wtype eq "wc") {
1477 } elsif ($wmajt eq "e") {
1479 } elsif ($wmajt eq "x") {
1481 } elsif ($wtype eq "i ") {
1485 die "panic in word_ps: $wtype$w\n";
1494 $size = 11/1000; # used only for length calculations
1495 while ($w = shift @line) {
1496 $w = "n " if $w eq " ";
1497 $w = "n\261" if $w eq "-";
1498 $f = substr($w,0,1);
1499 $f = "timesr" if $f eq "n";
1500 $f = "timesi" if $f eq "e";
1501 $f = "courr" if $f eq "c";
1502 foreach $c (unpack 'C*',substr($w,1)) {
1503 $l += $size * $$f[$c];
1510 # This is called from the top level, so I won't bother using
1514 print "writing file...";
1515 open TEXT
,">nasmdoc.texi";
1519 print "\input texinfo \@c -*-texinfo-*-\n";
1520 print "\@c \%**start of header\n";
1521 print "\@setfilename nasm.info\n";
1522 print "\@dircategory Programming\n";
1523 print "\@direntry\n";
1524 print "* NASM: (nasm). The Netwide Assembler for x86.\n";
1525 print "\@end direntry\n";
1526 print "\@settitle NASM: The Netwide Assembler\n";
1527 print "\@setchapternewpage odd\n";
1528 print "\@c \%**end of header\n";
1531 print "This file documents NASM, the Netwide Assembler: an assembler\n";
1532 print "targetting the Intel x86 series of processors, with portable source.\n";
1534 print "Copyright 1997 Simon Tatham\n";
1536 print "All rights reserved. This document is redistributable under the\n";
1537 print "licence given in the file \"Licence\" distributed in the NASM archive.\n";
1538 print "\@end ifinfo\n";
1540 print "\@titlepage\n";
1541 print "\@title NASM: The Netwide Assembler\n";
1542 print "\@author Simon Tatham\n";
1545 print "\@vskip 0pt plus 1filll\n";
1546 print "Copyright \@copyright{} 1997 Simon Tatham\n";
1548 print "All rights reserved. This document is redistributable under the\n";
1549 print "licence given in the file \"Licence\" distributed in the NASM archive.\n";
1550 print "\@end titlepage\n";
1552 print "\@node Top, $tstruct_next{'Top'}, (dir), (dir)\n";
1556 print "This file documents NASM, the Netwide Assembler: an assembler\n";
1557 print "targetting the Intel x86 series of processors, with portable source.\n";
1558 print "\@end ifinfo\n";
1563 for ($para = 0; $para <= $#pnames; $para++) {
1564 $pname = $pnames[$para];
1565 $pflags = $pflags[$para];
1566 $ptype = substr($pflags,0,4);
1568 $bulleting = 0, print "\@end itemize\n" if $bulleting && $ptype ne "bull";
1569 print "\n"; # always one of these before a new paragraph
1571 if ($ptype eq "chap") {
1572 # Chapter heading. Begin a new node.
1574 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1575 $pflags =~ /chap (.*) :(.*)/;
1576 $node = "Chapter $1";
1577 $title = "Chapter $1: ";
1578 foreach $i (@
$pname) {
1579 $ww = &word_texi
($i);
1580 $title .= $ww unless $ww eq "\001";
1582 print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},";
1583 print " $tstruct_up{$node}\n\@unnumbered $title\n";
1584 } elsif ($ptype eq "appn") {
1585 # Appendix heading. Begin a new node.
1587 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1588 $pflags =~ /appn (.*) :(.*)/;
1589 $node = "Appendix $1";
1590 $title = "Appendix $1: ";
1591 foreach $i (@
$pname) {
1592 $ww = &word_texi
($i);
1593 $title .= $ww unless $ww eq "\001";
1595 print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},";
1596 print " $tstruct_up{$node}\n\@unnumbered $title\n";
1597 } elsif ($ptype eq "head" || $ptype eq "subh") {
1598 # Heading or subheading. Begin a new node.
1600 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1601 $pflags =~ /.... (.*) :(.*)/;
1602 $node = "Section $1";
1604 foreach $i (@
$pname) {
1605 $ww = &word_texi
($i);
1606 $title .= $ww unless $ww eq "\001";
1608 print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},";
1609 print " $tstruct_up{$node}\n\@unnumbered $title\n";
1610 } elsif ($ptype eq "code") {
1611 # Code paragraph. Surround with @example / @end example.
1612 print "\@example\n";
1613 foreach $i (@
$pname) {
1614 warn "code line longer than 68 chars: $i\n" if length $i > 68;
1620 print "\@end example\n";
1621 } elsif ($ptype eq "bull" || $ptype eq "norm") {
1622 # Ordinary paragraph, optionally bulleted. We wrap, FWIW.
1623 if ($ptype eq "bull") {
1624 $bulleting = 1, print "\@itemize \@bullet\n" if !$bulleting;
1631 do { $w = &word_texi
(shift @a); } while $w eq "\001"; # hack
1633 if ($wprev =~ /-$/ || $w eq ' ' || $w eq '' || $w eq undef) {
1634 if (length ($line . $wd) > 75) {
1635 $line =~ s/\s*$//; # trim trailing spaces
1638 $wd =~ s/^\s*//; # trim leading spaces
1644 } while ($w ne '' && $w ne undef);
1645 if ($line =~ /\S/) {
1646 $line =~ s/\s*$//; # trim trailing spaces
1656 print "\n\@contents\n\@bye\n";
1661 # Side effect of this procedure: update global `texiwdlen' to be the length
1662 # in chars of the formatted version of the word.
1667 return undef if $w eq '' || $w eq undef;
1668 $wtype = substr($w,0,2);
1669 $wmajt = substr($wtype,0,1);
1675 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
1676 substr($w,0,1) =~ tr/a-z/A-Z/, $capital = 0 if $capital;
1677 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
1680 } elsif ($wtype eq "sp") {
1683 } elsif ($wtype eq "da") {
1686 } elsif ($wmajt eq "c" || $wtype eq "wc") {
1687 $texiwdlen = 2 + $wlen;
1688 return "\@code\{$w\}";
1689 } elsif ($wtype eq "es") {
1690 $texiwdlen = 1 + $wlen;
1691 return "\@emph\{${w}";
1692 } elsif ($wtype eq "ee") {
1693 $texiwdlen = 1 + $wlen;
1695 } elsif ($wtype eq "eo") {
1696 $texiwdlen = 2 + $wlen;
1697 return "\@emph\{${w}\}";
1698 } elsif ($wtype eq "x ") {
1699 $texiwdlen = 0; # we don't need it in this case
1700 $capital = 1; # hack
1702 } elsif ($wtype eq "xe") {
1703 $texiwdlen = 0; # we don't need it in this case
1705 } elsif ($wmajt eq "i") {
1706 $texiwdlen = 0; # we don't need it in this case
1709 die "panic in word_texi: $wtype$w\n";
1715 my $item, $i, $mpname, $title, $wd;
1717 $item = $tstruct_next{$topitem};
1721 $mpname = $tstruct_pname{$item};
1722 foreach $i (@
$mpname) {
1723 $wd = &word_texi
($i);
1724 $title .= $wd unless $wd eq "\001";
1726 print "* ${item}:: $title\n";
1727 $item = $tstruct_mnext{$item};
1729 print "* Index::\n" if $topitem eq "Top";
1730 print "\@end menu\n";
1734 my $itag, $ientry, @a, $wd, $item, $len;
1735 my $subnums = "123456789ABCDEFGHIJKLMNOPQRSTU" .
1736 "VWXYZabcdefghijklmnopqrstuvwxyz";
1738 print "\@ifinfo\n\@node Index, , $FIXMElastnode, Top\n";
1739 print "\@unnumbered Index\n\n\@menu\n";
1741 foreach $itag (@itags) {
1742 $ientry = $idxmap{$itag};
1747 $wd = &word_texi
($i);
1748 $item .= $wd, $len += $texiwdlen unless $wd eq "\001";
1751 foreach $node (@nodes) {
1752 next if !$idxnodes{$node,$itag};
1753 printf "* %s%s (%s): %s.\n",
1754 $item, " " x
(40-$len), substr($subnums,$i++,1), $node;
1757 print "\@end menu\n\@end ifinfo\n";
1761 # This is called from the top level, so I won't bother using
1764 # Build the index-tag text forms.
1765 print "building index entries...";
1768 my $ientry = $idxmap{$_};
1770 foreach $i (@
$ientry) {
1771 $ww = &word_hlp
($i,0);
1772 $title .= $ww unless $ww eq "\001";
1777 # Write the HPJ project-description file.
1778 print "writing .hpj file...";
1779 open HPJ
,">nasmdoc.hpj";
1780 print HPJ
"[OPTIONS]\ncompress=true\n";
1781 print HPJ
"title=NASM: The Netwide Assembler\noldkeyphrase=no\n\n";
1782 print HPJ
"[FILES]\nnasmdoc.rtf\n\n";
1783 print HPJ
"[CONFIG]\n";
1784 print HPJ
'CreateButton("btn_up", "&Up",'.
1785 ' "JumpContents(`nasmdoc.hlp'."'".')")';
1786 print HPJ
"\nBrowseButtons()\n";
1790 print "\n writing .rtf file...";
1791 open TEXT
,">nasmdoc.rtf";
1795 print "{\\rtf1\\ansi{\\fonttbl\n";
1796 print "\\f0\\froman Times New Roman;\\f1\\fmodern Courier New;\n";
1797 print "\\f2\\fswiss Arial;\\f3\\ftech Wingdings}\\deff0\n";
1798 print "#{\\footnote Top}\n";
1799 print "\${\\footnote Contents}\n";
1800 print "+{\\footnote browse:00000}\n";
1801 print "!{\\footnote DisableButton(\"btn_up\")}\n";
1802 print "\\keepn\\f2\\b\\fs30\\sb0\n";
1803 print "NASM: The Netwide Assembler\n";
1804 print "\\par\\pard\\plain\\sb120\n";
1805 print "This file documents NASM, the Netwide Assembler: an assembler \n";
1806 print "targetting the Intel x86 series of processors, with portable source.\n";
1811 $newpar = "\\par\\sb120\n";
1812 for ($para = 0; $para <= $#pnames; $para++) {
1813 $pname = $pnames[$para];
1814 $pflags = $pflags[$para];
1815 $ptype = substr($pflags,0,4);
1818 $newpar = "\\par\\sb120\n";
1820 if ($ptype eq "chap") {
1821 # Chapter heading. Begin a new node.
1823 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1824 $pflags =~ /chap (.*) :(.*)/;
1825 $node = "Chapter $1";
1826 $title = $footnotetitle = "Chapter $1: ";
1827 foreach $i (@
$pname) {
1828 $ww = &word_hlp
($i,1);
1829 $title .= $ww, $footnotetitle .= &word_hlp
($i,0) unless $ww eq "\001";
1832 printf "#{\\footnote %s}\n", &hlp_sectkw
($node);
1833 print "\${\\footnote $footnotetitle}\n";
1834 printf "+{\\footnote browse:%05d}\n", ++$browse;
1835 printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," .
1836 "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n",
1837 &hlp_sectkw
($tstruct_up{$node});
1838 print "EnableButton(\"btn_up\")}\n";
1839 &hlp_keywords
($node);
1840 print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n";
1842 $newpar = "\\par\\pard\\plain\\sb120\n";
1843 } elsif ($ptype eq "appn") {
1844 # Appendix heading. Begin a new node.
1846 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1847 $pflags =~ /appn (.*) :(.*)/;
1848 $node = "Appendix $1";
1849 $title = $footnotetitle = "Appendix $1: ";
1850 foreach $i (@
$pname) {
1851 $ww = &word_hlp
($i,1);
1852 $title .= $ww, $footnotetitle .= &word_hlp
($i,0) unless $ww eq "\001";
1855 printf "#{\\footnote %s}\n", &hlp_sectkw
($node);
1856 print "\${\\footnote $footnotetitle}\n";
1857 printf "+{\\footnote browse:%05d}\n", ++$browse;
1858 printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," .
1859 "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n",
1860 &hlp_sectkw
($tstruct_up{$node});
1861 print "EnableButton(\"btn_up\")}\n";
1862 &hlp_keywords
($node);
1863 print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n";
1865 $newpar = "\\par\\pard\\plain\\sb120\n";
1866 } elsif ($ptype eq "head" || $ptype eq "subh") {
1867 # Heading or subheading. Begin a new node.
1869 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1870 $pflags =~ /.... (.*) :(.*)/;
1871 $node = "Section $1";
1872 $title = $footnotetitle = "$1. ";
1873 foreach $i (@
$pname) {
1874 $ww = &word_hlp
($i,1);
1875 $title .= $ww, $footnotetitle .= &word_hlp
($i,0) unless $ww eq "\001";
1878 printf "#{\\footnote %s}\n", &hlp_sectkw
($node);
1879 print "\${\\footnote $footnotetitle}\n";
1880 printf "+{\\footnote browse:%05d}\n", ++$browse;
1881 printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," .
1882 "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n",
1883 &hlp_sectkw
($tstruct_up{$node});
1884 print "EnableButton(\"btn_up\")}\n";
1885 &hlp_keywords
($node);
1886 print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n";
1888 $newpar = "\\par\\pard\\plain\\sb120\n";
1889 } elsif ($ptype eq "code") {
1891 print "\\keep\\f1\\sb120\n";
1892 foreach $i (@
$pname) {
1893 warn "code line longer than 68 chars: $i\n" if length $i > 68;
1897 print "$i\\par\\sb0\n";
1899 $newpar = "\\pard\\f0\\sb120\n";
1900 } elsif ($ptype eq "bull" || $ptype eq "norm") {
1901 # Ordinary paragraph, optionally bulleted. We wrap, FWIW.
1902 if ($ptype eq "bull") {
1903 print "\\tx360\\li360\\fi-360{\\f3\\'9F}\\tab\n";
1904 $newpar = "\\par\\pard\\sb120\n";
1906 $newpar = "\\par\\sb120\n";
1912 do { $w = &word_hlp
((shift @a),1); } while $w eq "\001"; # hack
1914 if ($w eq ' ' || $w eq '' || $w eq undef) {
1915 if (length ($line . $wd) > 75) {
1916 $line =~ s/\s*$//; # trim trailing spaces
1917 print "$line \n"; # and put one back
1919 $wd =~ s/^\s*//; # trim leading spaces
1925 } while ($w ne '' && $w ne undef);
1926 if ($line =~ /\S/) {
1927 $line =~ s/\s*$//; # trim trailing spaces
1940 my ($w, $docode) = @_;
1943 return undef if $w eq '' || $w eq undef;
1944 $wtype = substr($w,0,2);
1945 $wmajt = substr($wtype,0,1);
1950 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
1951 substr($w,0,length($w)-1) =~ s/-/\\'AD/g if $wmajt ne "x"; #nonbreakhyphens
1952 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
1954 } elsif ($wtype eq "sp") {
1956 } elsif ($wtype eq "da") {
1958 } elsif ($wmajt eq "c" || $wtype eq "wc") {
1959 $w =~ s/ /\\'A0/g; # make spaces non-breaking
1960 return $docode ?
"{\\f1 ${w}}" : $w;
1961 } elsif ($wtype eq "es") {
1963 } elsif ($wtype eq "ee") {
1965 } elsif ($wtype eq "eo") {
1966 return "{\\i ${w}}";
1967 } elsif ($wtype eq "x ") {
1969 } elsif ($wtype eq "xe") {
1970 $w = &hlp_sectkw
($w);
1971 return "}{\\v ${w}}";
1972 } elsif ($wmajt eq "i") {
1975 die "panic in word_hlp: $wtype$w\n";
1981 my $item, $kword, $i, $mpname, $title;
1983 $item = $tstruct_next{$topitem};
1984 print "\\li360\\fi-360\n";
1987 $mpname = $tstruct_pname{$item};
1988 foreach $i (@
$mpname) {
1989 $ww = &word_hlp
($i, 0);
1990 $title .= $ww unless $ww eq "\001";
1992 $kword = &hlp_sectkw
($item);
1993 print "{\\uldb ${item}: $title}{\\v $kword}\\par\\sb0\n";
1994 $item = $tstruct_mnext{$item};
1996 print "\\pard\\sb120\n";
2001 $node =~ tr/A-Z/a-z/;
2002 $node =~ tr/- ./___/;
2008 my $pfx = "K{\\footnote ";
2010 foreach $i (0..$#itags) {
2011 (print $pfx,$hlp_index[$i]), $pfx = ";\n", $done++
2012 if $idxnodes{$node,$itags[$i]};
2014 print "}\n" if $done;
2017 # Make tree structures. $tstruct_* is top-level and global.
2019 my ($item, $level) = @_;
2022 $tstruct_pname{$item} = $pname;
2023 $tstruct_next{$tstruct_previtem} = $item;
2024 $tstruct_prev{$item} = $tstruct_previtem;
2025 $tstruct_level{$item} = $level;
2026 $tstruct_up{$item} = $tstruct_last[$level-1];
2027 $tstruct_mnext{$tstruct_last[$level]} = $item;
2028 $tstruct_last[$level] = $item;
2029 for ($i=$level+1; $i<$MAXLEVEL; $i++) { $tstruct_last[$i] = undef; }
2030 $tstruct_previtem = $item;
2034 # PostScript font metric data. Used for line breaking.
2037 250, 0, 0, 0, 0, 0, 0, 0,
2038 0, 0, 0, 0, 0, 0, 0, 0,
2039 0, 0, 0, 0, 0, 0, 0, 0,
2040 0, 0, 0, 0, 0, 0, 0, 0,
2041 250, 333, 408, 500, 500, 833, 778, 333,
2042 333, 333, 500, 564, 250, 333, 250, 278,
2043 500, 500, 500, 500, 500, 500, 500, 500,
2044 500, 500, 278, 278, 564, 564, 564, 444,
2045 921, 722, 667, 667, 722, 611, 556, 722,
2046 722, 333, 389, 722, 611, 889, 722, 722,
2047 556, 722, 667, 556, 611, 722, 722, 944,
2048 722, 722, 611, 333, 278, 333, 469, 500,
2049 333, 444, 500, 444, 500, 444, 333, 500,
2050 500, 278, 278, 500, 278, 778, 500, 500,
2051 500, 500, 333, 389, 278, 500, 500, 722,
2052 500, 500, 444, 480, 200, 480, 541, 0,
2053 0, 0, 0, 0, 0, 0, 0, 0,
2054 0, 0, 0, 0, 0, 0, 0, 0,
2055 0, 0, 0, 0, 0, 0, 0, 0,
2056 0, 0, 0, 0, 0, 0, 0, 0,
2057 0, 333, 500, 500, 167, 500, 500, 500,
2058 500, 180, 444, 500, 333, 333, 556, 556,
2059 0, 500, 500, 500, 250, 0, 453, 350,
2060 333, 444, 444, 500,1000,1000, 0, 444,
2061 0, 333, 333, 333, 333, 333, 333, 333,
2062 333, 0, 333, 333, 0, 333, 333, 333,
2063 1000, 0, 0, 0, 0, 0, 0, 0,
2064 0, 0, 0, 0, 0, 0, 0, 0,
2065 0, 889, 0, 276, 0, 0, 0, 0,
2066 611, 722, 889, 310, 0, 0, 0, 0,
2067 0, 667, 0, 0, 0, 278, 0, 0,
2068 278, 500, 722, 500, 0, 0, 0, 0
2071 250, 0, 0, 0, 0, 0, 0, 0,
2072 0, 0, 0, 0, 0, 0, 0, 0,
2073 0, 0, 0, 0, 0, 0, 0, 0,
2074 0, 0, 0, 0, 0, 0, 0, 0,
2075 250, 333, 420, 500, 500, 833, 778, 333,
2076 333, 333, 500, 675, 250, 333, 250, 278,
2077 500, 500, 500, 500, 500, 500, 500, 500,
2078 500, 500, 333, 333, 675, 675, 675, 500,
2079 920, 611, 611, 667, 722, 611, 611, 722,
2080 722, 333, 444, 667, 556, 833, 667, 722,
2081 611, 722, 611, 500, 556, 722, 611, 833,
2082 611, 556, 556, 389, 278, 389, 422, 500,
2083 333, 500, 500, 444, 500, 444, 278, 500,
2084 500, 278, 278, 444, 278, 722, 500, 500,
2085 500, 500, 389, 389, 278, 500, 444, 667,
2086 444, 444, 389, 400, 275, 400, 541, 0,
2087 0, 0, 0, 0, 0, 0, 0, 0,
2088 0, 0, 0, 0, 0, 0, 0, 0,
2089 0, 0, 0, 0, 0, 0, 0, 0,
2090 0, 0, 0, 0, 0, 0, 0, 0,
2091 0, 389, 500, 500, 167, 500, 500, 500,
2092 500, 214, 556, 500, 333, 333, 500, 500,
2093 0, 500, 500, 500, 250, 0, 523, 350,
2094 333, 556, 556, 500, 889,1000, 0, 500,
2095 0, 333, 333, 333, 333, 333, 333, 333,
2096 333, 0, 333, 333, 0, 333, 333, 333,
2097 889, 0, 0, 0, 0, 0, 0, 0,
2098 0, 0, 0, 0, 0, 0, 0, 0,
2099 0, 889, 0, 276, 0, 0, 0, 0,
2100 556, 722, 944, 310, 0, 0, 0, 0,
2101 0, 667, 0, 0, 0, 278, 0, 0,
2102 278, 500, 667, 500, 0, 0, 0, 0
2105 600, 0, 0, 0, 0, 0, 0, 0,
2106 0, 0, 0, 0, 0, 0, 0, 0,
2107 0, 0, 0, 0, 0, 0, 0, 0,
2108 0, 0, 0, 0, 0, 0, 0, 0,
2109 600, 600, 600, 600, 600, 600, 600, 600,
2110 600, 600, 600, 600, 600, 600, 600, 600,
2111 600, 600, 600, 600, 600, 600, 600, 600,
2112 600, 600, 600, 600, 600, 600, 600, 600,
2113 600, 600, 600, 600, 600, 600, 600, 600,
2114 600, 600, 600, 600, 600, 600, 600, 600,
2115 600, 600, 600, 600, 600, 600, 600, 600,
2116 600, 600, 600, 600, 600, 600, 600, 600,
2117 600, 600, 600, 600, 600, 600, 600, 600,
2118 600, 600, 600, 600, 600, 600, 600, 600,
2119 600, 600, 600, 600, 600, 600, 600, 600,
2120 600, 600, 600, 600, 600, 600, 600, 0,
2121 0, 0, 0, 0, 0, 0, 0, 0,
2122 0, 0, 0, 0, 0, 0, 0, 0,
2123 0, 0, 0, 0, 0, 0, 0, 0,
2124 0, 0, 0, 0, 0, 0, 0, 0,
2125 0, 600, 600, 600, 600, 600, 600, 600,
2126 600, 600, 600, 600, 600, 600, 600, 600,
2127 0, 600, 600, 600, 600, 0, 600, 600,
2128 600, 600, 600, 600, 600, 600, 0, 600,
2129 0, 600, 600, 600, 600, 600, 600, 600,
2130 600, 0, 600, 600, 0, 600, 600, 600,
2131 600, 0, 0, 0, 0, 0, 0, 0,
2132 0, 0, 0, 0, 0, 0, 0, 0,
2133 0, 600, 0, 600, 0, 0, 0, 0,
2134 600, 600, 600, 600, 0, 0, 0, 0,
2135 0, 600, 0, 0, 0, 600, 0, 0,
2136 600, 600, 600, 600, 0, 0, 0, 0