NASM 0.98bf
[nasm/avx512.git] / doc / rdsrc.pl
blob38044b165125569fec39e1768234a46e21d3a48e
1 #!/usr/bin/perl
3 # Read the source-form of the NASM manual and generate the various
4 # output forms.
6 # TODO:
8 # PS output:
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 # ---------------------
18 # Bullet \b
19 # Bullets the paragraph. Rest of paragraph is indented to cope. In
20 # HTML, consecutive groups of bulleted paragraphs become unordered
21 # lists.
23 # Emphasis \e{foobar}
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
29 # Display code
30 # \c line one
31 # \c line two
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
47 # hyperlinks.
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.
53 # Literals \{ \} \\
54 # In case it's necessary, they expand to the real versions.
56 # Nonbreaking hyphen \-
57 # Need more be said?
59 # Source comment \#
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
71 # Index rewrite
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
76 # Index alias
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";
84 $| = 1;
86 $tstruct_previtem = $node = "Top";
87 $nodes = ($node);
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 = ();
96 $para = undef;
97 while (<>) {
98 chomp;
99 if (!/\S/ || /^\\I[AR]/) { # special case: \I[AR] implies new-paragraph
100 &got_para($para);
101 $para = undef;
103 if (/\S/) {
104 s/\\#.*$//; # strip comments
105 $para .= " " . $_;
108 &got_para($para);
109 print "done.\n";
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...";
114 &fixup_xrefs;
115 print "done.\n";
117 # Sort the index tags, according to the slightly odd order I've decided on.
118 print "Sorting index tags...";
119 &indexsort;
120 print "done.\n";
122 if ($diag) {
123 print "Writing index-diagnostic file...";
124 &indexdiag;
125 print "done.\n";
128 # OK. Write out the various output files.
129 print "Producing text output: ";
130 &write_txt;
131 print "done.\n";
132 print "Producing HTML output: ";
133 &write_html;
134 print "done.\n";
135 print "Producing PostScript output: ";
136 &write_ps;
137 print "done.\n";
138 print "Producing Texinfo output: ";
139 &write_texi;
140 print "done.\n";
141 print "Producing WinHelp output: ";
142 &write_hlp;
143 print "done.\n";
145 sub got_para {
146 local ($_) = @_;
147 my $pflags = "", $i, $w, $l, $t;
148 return if !/\S/;
150 @$pname = ();
152 # Strip off _leading_ spaces, then determine type of paragraph.
153 s/^\s*//;
154 $irewrite = undef;
155 if (/^\\c[^{]/) {
156 # A code paragraph. The paragraph-array will contain the simple
157 # strings which form each line of the paragraph.
158 $pflags = "code";
159 while (/^\\c (([^\\]|\\[^c])*)(.*)$/) {
160 $l = $1;
161 $_ = $3;
162 $l =~ s/\\{/{/g;
163 $l =~ s/\\}/}/g;
164 $l =~ s/\\\\/\\/g;
165 push @$pname, $l;
167 $_ = ''; # suppress word-by-word code
168 } elsif (/^\\C/) {
169 # A chapter heading. Define the keyword and allocate a chapter
170 # number.
171 $cnum++;
172 $hnum = 0;
173 $snum = 0;
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";
179 &add_item($node, 1);
180 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
181 $xrefs{$1} = $xref;
182 $_ = $2;
183 # the standard word-by-word code will happen next
184 } elsif (/^\\A/) {
185 # An appendix heading. Define the keyword and allocate an appendix
186 # letter.
187 $cnum++;
188 $cnum = 'A' if $cnum =~ /[0-9]+/;
189 $hnum = 0;
190 $snum = 0;
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";
196 &add_item($node, 1);
197 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
198 $xrefs{$1} = $xref;
199 $_ = $2;
200 # the standard word-by-word code will happen next
201 } elsif (/^\\H/) {
202 # A major heading. Define the keyword and allocate a section number.
203 $hnum++;
204 $snum = 0;
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";
210 &add_item($node, 2);
211 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
212 $xrefs{$1} = $xref;
213 $_ = $2;
214 # the standard word-by-word code will happen next
215 } elsif (/^\\S/) {
216 # A sub-heading. Define the keyword and allocate a section number.
217 $snum++;
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";
223 &add_item($node, 3);
224 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
225 $xrefs{$1} = $xref;
226 $_ = $2;
227 # the standard word-by-word code will happen next
228 } elsif (/^\\IR/) {
229 # An index-rewrite.
230 die "badly formatted index rewrite: $_\n" if !/^\\IR{([^}]*)}\s*(.*)$/;
231 $irewrite = $1;
232 $_ = $2;
233 # the standard word-by-word code will happen next
234 } elsif (/^\\IA/) {
235 # An index-alias.
236 die "badly formatted index alias: $_\n" if !/^\\IA{([^}]*)}{([^}]*)}\s*$/;
237 $idxalias{$1} = $2;
238 return; # avoid word-by-word code
239 } elsif (/^\\b/) {
240 # A bulleted paragraph. Strip off the initial \b and let the
241 # word-by-word code take care of the rest.
242 $pflags = "bull";
243 s/^\\b\s*//;
244 } else {
245 # A normal paragraph. Just set $pflags: the word-by-word code does
246 # the rest.
247 $pflags = "norm";
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.
257 # Type codes are:
258 # "n " for normal
259 # "da" for a dash
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
264 # "c " for code
265 # "k " for cross-ref
266 # "kK" for capitalised cross-ref
267 # "w " for Web link
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
273 # index-items arrays
274 # "sp" for space
275 while (/\S/) {
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;
281 s/^\\c//;
282 die "badly formatted \\c: \\c$_\n" if !/{(([^\\}]|\\.)*)}(.*)$/;
283 $w = $1;
284 $_ = $3;
285 $w =~ s/\\{/{/g;
286 $w =~ s/\\}/}/g;
287 $w =~ s/\\-/-/g;
288 $w =~ s/\\\\/\\/g;
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]/) {
293 /^(\\[iI])?(\\e)?/;
294 $emph = 0;
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 !/{(([^\\}]|\\.)*)}(.*)$/;
300 $w = $1;
301 $_ = $3;
302 $w =~ s/\\{/{/g;
303 $w =~ s/\\}/}/g;
304 $w =~ s/\\-/-/g;
305 $w =~ s/\\\\/\\/g;
306 $t = $emph ? "es" : "n ";
307 @ientry = ();
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]/) {
323 $t = "k ";
324 $t = "kK" if /^\\K/;
325 s/^\\[kK]//;
326 die "badly formatted \\k: \\c$_\n" if !/{([^}]*)}(.*)$/;
327 $_ = $2;
328 push @$pname,"$t$1";
329 } elsif (/^\\W/) {
330 s/^\\W//;
331 die "badly formatted \\W: \\W$_\n"
332 if !/{([^}]*)}(\\i)?(\\c)?{(([^\\}]|\\.)*)}(.*)$/;
333 $l = $1;
334 $w = $4;
335 $_ = $6;
336 $t = "w ";
337 $t = "wc" if $3 eq "\\c";
338 $indexing = 1 if $2;
339 $w =~ s/\\{/{/g;
340 $w =~ s/\\}/}/g;
341 $w =~ s/\\-/-/g;
342 $w =~ s/\\\\/\\/g;
343 (push @$pname,"i"),$lastp = $#$pname if $indexing;
344 push @$pname,"$t<$l>$w";
345 $$pname[$lastp] = &addidx($node, $w, "c $w") if $indexing;
346 } else {
347 die "what the hell? $_\n" if !/^(([^\s\\\-]|\\[\\{}\-])*-?)(.*)$/;
348 die "painful death! $_\n" if !length $1;
349 $w = $1;
350 $_ = $3;
351 $w =~ s/\\{/{/g;
352 $w =~ s/\\}/}/g;
353 $w =~ s/\\-/-/g;
354 $w =~ s/\\\\/\\/g;
355 if ($w eq "-") {
356 push @$pname,"da";
357 } else {
358 push @$pname,"n $w";
362 if ($irewrite ne undef) {
363 &addidx(undef, $irewrite, @$pname);
364 @$pname = ();
365 } else {
366 push @pnames, $pname;
367 push @pflags, $pflags;
368 $pname++;
372 sub addidx {
373 my ($node, $text, @ientry) = @_;
374 $text = $idxalias{$text} || $text;
375 if ($node eq undef || !$idxmap{$text}) {
376 @$ientry = @ientry;
377 $idxmap{$text} = $ientry;
378 $ientry++;
380 if ($node) {
381 $idxnodes{$node,$text} = 1;
382 return "i $text";
386 sub indexsort {
387 my $iitem, $ientry, $i, $piitem, $pcval, $cval, $clrcval;
389 @itags = map { # get back the original data as the 1st elt of each list
390 $_->[0]
391 } sort { # compare auxiliary (non-first) elements of lists
392 $a->[1] cmp $b->[1] ||
393 $a->[2] cmp $b->[2] ||
394 $a->[0] cmp $b->[0]
395 } map { # transform array into list of 3-element lists
396 my $ientry = $idxmap{$_};
397 my $a = substr($$ientry[0],2);
398 $a =~ tr/A-Za-z//cd;
399 [$_, uc($a), substr($$ientry[0],0,2)]
400 } keys %idxmap;
402 # Having done that, check for comma-hood.
403 $cval = 0;
404 foreach $iitem (@itags) {
405 $ientry = $idxmap{$iitem};
406 $clrcval = 1;
407 $pcval = $cval;
408 FL:for ($i=0; $i <= $#$ientry; $i++) {
409 if ($$ientry[$i] =~ /^(n .*,)(.*)/) {
410 $$ientry[$i] = $1;
411 splice @$ientry,$i+1,0,"n $2" if length $2;
412 $commapos{$iitem} = $i+1;
413 $cval = join("\002", @$ientry[0..$i]);
414 $clrcval = 0;
415 last FL;
418 $cval = undef if $clrcval;
419 $commanext{$iitem} = $commaafter{$piitem} = 1
420 if $cval and ($cval eq $pcval);
421 $piitem = $iitem;
425 sub indexdiag {
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) {
432 $ww = &word_txt($w);
433 print INDEXDIAG $ww unless $ww eq "\001";
435 print INDEXDIAG ":";
436 $foo = " ";
437 foreach $node (@nodes) {
438 (print INDEXDIAG $foo,$node), $foo = ", " if $idxnodes{$node,$iitem};
440 print INDEXDIAG "\n";
442 close INDEXDIAG;
445 sub fixup_xrefs {
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/) {
453 $k = $$pname[$i];
454 $caps = ($k =~ /^kK/);
455 $k = substr($k,2);
456 $repl = $refs{$k};
457 die "undefined keyword `$k'\n" unless $repl;
458 substr($repl,0,1) =~ tr/a-z/A-Z/ if $caps;
459 @repl = ();
460 push @repl,"x $xrefs{$k}";
461 foreach $j (split /\s+/,$repl) {
462 push @repl,"n $j";
463 push @repl,"sp";
465 pop @repl; # remove final space
466 push @repl,"xe$xrefs{$k}";
467 splice @$pname,$i,1,@repl;
473 sub write_txt {
474 # This is called from the top level, so I won't bother using
475 # my or local.
477 # Open file.
478 print "writing file...";
479 open TEXT,">nasmdoc.txt";
480 select TEXT;
482 # Preamble.
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
497 # minus signs.
498 $pflags =~ /chap (.*) :(.*)/;
499 $title = "Chapter $1: ";
500 foreach $i (@$pname) {
501 $ww = &word_txt($i);
502 $title .= $ww unless $ww eq "\001";
504 print "$title\n";
505 $title =~ s/./-/g;
506 print "$title\n";
507 } elsif ($ptype eq "appn") {
508 # Appendix heading. "Appendix N: Title" followed by a line of
509 # minus signs.
510 $pflags =~ /appn (.*) :(.*)/;
511 $title = "Appendix $1: ";
512 foreach $i (@$pname) {
513 $ww = &word_txt($i);
514 $title .= $ww unless $ww eq "\001";
516 print "$title\n";
517 $title =~ s/./-/g;
518 print "$title\n";
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) {
524 $ww = &word_txt($i);
525 $title .= $ww unless $ww eq "\001";
527 print "$title\n";
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 . '(*) ';
540 $next = ' 'x11;
541 } else {
542 $line = $next = ' 'x7;
544 @a = @$pname;
545 $wd = $wprev = '';
546 do {
547 do { $w = &word_txt(shift @a) } while $w eq "\001"; # nasty hack
548 $wd .= $wprev;
549 if ($wprev =~ /-$/ || $w eq ' ' || $w eq '' || $w eq undef) {
550 if (length ($line . $wd) > 75) {
551 $line =~ s/\s*$//; # trim trailing spaces
552 print "$line\n";
553 $line = $next;
554 $wd =~ s/^\s*//; # trim leading spaces
556 $line .= $wd;
557 $wd = '';
559 $wprev = $w;
560 } while ($w ne '' && $w ne undef);
561 if ($line =~ /\S/) {
562 $line =~ s/\s*$//; # trim trailing spaces
563 print "$line\n";
568 # Close file.
569 select STDOUT;
570 close TEXT;
573 sub word_txt {
574 my ($w) = @_;
575 my $wtype, $wmajt;
577 return undef if $w eq '' || $w eq undef;
578 $wtype = substr($w,0,2);
579 $wmajt = substr($wtype,0,1);
580 $w = substr($w,2);
581 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
582 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
583 return $w;
584 } elsif ($wtype eq "sp") {
585 return ' ';
586 } elsif ($wtype eq "da") {
587 return '-';
588 } elsif ($wmajt eq "c" || $wtype eq "wc") {
589 return "`${w}'";
590 } elsif ($wtype eq "es") {
591 return "_${w}";
592 } elsif ($wtype eq "ee") {
593 return "${w}_";
594 } elsif ($wtype eq "eo") {
595 return "_${w}_";
596 } elsif ($wmajt eq "x" || $wmajt eq "i") {
597 return "\001";
598 } else {
599 die "panic in word_txt: $wtype$w\n";
603 sub write_html {
604 # This is called from the top level, so I won't bother using
605 # my or local.
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";
611 select TEXT;
612 &html_preamble(0);
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";
615 print "<p>";
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;
623 $link = $fname;
624 print "<p>";
625 } else {
626 # Use the preceding filename plus a marker point.
627 $link = $fname . "#$xrefnodes{$node}";
629 $title = "$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";
639 select STDOUT;
640 close TEXT;
642 # Open a null file, to ensure output (eg random &html_jumppoints calls)
643 # goes _somewhere_.
644 print "writing chapter files...";
645 open TEXT,">/dev/null";
646 select TEXT;
647 $html_lastf = '';
649 $in_list = 0;
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: ";
661 $xref = $2;
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: ";
677 $xref = $2;
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");
692 $title = $1 . " ";
693 $xref = $2;
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") {
700 # Code paragraph.
701 print "<p><pre>\n";
702 foreach $i (@$pname) {
703 $w = $i;
704 $w =~ s/&/&amp;/g;
705 $w =~ s/</&lt;/g;
706 $w =~ s/>/&gt;/g;
707 print $w, "\n";
709 print "</pre>\n";
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;
716 $line = '<li>';
717 } else {
718 $line = '<p>';
720 @a = @$pname;
721 $wd = $wprev = '';
722 do {
723 do { $w = &word_html(shift @a) } while $w eq "\001"; # nasty hack
724 $wd .= $wprev;
725 if ($w eq ' ' || $w eq '' || $w eq undef) {
726 if (length ($line . $wd) > 75) {
727 $line =~ s/\s*$//; # trim trailing spaces
728 print "$line\n";
729 $line = '';
730 $wd =~ s/^\s*//; # trim leading spaces
732 $line .= $wd;
733 $wd = '';
735 $wprev = $w;
736 } while ($w ne '' && $w ne undef);
737 if ($line =~ /\S/) {
738 $line =~ s/\s*$//; # trim trailing spaces
739 print "$line\n";
744 # Close whichever file was open.
745 &html_jumppoints;
746 print "</body></html>\n";
747 select STDOUT;
748 close TEXT;
750 print "\n writing index file...";
751 open TEXT,">nasmdoci.html";
752 select TEXT;
753 &html_preamble(0);
754 print "<p align=center><a href=\"nasmdoc0.html\">Contents</a>\n";
755 print "<p>";
756 &html_index;
757 print "<p align=center><a href=\"nasmdoc0.html\">Contents</a>\n";
758 print "</body></html>\n";
759 select STDOUT;
760 close TEXT;
763 sub html_preamble {
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";
777 sub html_index {
778 my $itag, $a, @ientry, $sep, $w, $wd, $wprev, $line;
780 $chapternode = '';
781 foreach $itag (@itags) {
782 $ientry = $idxmap{$itag};
783 @a = @$ientry;
784 push @a, "n :";
785 $sep = 0;
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}";
790 $sep = 1;
792 $line = '';
793 do {
794 do { $w = &word_html(shift @a) } while $w eq "\001"; # nasty hack
795 $wd .= $wprev;
796 if ($w eq ' ' || $w eq '' || $w eq undef) {
797 if (length ($line . $wd) > 75) {
798 $line =~ s/\s*$//; # trim trailing spaces
799 print "$line\n";
800 $line = '';
801 $wd =~ s/^\s*//; # trim leading spaces
803 $line .= $wd;
804 $wd = '';
806 $wprev = $w;
807 } while ($w ne '' && $w ne undef);
808 if ($line =~ /\S/) {
809 $line =~ s/\s*$//; # trim trailing spaces
810 print "$line\n";
812 print "<br>\n";
816 sub word_html {
817 my ($w) = @_;
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);
824 $w = substr($w,2);
825 $pfx = $sfx = '';
826 $pfx = "<a href=\"$1\">", $sfx = "</a>", $w = $2
827 if $wmajt eq "w" && $w =~ /^<(.*)>(.*)$/;
828 $w =~ s/&/&amp;/g;
829 $w =~ s/</&lt;/g;
830 $w =~ s/>/&gt;/g;
831 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
832 return $pfx . $w . $sfx;
833 } elsif ($wtype eq "sp") {
834 return ' ';
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") {
840 return "<em>${w}";
841 } elsif ($wtype eq "ee") {
842 return "${w}</em>";
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
849 # another file.
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") {
858 return "</a>";
859 } elsif ($wmajt eq "i") {
860 return "\001";
861 } else {
862 die "panic in word_html: $wtype$w\n";
866 sub write_ps {
867 # This is called from the top level, so I won't bother using
868 # my or local.
870 # First, set up the font metric arrays.
871 &font_metrics;
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.
879 # Font codes are:
880 # n == Normal
881 # e == Emphasised
882 # c == Code
883 # ' ' == space (no following text required)
884 # '-' == dash (no following text required)
886 # Line types are:
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.
916 @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
921 # minus signs.
922 $pflags =~ /chap (.*) :(.*)/;
923 push @line, "nChapter", " ", "n$1:", " ";
924 foreach $i (@$pname) {
925 $ww = &word_ps($i);
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
934 # minus signs.
935 $pflags =~ /appn (.*) :(.*)/;
936 push @line, "nAppendix", " ", "n$1:", " ";
937 foreach $i (@$pname) {
938 $ww = &word_ps($i);
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 =~ /.... (.*) :(.*)/;
948 push @line, "n$1";
949 foreach $i (@$pname) {
950 $ww = &word_ps($i);
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 (.*) :(.*)/;
960 push @line, "n$1";
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.
970 $type = "cbeg";
971 foreach $i (@$pname) {
972 @$lname = ("c$i");
973 push @lnames, $lname++;
974 $lnamei = "idx" . $lname;
975 push @ltypes, $type;
976 $type = "cbdy";
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";
986 $bodytype = "bbdy";
987 $onetype = "bone";
988 $endtype = "bend";
989 } else {
990 $width = 468;
991 $type = $begtype = "nbeg";
992 $bodytype = "nbdy";
993 $onetype = "none";
994 $endtype = "nend";
996 @a = @$pname;
997 @line = @wd = ();
998 $linelen = 0;
999 $wprev = undef;
1000 do {
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;
1011 $type = $bodytype;
1012 @line = @lindex = ();
1013 $linelen = 0;
1014 shift @wd while $wd[0] eq ' '; # trim leading spaces
1016 push @line, @wd;
1017 $linelen += $wdlen;
1018 @wd = ();
1020 $wprev = $w;
1021 } while ($w ne '' && $w ne undef);
1022 if (@line) {
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;
1028 $type = $bodytype;
1030 $ltypes[$#ltypes] =
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)/) {
1048 @$clname = @$lname;
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:
1073 # cend nend bend
1074 # They are forced before line-types:
1075 # chap
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
1096 } else {
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.
1104 $break = 0;
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.
1118 if ($break) {
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;
1127 $pnum++;
1128 $i = $bpt;
1129 $bpt = -1;
1130 $pstart = $i+1;
1131 $plen = 0;
1132 $space = 0;
1134 $i++;
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/) {
1142 $j = pop @$lname;
1143 push @$lname, "n" . $lpages[$j+$contlen];
1147 # Having got page numbers for most stuff, generate an index.
1148 print "building index...";
1149 $iwid = 222;
1150 $sep = 12;
1151 $commaindent = 32;
1152 foreach $k (@itags) {
1153 @line = ();
1154 $cmd = "index";
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};
1161 @line = ();
1162 foreach $i (@idxhead) {
1163 $ww = &word_ps($i);
1164 push @line, $ww unless $ww eq "x";
1166 &ps_idxout("index",\@line,[]);
1167 $cmd = "iindex";
1168 @line = ();
1170 $cmd = "iindex", splice @idxentry,0,$commapos{$k} if $commanext{$k};
1171 foreach $i (@idxentry) {
1172 $ww = &word_ps($i);
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"
1177 if $len < -$sep;
1178 @pp = ();
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);
1187 @pp = ();
1188 @line = ();
1189 $cmd = "index";
1190 $len = $iwid - $sep;
1192 push @pp, @pnum;
1193 $len -= $pnumlen;
1195 &ps_idxout($cmd,\@line,\@pp) if (length @pp);
1196 $l1 = &len_ps(@line);
1197 $l2 = &len_ps($pp);
1199 $$idx_clname[$#$idx_clname] = "n" . $pnum; # fix up TOC entry for index
1201 print "writing file...";
1202 open PS,">nasmdoc.ps";
1203 select PS;
1204 $page = $lpages[0];
1205 &ps_header;
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]);
1211 $i = 0;
1212 while ($i <= $#psindex) {
1213 &ps_throw_pg($page, $pnum) if $page != $pnum;
1214 $page = $pnum++;
1215 $ypos = 0;
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) {
1222 $j = $i+1;
1223 $j++ while $psindex[$j] and ($psindex[$j][3] == 0); # find next break
1224 last COL if $j-$i > $l or $i > $#psindex;
1225 while ($i < $j) {
1226 &ps_out_line($y, $psindex[$i][0] eq "index" ? "idl$col" : "ldl$col",
1227 $psindex[$i][1]);
1228 &ps_out_line($y,"idr$col",$psindex[$i][2]);
1229 $i++;
1230 $y += $textht;
1231 $l--;
1234 last PAGE if $i > $#psindex;
1237 &ps_trailer;
1238 close PS;
1239 select STDOUT;
1242 sub ps_idxout {
1243 my ($cmd, $left, $right) = @_;
1244 my $break = 1;
1245 $break = 0
1246 if ($#psindex >= 0) and ( ($#$left < 0) or ($cmd eq "iindex") );
1247 push @psindex,[$cmd,[@$left],[@$right],$break];
1250 sub ps_header {
1251 @pshdr = (
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',
1266 '/chapter {',
1267 ' 100 620 moveto',
1268 ' {',
1269 ' dup 0 get',
1270 ' dup n eq {pop nc setfont} {',
1271 ' e eq {ec setfont} {cc setfont} ifelse',
1272 ' } ifelse',
1273 ' dup length 1 sub 1 exch getinterval show',
1274 ' } forall',
1275 ' 0 setlinecap 3 setlinewidth',
1276 ' newpath 100 610 moveto 468 0 rlineto stroke',
1277 '} def',
1278 '/heading {',
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',
1282 ' 100 y moveto',
1283 ' a dup length 1 sub 1 exch getinterval {',
1284 ' /s exch def',
1285 ' s 0 get',
1286 ' dup n eq {pop nh setfont} {',
1287 ' e eq {eh setfont} {ch setfont} ifelse',
1288 ' } ifelse',
1289 ' s s length 1 sub 1 exch getinterval show',
1290 ' } forall',
1291 '} def',
1292 '/subhead {',
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',
1296 ' 100 y moveto',
1297 ' a dup length 1 sub 1 exch getinterval {',
1298 ' /s exch def',
1299 ' s 0 get',
1300 ' dup n eq {pop ns setfont} {',
1301 ' e eq {es setfont} {cs setfont} ifelse',
1302 ' } ifelse',
1303 ' s s length 1 sub 1 exch getinterval show',
1304 ' } forall',
1305 '} def',
1306 '/disp { /j exch def',
1307 ' 568 exch sub exch 689 exch sub moveto',
1308 ' {',
1309 ' /s exch def',
1310 ' s 0 get',
1311 ' dup n eq {pop nf setfont} {',
1312 ' e eq {ef setfont} {cf setfont} ifelse',
1313 ' } ifelse',
1314 ' s s length 1 sub 1 exch getinterval show',
1315 ' s sp eq {j 0 rmoveto} if',
1316 ' } forall',
1317 '} def',
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',
1328 ' } if',
1329 ' } for',
1330 '} def',
1331 '/just { /w exch def /y exch def /a exch def',
1332 ' /jj w def /spaces 0 def',
1333 ' a {',
1334 ' /s exch def',
1335 ' s 0 get',
1336 ' dup n eq {pop nf setfont} {',
1337 ' e eq {ef setfont} {cf setfont} ifelse',
1338 ' } 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',
1342 ' } forall',
1343 ' a y w jj spaces spaces 0 eq {pop pop 0} {div} ifelse disp',
1344 '} def',
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',
1348 ' a {',
1349 ' /s exch def',
1350 ' s 0 get',
1351 ' dup n eq {pop nf setfont} {',
1352 ' e eq {ef setfont} {cf setfont} ifelse',
1353 ' } ifelse',
1354 ' s s length 1 sub 1 exch getinterval stringwidth pop',
1355 ' x add /x exch def',
1356 ' } forall',
1357 ' a y x 0 disp',
1358 '} def',
1359 '/left {0 disp} def',
1360 '/bullet {',
1361 ' nf setfont dup 100 exch 689 exch sub moveto (\267) show',
1362 '} def'
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(.*)$/;
1377 $pshdr = $2;
1378 print "$1\n";
1380 print "$pshdr\n" if $pshdr =~ /\S/;
1381 print "%%EndSetup\n";
1382 &ps_initpg($lpages[0]);
1385 sub ps_trailer {
1386 &ps_donepg;
1387 print "%%Trailer\nrestore\n%%EOF\n";
1390 sub ps_throw_pg {
1391 my ($oldpg, $newpg) = @_;
1392 &ps_donepg;
1393 &ps_initpg($newpg);
1396 sub ps_initpg {
1397 my ($pgnum) = @_;
1398 print "%%Page: $pgnum $pgnum\n";
1399 print "%%BeginPageSetup\nsave\n%%EndPageSetup\n";
1402 sub ps_donepg {
1403 print "%%PageTrailer\nrestore showpage\n";
1406 sub ps_out_line {
1407 my ($ypos,$ltype,$lname) = @_;
1408 my $c,$d,$wid;
1410 print "[";
1411 $col = 1;
1412 foreach $c (@$lname) {#
1413 $c= "n " if $c eq " ";
1414 $c = "n\261" if $c eq "-";
1415 $d = '';
1416 while (length $c) {
1417 $d .= $1, $c = $2 while $c =~ /^([ -'\*-\[\]-~]+)(.*)$/;
1418 while (1) {
1419 $d .= "\\$1", $c = $2, next if $c =~ /^([\\\(\)])(.*)$/;
1420 ($d .= sprintf "\\%3o",unpack("C",$1)), $c = $2, next
1421 if $c =~ /^([^ -~])(.*)$/;
1422 last;
1425 $d = "($d)";
1426 $col = 0, print "\n" if $col>0 && $col+length $d > 77;
1427 print $d;
1428 $col += length $d;
1430 print "\n" if $col > 60;
1431 print "]";
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/) {
1443 $wid = 468;
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") {
1448 printf "chapter\n";
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";
1459 sub word_ps {
1460 my ($w) = @_;
1461 my $wtype, $wmajt;
1463 return undef if $w eq '' || $w eq undef;
1465 $wtype = substr($w,0,2);
1466 $wmajt = substr($wtype,0,1);
1467 $w = substr($w,2);
1468 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
1469 if ($wmajt eq "n" || $wtype eq "w ") {
1470 return "n$w";
1471 } elsif ($wtype eq "sp") {
1472 return ' ';
1473 } elsif ($wtype eq "da") {
1474 return '-';
1475 } elsif ($wmajt eq "c" || $wtype eq "wc") {
1476 return "c$w";
1477 } elsif ($wmajt eq "e") {
1478 return "e$w";
1479 } elsif ($wmajt eq "x") {
1480 return "x";
1481 } elsif ($wtype eq "i ") {
1482 push @lindex, $w;
1483 return "x";
1484 } else {
1485 die "panic in word_ps: $wtype$w\n";
1489 sub len_ps {
1490 my (@line) = @_;
1491 my $l = 0;
1492 my $w, $size;
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];
1506 return $l;
1509 sub write_texi {
1510 # This is called from the top level, so I won't bother using
1511 # my or local.
1513 # Open file.
1514 print "writing file...";
1515 open TEXT,">nasmdoc.texi";
1516 select TEXT;
1518 # Preamble.
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";
1529 print "\n";
1530 print "\@ifinfo\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";
1533 print "\n";
1534 print "Copyright 1997 Simon Tatham\n";
1535 print "\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";
1539 print "\n";
1540 print "\@titlepage\n";
1541 print "\@title NASM: The Netwide Assembler\n";
1542 print "\@author Simon Tatham\n";
1543 print "\n";
1544 print "\@page\n";
1545 print "\@vskip 0pt plus 1filll\n";
1546 print "Copyright \@copyright{} 1997 Simon Tatham\n";
1547 print "\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";
1551 print "\n";
1552 print "\@node Top, $tstruct_next{'Top'}, (dir), (dir)\n";
1553 print "\@top\n";
1554 print "\n";
1555 print "\@ifinfo\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";
1560 $node = "Top";
1562 $bulleting = 0;
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.
1573 &texi_menu($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.
1586 &texi_menu($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.
1599 &texi_menu($node)
1600 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1601 $pflags =~ /.... (.*) :(.*)/;
1602 $node = "Section $1";
1603 $title = "$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;
1615 $i =~ s/\@/\@\@/g;
1616 $i =~ s/\{/\@\{/g;
1617 $i =~ s/\}/\@\}/g;
1618 print "$i\n";
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;
1625 print "\@item\n";
1627 $line = '';
1628 @a = @$pname;
1629 $wd = $wprev = '';
1630 do {
1631 do { $w = &word_texi(shift @a); } while $w eq "\001"; # hack
1632 $wd .= $wprev;
1633 if ($wprev =~ /-$/ || $w eq ' ' || $w eq '' || $w eq undef) {
1634 if (length ($line . $wd) > 75) {
1635 $line =~ s/\s*$//; # trim trailing spaces
1636 print "$line\n";
1637 $line = '';
1638 $wd =~ s/^\s*//; # trim leading spaces
1640 $line .= $wd;
1641 $wd = '';
1643 $wprev = $w;
1644 } while ($w ne '' && $w ne undef);
1645 if ($line =~ /\S/) {
1646 $line =~ s/\s*$//; # trim trailing spaces
1647 print "$line\n";
1652 # Write index.
1653 &texi_index;
1655 # Close file.
1656 print "\n\@contents\n\@bye\n";
1657 select STDOUT;
1658 close TEXT;
1661 # Side effect of this procedure: update global `texiwdlen' to be the length
1662 # in chars of the formatted version of the word.
1663 sub word_texi {
1664 my ($w) = @_;
1665 my $wtype, $wmajt;
1667 return undef if $w eq '' || $w eq undef;
1668 $wtype = substr($w,0,2);
1669 $wmajt = substr($wtype,0,1);
1670 $w = substr($w,2);
1671 $wlen = length $w;
1672 $w =~ s/\@/\@\@/g;
1673 $w =~ s/\{/\@\{/g;
1674 $w =~ s/\}/\@\}/g;
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 ") {
1678 $texiwdlen = $wlen;
1679 return $w;
1680 } elsif ($wtype eq "sp") {
1681 $texiwdlen = 1;
1682 return ' ';
1683 } elsif ($wtype eq "da") {
1684 $texiwdlen = 2;
1685 return '--';
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;
1694 return "${w}\}";
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
1701 return "\@ref\{";
1702 } elsif ($wtype eq "xe") {
1703 $texiwdlen = 0; # we don't need it in this case
1704 return "\}";
1705 } elsif ($wmajt eq "i") {
1706 $texiwdlen = 0; # we don't need it in this case
1707 return "\001";
1708 } else {
1709 die "panic in word_texi: $wtype$w\n";
1713 sub texi_menu {
1714 my ($topitem) = @_;
1715 my $item, $i, $mpname, $title, $wd;
1717 $item = $tstruct_next{$topitem};
1718 print "\@menu\n";
1719 while ($item) {
1720 $title = "";
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";
1733 sub texi_index {
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};
1743 @a = @$ientry;
1744 $item = '';
1745 $len = 0;
1746 foreach $i (@a) {
1747 $wd = &word_texi($i);
1748 $item .= $wd, $len += $texiwdlen unless $wd eq "\001";
1750 $i = 0;
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";
1760 sub write_hlp {
1761 # This is called from the top level, so I won't bother using
1762 # my or local.
1764 # Build the index-tag text forms.
1765 print "building index entries...";
1766 @hlp_index = map {
1767 my $i,$ww;
1768 my $ientry = $idxmap{$_};
1769 my $title = "";
1770 foreach $i (@$ientry) {
1771 $ww = &word_hlp($i,0);
1772 $title .= $ww unless $ww eq "\001";
1774 $title;
1775 } @itags;
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";
1787 close HPJ;
1789 # Open file.
1790 print "\n writing .rtf file...";
1791 open TEXT,">nasmdoc.rtf";
1792 select TEXT;
1794 # Preamble.
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";
1808 $node = "Top";
1809 $browse = 0;
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);
1817 print $newpar;
1818 $newpar = "\\par\\sb120\n";
1820 if ($ptype eq "chap") {
1821 # Chapter heading. Begin a new node.
1822 &hlp_menu($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";
1831 print "\\page\n";
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";
1841 print "$title\n";
1842 $newpar = "\\par\\pard\\plain\\sb120\n";
1843 } elsif ($ptype eq "appn") {
1844 # Appendix heading. Begin a new node.
1845 &hlp_menu($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";
1854 print "\\page\n";
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";
1864 print "$title\n";
1865 $newpar = "\\par\\pard\\plain\\sb120\n";
1866 } elsif ($ptype eq "head" || $ptype eq "subh") {
1867 # Heading or subheading. Begin a new node.
1868 &hlp_menu($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";
1877 print "\\page\n";
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";
1887 print "$title\n";
1888 $newpar = "\\par\\pard\\plain\\sb120\n";
1889 } elsif ($ptype eq "code") {
1890 # Code paragraph.
1891 print "\\keep\\f1\\sb120\n";
1892 foreach $i (@$pname) {
1893 warn "code line longer than 68 chars: $i\n" if length $i > 68;
1894 $i =~ s/\\/\\\\/g;
1895 $i =~ s/\{/\\\{/g;
1896 $i =~ s/\}/\\\}/g;
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";
1905 } else {
1906 $newpar = "\\par\\sb120\n";
1908 $line = '';
1909 @a = @$pname;
1910 $wd = $wprev = '';
1911 do {
1912 do { $w = &word_hlp((shift @a),1); } while $w eq "\001"; # hack
1913 $wd .= $wprev;
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
1918 $line = '';
1919 $wd =~ s/^\s*//; # trim leading spaces
1921 $line .= $wd;
1922 $wd = '';
1924 $wprev = $w;
1925 } while ($w ne '' && $w ne undef);
1926 if ($line =~ /\S/) {
1927 $line =~ s/\s*$//; # trim trailing spaces
1928 print "$line\n";
1933 # Close file.
1934 print "\\page}\n";
1935 select STDOUT;
1936 close TEXT;
1939 sub word_hlp {
1940 my ($w, $docode) = @_;
1941 my $wtype, $wmajt;
1943 return undef if $w eq '' || $w eq undef;
1944 $wtype = substr($w,0,2);
1945 $wmajt = substr($wtype,0,1);
1946 $w = substr($w,2);
1947 $w =~ s/\\/\\\\/g;
1948 $w =~ s/\{/\\\{/g;
1949 $w =~ s/\}/\\\}/g;
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 ") {
1953 return $w;
1954 } elsif ($wtype eq "sp") {
1955 return ' ';
1956 } elsif ($wtype eq "da") {
1957 return "\\'96";
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") {
1962 return "{\\i ${w}";
1963 } elsif ($wtype eq "ee") {
1964 return "${w}}";
1965 } elsif ($wtype eq "eo") {
1966 return "{\\i ${w}}";
1967 } elsif ($wtype eq "x ") {
1968 return "{\\uldb ";
1969 } elsif ($wtype eq "xe") {
1970 $w = &hlp_sectkw($w);
1971 return "}{\\v ${w}}";
1972 } elsif ($wmajt eq "i") {
1973 return "\001";
1974 } else {
1975 die "panic in word_hlp: $wtype$w\n";
1979 sub hlp_menu {
1980 my ($topitem) = @_;
1981 my $item, $kword, $i, $mpname, $title;
1983 $item = $tstruct_next{$topitem};
1984 print "\\li360\\fi-360\n";
1985 while ($item) {
1986 $title = "";
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";
1999 sub hlp_sectkw {
2000 my ($node) = @_;
2001 $node =~ tr/A-Z/a-z/;
2002 $node =~ tr/- ./___/;
2003 $node;
2006 sub hlp_keywords {
2007 my ($node) = @_;
2008 my $pfx = "K{\\footnote ";
2009 my $done = 0;
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.
2018 sub add_item {
2019 my ($item, $level) = @_;
2020 my $i;
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;
2031 push @nodes, $item;
2034 # PostScript font metric data. Used for line breaking.
2035 sub font_metrics {
2036 @timesr = (
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
2070 @timesi = (
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
2104 @courr = (
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