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 "\@settitle NASM: The Netwide Assembler\n";
1523 print "\@setchapternewpage odd\n";
1524 print "\@c \%**end of header\n";
1527 print "This file documents NASM, the Netwide Assembler: an assembler\n";
1528 print "targetting the Intel x86 series of processors, with portable source.\n";
1530 print "Copyright 1997 Simon Tatham\n";
1532 print "All rights reserved. This document is redistributable under the\n";
1533 print "licence given in the file \"Licence\" distributed in the NASM archive.\n";
1534 print "\@end ifinfo\n";
1536 print "\@titlepage\n";
1537 print "\@title NASM: The Netwide Assembler\n";
1538 print "\@author Simon Tatham\n";
1541 print "\@vskip 0pt plus 1filll\n";
1542 print "Copyright \@copyright{} 1997 Simon Tatham\n";
1544 print "All rights reserved. This document is redistributable under the\n";
1545 print "licence given in the file \"Licence\" distributed in the NASM archive.\n";
1546 print "\@end titlepage\n";
1548 print "\@node Top, $tstruct_next{'Top'}, (dir), (dir)\n";
1552 print "This file documents NASM, the Netwide Assembler: an assembler\n";
1553 print "targetting the Intel x86 series of processors, with portable source.\n";
1554 print "\@end ifinfo\n";
1559 for ($para = 0; $para <= $#pnames; $para++) {
1560 $pname = $pnames[$para];
1561 $pflags = $pflags[$para];
1562 $ptype = substr($pflags,0,4);
1564 $bulleting = 0, print "\@end itemize\n" if $bulleting && $ptype ne "bull";
1565 print "\n"; # always one of these before a new paragraph
1567 if ($ptype eq "chap") {
1568 # Chapter heading. Begin a new node.
1570 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1571 $pflags =~ /chap (.*) :(.*)/;
1572 $node = "Chapter $1";
1573 $title = "Chapter $1: ";
1574 foreach $i (@
$pname) {
1575 $ww = &word_texi
($i);
1576 $title .= $ww unless $ww eq "\001";
1578 print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},";
1579 print " $tstruct_up{$node}\n\@unnumbered $title\n";
1580 } elsif ($ptype eq "appn") {
1581 # Appendix heading. Begin a new node.
1583 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1584 $pflags =~ /appn (.*) :(.*)/;
1585 $node = "Appendix $1";
1586 $title = "Appendix $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 "head" || $ptype eq "subh") {
1594 # Heading or subheading. Begin a new node.
1596 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1597 $pflags =~ /.... (.*) :(.*)/;
1598 $node = "Section $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 "code") {
1607 # Code paragraph. Surround with @example / @end example.
1608 print "\@example\n";
1609 foreach $i (@
$pname) {
1610 warn "code line longer than 68 chars: $i\n" if length $i > 68;
1616 print "\@end example\n";
1617 } elsif ($ptype eq "bull" || $ptype eq "norm") {
1618 # Ordinary paragraph, optionally bulleted. We wrap, FWIW.
1619 if ($ptype eq "bull") {
1620 $bulleting = 1, print "\@itemize \@bullet\n" if !$bulleting;
1627 do { $w = &word_texi
(shift @a); } while $w eq "\001"; # hack
1629 if ($wprev =~ /-$/ || $w eq ' ' || $w eq '' || $w eq undef) {
1630 if (length ($line . $wd) > 75) {
1631 $line =~ s/\s*$//; # trim trailing spaces
1634 $wd =~ s/^\s*//; # trim leading spaces
1640 } while ($w ne '' && $w ne undef);
1641 if ($line =~ /\S/) {
1642 $line =~ s/\s*$//; # trim trailing spaces
1652 print "\n\@contents\n\@bye\n";
1657 # Side effect of this procedure: update global `texiwdlen' to be the length
1658 # in chars of the formatted version of the word.
1663 return undef if $w eq '' || $w eq undef;
1664 $wtype = substr($w,0,2);
1665 $wmajt = substr($wtype,0,1);
1671 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
1672 substr($w,0,1) =~ tr/a-z/A-Z/, $capital = 0 if $capital;
1673 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
1676 } elsif ($wtype eq "sp") {
1679 } elsif ($wtype eq "da") {
1682 } elsif ($wmajt eq "c" || $wtype eq "wc") {
1683 $texiwdlen = 2 + $wlen;
1684 return "\@code\{$w\}";
1685 } elsif ($wtype eq "es") {
1686 $texiwdlen = 1 + $wlen;
1687 return "\@emph\{${w}";
1688 } elsif ($wtype eq "ee") {
1689 $texiwdlen = 1 + $wlen;
1691 } elsif ($wtype eq "eo") {
1692 $texiwdlen = 2 + $wlen;
1693 return "\@emph\{${w}\}";
1694 } elsif ($wtype eq "x ") {
1695 $texiwdlen = 0; # we don't need it in this case
1696 $capital = 1; # hack
1698 } elsif ($wtype eq "xe") {
1699 $texiwdlen = 0; # we don't need it in this case
1701 } elsif ($wmajt eq "i") {
1702 $texiwdlen = 0; # we don't need it in this case
1705 die "panic in word_texi: $wtype$w\n";
1711 my $item, $i, $mpname, $title, $wd;
1713 $item = $tstruct_next{$topitem};
1717 $mpname = $tstruct_pname{$item};
1718 foreach $i (@
$mpname) {
1719 $wd = &word_texi
($i);
1720 $title .= $wd unless $wd eq "\001";
1722 print "* ${item}:: $title\n";
1723 $item = $tstruct_mnext{$item};
1725 print "* Index::\n" if $topitem eq "Top";
1726 print "\@end menu\n";
1730 my $itag, $ientry, @a, $wd, $item, $len;
1731 my $subnums = "123456789ABCDEFGHIJKLMNOPQRSTU" .
1732 "VWXYZabcdefghijklmnopqrstuvwxyz";
1734 print "\@ifinfo\n\@node Index, , $FIXMElastnode, Top\n";
1735 print "\@unnumbered Index\n\n\@menu\n";
1737 foreach $itag (@itags) {
1738 $ientry = $idxmap{$itag};
1743 $wd = &word_texi
($i);
1744 $item .= $wd, $len += $texiwdlen unless $wd eq "\001";
1747 foreach $node (@nodes) {
1748 next if !$idxnodes{$node,$itag};
1749 printf "* %s%s (%s): %s.\n",
1750 $item, " " x
(40-$len), substr($subnums,$i++,1), $node;
1753 print "\@end menu\n\@end ifinfo\n";
1757 # This is called from the top level, so I won't bother using
1760 # Build the index-tag text forms.
1761 print "building index entries...";
1764 my $ientry = $idxmap{$_};
1766 foreach $i (@
$ientry) {
1767 $ww = &word_hlp
($i,0);
1768 $title .= $ww unless $ww eq "\001";
1773 # Write the HPJ project-description file.
1774 print "writing .hpj file...";
1775 open HPJ
,">nasmdoc.hpj";
1776 print HPJ
"[OPTIONS]\ncompress=true\n";
1777 print HPJ
"title=NASM: The Netwide Assembler\noldkeyphrase=no\n\n";
1778 print HPJ
"[FILES]\nnasmdoc.rtf\n\n";
1779 print HPJ
"[CONFIG]\n";
1780 print HPJ
'CreateButton("btn_up", "&Up",'.
1781 ' "JumpContents(`nasmdoc.hlp'."'".')")';
1782 print HPJ
"\nBrowseButtons()\n";
1786 print "\n writing .rtf file...";
1787 open TEXT
,">nasmdoc.rtf";
1791 print "{\\rtf1\\ansi{\\fonttbl\n";
1792 print "\\f0\\froman Times New Roman;\\f1\\fmodern Courier New;\n";
1793 print "\\f2\\fswiss Arial;\\f3\\ftech Wingdings}\\deff0\n";
1794 print "#{\\footnote Top}\n";
1795 print "\${\\footnote Contents}\n";
1796 print "+{\\footnote browse:00000}\n";
1797 print "!{\\footnote DisableButton(\"btn_up\")}\n";
1798 print "\\keepn\\f2\\b\\fs30\\sb0\n";
1799 print "NASM: The Netwide Assembler\n";
1800 print "\\par\\pard\\plain\\sb120\n";
1801 print "This file documents NASM, the Netwide Assembler: an assembler \n";
1802 print "targetting the Intel x86 series of processors, with portable source.\n";
1807 $newpar = "\\par\\sb120\n";
1808 for ($para = 0; $para <= $#pnames; $para++) {
1809 $pname = $pnames[$para];
1810 $pflags = $pflags[$para];
1811 $ptype = substr($pflags,0,4);
1814 $newpar = "\\par\\sb120\n";
1816 if ($ptype eq "chap") {
1817 # Chapter heading. Begin a new node.
1819 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1820 $pflags =~ /chap (.*) :(.*)/;
1821 $node = "Chapter $1";
1822 $title = $footnotetitle = "Chapter $1: ";
1823 foreach $i (@
$pname) {
1824 $ww = &word_hlp
($i,1);
1825 $title .= $ww, $footnotetitle .= &word_hlp
($i,0) unless $ww eq "\001";
1828 printf "#{\\footnote %s}\n", &hlp_sectkw
($node);
1829 print "\${\\footnote $footnotetitle}\n";
1830 printf "+{\\footnote browse:%05d}\n", ++$browse;
1831 printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," .
1832 "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n",
1833 &hlp_sectkw
($tstruct_up{$node});
1834 print "EnableButton(\"btn_up\")}\n";
1835 &hlp_keywords
($node);
1836 print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n";
1838 $newpar = "\\par\\pard\\plain\\sb120\n";
1839 } elsif ($ptype eq "appn") {
1840 # Appendix heading. Begin a new node.
1842 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1843 $pflags =~ /appn (.*) :(.*)/;
1844 $node = "Appendix $1";
1845 $title = $footnotetitle = "Appendix $1: ";
1846 foreach $i (@
$pname) {
1847 $ww = &word_hlp
($i,1);
1848 $title .= $ww, $footnotetitle .= &word_hlp
($i,0) unless $ww eq "\001";
1851 printf "#{\\footnote %s}\n", &hlp_sectkw
($node);
1852 print "\${\\footnote $footnotetitle}\n";
1853 printf "+{\\footnote browse:%05d}\n", ++$browse;
1854 printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," .
1855 "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n",
1856 &hlp_sectkw
($tstruct_up{$node});
1857 print "EnableButton(\"btn_up\")}\n";
1858 &hlp_keywords
($node);
1859 print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n";
1861 $newpar = "\\par\\pard\\plain\\sb120\n";
1862 } elsif ($ptype eq "head" || $ptype eq "subh") {
1863 # Heading or subheading. Begin a new node.
1865 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1866 $pflags =~ /.... (.*) :(.*)/;
1867 $node = "Section $1";
1868 $title = $footnotetitle = "$1. ";
1869 foreach $i (@
$pname) {
1870 $ww = &word_hlp
($i,1);
1871 $title .= $ww, $footnotetitle .= &word_hlp
($i,0) unless $ww eq "\001";
1874 printf "#{\\footnote %s}\n", &hlp_sectkw
($node);
1875 print "\${\\footnote $footnotetitle}\n";
1876 printf "+{\\footnote browse:%05d}\n", ++$browse;
1877 printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," .
1878 "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n",
1879 &hlp_sectkw
($tstruct_up{$node});
1880 print "EnableButton(\"btn_up\")}\n";
1881 &hlp_keywords
($node);
1882 print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n";
1884 $newpar = "\\par\\pard\\plain\\sb120\n";
1885 } elsif ($ptype eq "code") {
1887 print "\\keep\\f1\\sb120\n";
1888 foreach $i (@
$pname) {
1889 warn "code line longer than 68 chars: $i\n" if length $i > 68;
1893 print "$i\\par\\sb0\n";
1895 $newpar = "\\pard\\f0\\sb120\n";
1896 } elsif ($ptype eq "bull" || $ptype eq "norm") {
1897 # Ordinary paragraph, optionally bulleted. We wrap, FWIW.
1898 if ($ptype eq "bull") {
1899 print "\\tx360\\li360\\fi-360{\\f3\\'9F}\\tab\n";
1900 $newpar = "\\par\\pard\\sb120\n";
1902 $newpar = "\\par\\sb120\n";
1908 do { $w = &word_hlp
((shift @a),1); } while $w eq "\001"; # hack
1910 if ($w eq ' ' || $w eq '' || $w eq undef) {
1911 if (length ($line . $wd) > 75) {
1912 $line =~ s/\s*$//; # trim trailing spaces
1913 print "$line \n"; # and put one back
1915 $wd =~ s/^\s*//; # trim leading spaces
1921 } while ($w ne '' && $w ne undef);
1922 if ($line =~ /\S/) {
1923 $line =~ s/\s*$//; # trim trailing spaces
1936 my ($w, $docode) = @_;
1939 return undef if $w eq '' || $w eq undef;
1940 $wtype = substr($w,0,2);
1941 $wmajt = substr($wtype,0,1);
1946 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
1947 substr($w,0,length($w)-1) =~ s/-/\\'AD/g if $wmajt ne "x"; #nonbreakhyphens
1948 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
1950 } elsif ($wtype eq "sp") {
1952 } elsif ($wtype eq "da") {
1954 } elsif ($wmajt eq "c" || $wtype eq "wc") {
1955 $w =~ s/ /\\'A0/g; # make spaces non-breaking
1956 return $docode ?
"{\\f1 ${w}}" : $w;
1957 } elsif ($wtype eq "es") {
1959 } elsif ($wtype eq "ee") {
1961 } elsif ($wtype eq "eo") {
1962 return "{\\i ${w}}";
1963 } elsif ($wtype eq "x ") {
1965 } elsif ($wtype eq "xe") {
1966 $w = &hlp_sectkw
($w);
1967 return "}{\\v ${w}}";
1968 } elsif ($wmajt eq "i") {
1971 die "panic in word_hlp: $wtype$w\n";
1977 my $item, $kword, $i, $mpname, $title;
1979 $item = $tstruct_next{$topitem};
1980 print "\\li360\\fi-360\n";
1983 $mpname = $tstruct_pname{$item};
1984 foreach $i (@
$mpname) {
1985 $ww = &word_hlp
($i, 0);
1986 $title .= $ww unless $ww eq "\001";
1988 $kword = &hlp_sectkw
($item);
1989 print "{\\uldb ${item}: $title}{\\v $kword}\\par\\sb0\n";
1990 $item = $tstruct_mnext{$item};
1992 print "\\pard\\sb120\n";
1997 $node =~ tr/A-Z/a-z/;
1998 $node =~ tr/- ./___/;
2004 my $pfx = "K{\\footnote ";
2006 foreach $i (0..$#itags) {
2007 (print $pfx,$hlp_index[$i]), $pfx = ";\n", $done++
2008 if $idxnodes{$node,$itags[$i]};
2010 print "}\n" if $done;
2013 # Make tree structures. $tstruct_* is top-level and global.
2015 my ($item, $level) = @_;
2018 $tstruct_pname{$item} = $pname;
2019 $tstruct_next{$tstruct_previtem} = $item;
2020 $tstruct_prev{$item} = $tstruct_previtem;
2021 $tstruct_level{$item} = $level;
2022 $tstruct_up{$item} = $tstruct_last[$level-1];
2023 $tstruct_mnext{$tstruct_last[$level]} = $item;
2024 $tstruct_last[$level] = $item;
2025 for ($i=$level+1; $i<$MAXLEVEL; $i++) { $tstruct_last[$i] = undef; }
2026 $tstruct_previtem = $item;
2030 # PostScript font metric data. Used for line breaking.
2033 250, 0, 0, 0, 0, 0, 0, 0,
2034 0, 0, 0, 0, 0, 0, 0, 0,
2035 0, 0, 0, 0, 0, 0, 0, 0,
2036 0, 0, 0, 0, 0, 0, 0, 0,
2037 250, 333, 408, 500, 500, 833, 778, 333,
2038 333, 333, 500, 564, 250, 333, 250, 278,
2039 500, 500, 500, 500, 500, 500, 500, 500,
2040 500, 500, 278, 278, 564, 564, 564, 444,
2041 921, 722, 667, 667, 722, 611, 556, 722,
2042 722, 333, 389, 722, 611, 889, 722, 722,
2043 556, 722, 667, 556, 611, 722, 722, 944,
2044 722, 722, 611, 333, 278, 333, 469, 500,
2045 333, 444, 500, 444, 500, 444, 333, 500,
2046 500, 278, 278, 500, 278, 778, 500, 500,
2047 500, 500, 333, 389, 278, 500, 500, 722,
2048 500, 500, 444, 480, 200, 480, 541, 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 0, 0, 0, 0, 0, 0, 0, 0,
2053 0, 333, 500, 500, 167, 500, 500, 500,
2054 500, 180, 444, 500, 333, 333, 556, 556,
2055 0, 500, 500, 500, 250, 0, 453, 350,
2056 333, 444, 444, 500,1000,1000, 0, 444,
2057 0, 333, 333, 333, 333, 333, 333, 333,
2058 333, 0, 333, 333, 0, 333, 333, 333,
2059 1000, 0, 0, 0, 0, 0, 0, 0,
2060 0, 0, 0, 0, 0, 0, 0, 0,
2061 0, 889, 0, 276, 0, 0, 0, 0,
2062 611, 722, 889, 310, 0, 0, 0, 0,
2063 0, 667, 0, 0, 0, 278, 0, 0,
2064 278, 500, 722, 500, 0, 0, 0, 0
2067 250, 0, 0, 0, 0, 0, 0, 0,
2068 0, 0, 0, 0, 0, 0, 0, 0,
2069 0, 0, 0, 0, 0, 0, 0, 0,
2070 0, 0, 0, 0, 0, 0, 0, 0,
2071 250, 333, 420, 500, 500, 833, 778, 333,
2072 333, 333, 500, 675, 250, 333, 250, 278,
2073 500, 500, 500, 500, 500, 500, 500, 500,
2074 500, 500, 333, 333, 675, 675, 675, 500,
2075 920, 611, 611, 667, 722, 611, 611, 722,
2076 722, 333, 444, 667, 556, 833, 667, 722,
2077 611, 722, 611, 500, 556, 722, 611, 833,
2078 611, 556, 556, 389, 278, 389, 422, 500,
2079 333, 500, 500, 444, 500, 444, 278, 500,
2080 500, 278, 278, 444, 278, 722, 500, 500,
2081 500, 500, 389, 389, 278, 500, 444, 667,
2082 444, 444, 389, 400, 275, 400, 541, 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 0, 0, 0, 0, 0, 0, 0, 0,
2087 0, 389, 500, 500, 167, 500, 500, 500,
2088 500, 214, 556, 500, 333, 333, 500, 500,
2089 0, 500, 500, 500, 250, 0, 523, 350,
2090 333, 556, 556, 500, 889,1000, 0, 500,
2091 0, 333, 333, 333, 333, 333, 333, 333,
2092 333, 0, 333, 333, 0, 333, 333, 333,
2093 889, 0, 0, 0, 0, 0, 0, 0,
2094 0, 0, 0, 0, 0, 0, 0, 0,
2095 0, 889, 0, 276, 0, 0, 0, 0,
2096 556, 722, 944, 310, 0, 0, 0, 0,
2097 0, 667, 0, 0, 0, 278, 0, 0,
2098 278, 500, 667, 500, 0, 0, 0, 0
2101 600, 0, 0, 0, 0, 0, 0, 0,
2102 0, 0, 0, 0, 0, 0, 0, 0,
2103 0, 0, 0, 0, 0, 0, 0, 0,
2104 0, 0, 0, 0, 0, 0, 0, 0,
2105 600, 600, 600, 600, 600, 600, 600, 600,
2106 600, 600, 600, 600, 600, 600, 600, 600,
2107 600, 600, 600, 600, 600, 600, 600, 600,
2108 600, 600, 600, 600, 600, 600, 600, 600,
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, 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 0, 0, 0, 0, 0, 0, 0, 0,
2121 0, 600, 600, 600, 600, 600, 600, 600,
2122 600, 600, 600, 600, 600, 600, 600, 600,
2123 0, 600, 600, 600, 600, 0, 600, 600,
2124 600, 600, 600, 600, 600, 600, 0, 600,
2125 0, 600, 600, 600, 600, 600, 600, 600,
2126 600, 0, 600, 600, 0, 600, 600, 600,
2127 600, 0, 0, 0, 0, 0, 0, 0,
2128 0, 0, 0, 0, 0, 0, 0, 0,
2129 0, 600, 0, 600, 0, 0, 0, 0,
2130 600, 600, 600, 600, 0, 0, 0, 0,
2131 0, 600, 0, 0, 0, 600, 0, 0,
2132 600, 600, 600, 600, 0, 0, 0, 0