doc/changes.src: document the RDPID instruction
[nasm.git] / doc / rdsrc.pl
blobda9cf252df005cf4acde9bb07a892bedfc4adc15
1 #!/usr/bin/perl
2 ## --------------------------------------------------------------------------
3 ##
4 ## Copyright 1996-2016 The NASM Authors - All Rights Reserved
5 ## See the file AUTHORS included with the NASM distribution for
6 ## the specific copyright holders.
7 ##
8 ## Redistribution and use in source and binary forms, with or without
9 ## modification, are permitted provided that the following
10 ## conditions are met:
12 ## * Redistributions of source code must retain the above copyright
13 ## notice, this list of conditions and the following disclaimer.
14 ## * Redistributions in binary form must reproduce the above
15 ## copyright notice, this list of conditions and the following
16 ## disclaimer in the documentation and/or other materials provided
17 ## with the distribution.
19 ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
20 ## CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
21 ## INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 ## DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 ## NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 ## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 ## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 ## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 ## OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
31 ## EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 ## --------------------------------------------------------------------------
36 # Read the source-form of the NASM manual and generate the various
37 # output forms.
39 # TODO:
41 # Ellipsis support would be nice.
43 # Source-form features:
44 # ---------------------
46 # Bullet \b
47 # Bullets the paragraph. Rest of paragraph is indented to cope. In
48 # HTML, consecutive groups of bulleted paragraphs become unordered
49 # lists.
51 # Emphasis \e{foobar}
52 # produces `_foobar_' in text and italics in HTML, PS, RTF
54 # Inline code \c{foobar}
55 # produces ``foobar'' in text, and fixed-pitch font in HTML, PS, RTF
57 # Display code
58 # \c line one
59 # \c line two
60 # produces fixed-pitch font where appropriate, and doesn't break
61 # pages except sufficiently far into the middle of a display.
63 # Chapter, header and subheader
64 # \C{intro} Introduction
65 # \H{whatsnasm} What is NASM?
66 # \S{free} NASM Is Free
67 # dealt with as appropriate. Chapters begin on new sides, possibly
68 # even new _pages_. (Sub)?headers are good places to begin new
69 # pages. Just _after_ a (sub)?header isn't.
70 # The keywords can be substituted with \K and \k.
72 # Keyword \K{cintro} \k{cintro}
73 # Expands to `Chapter 1', `Section 1.1', `Section 1.1.1'. \K has an
74 # initial capital whereas \k doesn't. In HTML, will produce
75 # hyperlinks.
77 # Web link \W{http://foobar/}{text} or \W{mailto:me@here}\c{me@here}
78 # the \W prefix is ignored except in HTML; in HTML the last part
79 # becomes a hyperlink to the first part.
81 # Literals \{ \} \\
82 # In case it's necessary, they expand to the real versions.
84 # Nonbreaking hyphen \-
85 # Need more be said?
87 # Source comment \#
88 # Causes everything after it on the line to be ignored by the
89 # source-form processor.
91 # Indexable word \i{foobar} (or \i\e{foobar} or \i\c{foobar}, equally)
92 # makes word appear in index, referenced to that point
93 # \i\c comes up in code style even in the index; \i\e doesn't come
94 # up in emphasised style.
96 # Indexable non-displayed word \I{foobar} or \I\c{foobar}
97 # just as \i{foobar} except that nothing is displayed for it
99 # Index rewrite
100 # \IR{foobar} \c{foobar} operator, uses of
101 # tidies up the appearance in the index of something the \i or \I
102 # operator was applied to
104 # Index alias
105 # \IA{foobar}{bazquux}
106 # aliases one index tag (as might be supplied to \i or \I) to
107 # another, so that \I{foobar} has the effect of \I{bazquux}, and
108 # \i{foobar} has the effect of \I{bazquux}foobar
110 # Metadata
111 # \M{key}{something}
112 # defines document metadata, such as authorship, title and copyright;
113 # different output formats use this differently.
115 # Include subfile
116 # \&{filename}
117 # Includes filename. Recursion is allowed.
120 use File::Spec;
122 @include_path = ();
124 $diag = 1, shift @ARGV if $ARGV[0] eq "-d";
125 while ($ARGV[0] =~ /^\-[Ii](.*)$/) {
126 push(@include_path, $1);
127 shift;
130 $out_format = shift(@ARGV);
131 @files = @ARGV;
132 @files = ('-') unless(scalar(@files));
134 $| = 1;
136 $tstruct_previtem = $node = "Top";
137 $nodes = ($node);
138 $tstruct_level{$tstruct_previtem} = 0;
139 $tstruct_last[$tstruct_level{$tstruct_previtem}] = $tstruct_previtem;
140 $MAXLEVEL = 10; # really 3, but play safe ;-)
142 # Read the file; pass a paragraph at a time to the paragraph processor.
143 print "Reading input...";
144 $pname = "para000000";
145 @pnames = @pflags = ();
146 $para = undef;
147 foreach $file (@files) {
148 &include($file);
150 &got_para($para);
151 print "done.\n";
153 # Now we've read in the entire document and we know what all the
154 # heading keywords refer to. Go through and fix up the \k references.
155 print "Fixing up cross-references...";
156 &fixup_xrefs;
157 print "done.\n";
159 # Sort the index tags, according to the slightly odd order I've decided on.
160 print "Sorting index tags...";
161 &indexsort;
162 print "done.\n";
164 if ($diag) {
165 print "Writing index-diagnostic file...";
166 &indexdiag;
167 print "done.\n";
170 # OK. Write out the various output files.
171 if ($out_format eq 'txt') {
172 print "Producing text output: ";
173 &write_txt;
174 print "done.\n";
175 } elsif ($out_format eq 'html') {
176 print "Producing HTML output: ";
177 &write_html;
178 print "done.\n";
179 } elsif ($out_format eq 'texi') {
180 print "Producing Texinfo output: ";
181 &write_texi;
182 print "done.\n";
183 } elsif ($out_format eq 'hlp') {
184 print "Producing WinHelp output: ";
185 &write_hlp;
186 print "done.\n";
187 } elsif ($out_format eq 'dip') {
188 print "Producing Documentation Intermediate Paragraphs: ";
189 &write_dip;
190 print "done.\n";
191 } else {
192 die "$0: unknown output format: $out_format\n";
195 sub untabify($) {
196 my($s) = @_;
197 my $o = '';
198 my($c, $i, $p);
200 $p = 0;
201 for ($i = 0; $i < length($s); $i++) {
202 $c = substr($s, $i, 1);
203 if ($c eq "\t") {
204 do {
205 $o .= ' ';
206 $p++;
207 } while ($p & 7);
208 } else {
209 $o .= $c;
210 $p++;
213 return $o;
215 sub read_line {
216 local $_ = shift;
217 $_ = &untabify($_);
218 if (/\\& (\S+)/) {
219 &include($1);
220 } else {
221 &get_para($_);
224 sub get_para($_) {
225 chomp;
226 if (!/\S/ || /^\\(IA|IR|M)/) { # special case: \IA \IR \M imply new-paragraph
227 &got_para($para);
228 $para = undef;
230 if (/\S/) {
231 s/\\#.*$//; # strip comments
232 $para .= " " . $_;
235 sub include {
236 my $name = shift;
237 my $F;
239 if ($name eq '-') {
240 open($F, '<-'); # stdin
241 } else {
242 my $found = 0;
243 foreach my $idir ( File::Spec->curdir, @include_path ) {
244 my $fpath = File::Spec->catfile($idir, $name);
245 if (open($F, '<', $fpath)) {
246 $found = 1;
247 last;
250 die "Cannot open $name: $!\n" unless ($found);
252 while (defined($_ = <$F>)) {
253 &read_line($_);
255 close($F);
257 sub got_para {
258 local ($_) = @_;
259 my $pflags = "", $i, $w, $l, $t;
260 return if !/\S/;
262 @$pname = ();
264 # Strip off _leading_ spaces, then determine type of paragraph.
265 s/^\s*//;
266 $irewrite = undef;
267 if (/^\\c[^{]/) {
268 # A code paragraph. The paragraph-array will contain the simple
269 # strings which form each line of the paragraph.
270 $pflags = "code";
271 while (/^\\c (([^\\]|\\[^c])*)(.*)$/) {
272 $l = $1;
273 $_ = $3;
274 $l =~ s/\\\{/\{/g;
275 $l =~ s/\\\}/}/g;
276 $l =~ s/\\\\/\\/g;
277 push @$pname, $l;
279 $_ = ''; # suppress word-by-word code
280 } elsif (/^\\C/) {
281 # A chapter heading. Define the keyword and allocate a chapter
282 # number.
283 $cnum++;
284 $hnum = 0;
285 $snum = 0;
286 $xref = "chapter-$cnum";
287 $pflags = "chap $cnum :$xref";
288 die "badly formatted chapter heading: $_\n" if !/^\\C\{([^\}]*)\}\s*(.*)$/;
289 $refs{$1} = "chapter $cnum";
290 $node = "Chapter $cnum";
291 &add_item($node, 1);
292 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
293 $xrefs{$1} = $xref;
294 $_ = $2;
295 # the standard word-by-word code will happen next
296 } elsif (/^\\A/) {
297 # An appendix heading. Define the keyword and allocate an appendix
298 # letter.
299 $cnum++;
300 $cnum = 'A' if $cnum =~ /[0-9]+/;
301 $hnum = 0;
302 $snum = 0;
303 $xref = "appendix-$cnum";
304 $pflags = "appn $cnum :$xref";
305 die "badly formatted appendix heading: $_\n" if !/^\\A\{([^\}]*)}\s*(.*)$/;
306 $refs{$1} = "appendix $cnum";
307 $node = "Appendix $cnum";
308 &add_item($node, 1);
309 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
310 $xrefs{$1} = $xref;
311 $_ = $2;
312 # the standard word-by-word code will happen next
313 } elsif (/^\\H/) {
314 # A major heading. Define the keyword and allocate a section number.
315 $hnum++;
316 $snum = 0;
317 $xref = "section-$cnum.$hnum";
318 $pflags = "head $cnum.$hnum :$xref";
319 die "badly formatted heading: $_\n" if !/^\\[HP]{([^\}]*)}\s*(.*)$/;
320 $refs{$1} = "section $cnum.$hnum";
321 $node = "Section $cnum.$hnum";
322 &add_item($node, 2);
323 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
324 $xrefs{$1} = $xref;
325 $_ = $2;
326 # the standard word-by-word code will happen next
327 } elsif (/^\\S/) {
328 # A sub-heading. Define the keyword and allocate a section number.
329 $snum++;
330 $xref = "section-$cnum.$hnum.$snum";
331 $pflags = "subh $cnum.$hnum.$snum :$xref";
332 die "badly formatted subheading: $_\n" if !/^\\S\{([^\}]*)\}\s*(.*)$/;
333 $refs{$1} = "section $cnum.$hnum.$snum";
334 $node = "Section $cnum.$hnum.$snum";
335 &add_item($node, 3);
336 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
337 $xrefs{$1} = $xref;
338 $_ = $2;
339 # the standard word-by-word code will happen next
340 } elsif (/^\\IR/) {
341 # An index-rewrite.
342 die "badly formatted index rewrite: $_\n" if !/^\\IR\{([^\}]*)\}\s*(.*)$/;
343 $irewrite = $1;
344 $_ = $2;
345 # the standard word-by-word code will happen next
346 } elsif (/^\\IA/) {
347 # An index-alias.
348 die "badly formatted index alias: $_\n" if !/^\\IA\{([^\}]*)}\{([^\}]*)\}\s*$/;
349 $idxalias{$1} = $2;
350 return; # avoid word-by-word code
351 } elsif (/^\\M/) {
352 # Metadata
353 die "badly formed metadata: $_\n" if !/^\\M\{([^\}]*)}\{([^\}]*)\}\s*$/;
354 $metadata{$1} = $2;
355 return; # avoid word-by-word code
356 } elsif (/^\\b/) {
357 # A bulleted paragraph. Strip off the initial \b and let the
358 # word-by-word code take care of the rest.
359 $pflags = "bull";
360 s/^\\b\s*//;
361 } else {
362 # A normal paragraph. Just set $pflags: the word-by-word code does
363 # the rest.
364 $pflags = "norm";
367 # The word-by-word code: unless @$pname is already defined (which it
368 # will be in the case of a code paragraph), split the paragraph up
369 # into words and push each on @$pname.
371 # Each thing pushed on @$pname should have a two-character type
372 # code followed by the text.
374 # Type codes are:
375 # "n " for normal
376 # "da" for a dash
377 # "es" for first emphasised word in emphasised bit
378 # "e " for emphasised in mid-emphasised-bit
379 # "ee" for last emphasised word in emphasised bit
380 # "eo" for single (only) emphasised word
381 # "c " for code
382 # "k " for cross-ref
383 # "kK" for capitalised cross-ref
384 # "w " for Web link
385 # "wc" for code-type Web link
386 # "x " for beginning of resolved cross-ref; generates no visible output,
387 # and the text is the cross-reference code
388 # "xe" for end of resolved cross-ref; text is same as for "x ".
389 # "i " for point to be indexed: the text is the internal index into the
390 # index-items arrays
391 # "sp" for space
392 while (/\S/) {
393 s/^\s*//, push @$pname, "sp" if /^\s/;
394 $indexing = $qindex = 0;
395 if (/^(\\[iI])?\\c/) {
396 $qindex = 1 if $1 eq "\\I";
397 $indexing = 1, s/^\\[iI]// if $1;
398 s/^\\c//;
399 die "badly formatted \\c: \\c$_\n" if !/\{(([^\\}]|\\.)*)\}(.*)$/;
400 $w = $1;
401 $_ = $3;
402 $w =~ s/\\\{/\{/g;
403 $w =~ s/\\\}/\}/g;
404 $w =~ s/\\-/-/g;
405 $w =~ s/\\\\/\\/g;
406 (push @$pname,"i"),$lastp = $#$pname if $indexing;
407 push @$pname,"c $w" if !$qindex;
408 $$pname[$lastp] = &addidx($node, $w, "c $w") if $indexing;
409 } elsif (/^\\[iIe]/) {
410 /^(\\[iI])?(\\e)?/;
411 $emph = 0;
412 $qindex = 1 if $1 eq "\\I";
413 $indexing = 1, $type = "\\i" if $1;
414 $emph = 1, $type = "\\e" if $2;
415 s/^(\\[iI])?(\\e?)//;
416 die "badly formatted $type: $type$_\n" if !/\{(([^\\}]|\\.)*)\}(.*)$/;
417 $w = $1;
418 $_ = $3;
419 $w =~ s/\\\{/\{/g;
420 $w =~ s/\\\}/\}/g;
421 $w =~ s/\\-/-/g;
422 $w =~ s/\\\\/\\/g;
423 $t = $emph ? "es" : "n ";
424 @ientry = ();
425 (push @$pname,"i"),$lastp = $#$pname if $indexing;
426 foreach $i (split /\s+/,$w) { # \e and \i can be multiple words
427 push @$pname,"$t$i","sp" if !$qindex;
428 ($ii=$i) =~ tr/A-Z/a-z/, push @ientry,"n $ii","sp" if $indexing;
429 $t = $emph ? "e " : "n ";
431 $w =~ tr/A-Z/a-z/, pop @ientry if $indexing;
432 $$pname[$lastp] = &addidx($node, $w, @ientry) if $indexing;
433 pop @$pname if !$qindex; # remove final space
434 if (substr($$pname[$#$pname],0,2) eq "es" && !$qindex) {
435 substr($$pname[$#$pname],0,2) = "eo";
436 } elsif ($emph && !$qindex) {
437 substr($$pname[$#$pname],0,2) = "ee";
439 } elsif (/^\\[kK]/) {
440 $t = "k ";
441 $t = "kK" if /^\\K/;
442 s/^\\[kK]//;
443 die "badly formatted \\k: \\k$_\n" if !/\{([^\}]*)\}(.*)$/;
444 $_ = $2;
445 push @$pname,"$t$1";
446 } elsif (/^\\W/) {
447 s/^\\W//;
448 die "badly formatted \\W: \\W$_\n"
449 if !/\{([^\}]*)\}(\\i)?(\\c)?\{(([^\\}]|\\.)*)\}(.*)$/;
450 $l = $1;
451 $w = $4;
452 $_ = $6;
453 $t = "w ";
454 $t = "wc" if $3 eq "\\c";
455 $indexing = 1 if $2;
456 $w =~ s/\\\{/\{/g;
457 $w =~ s/\\\}/\}/g;
458 $w =~ s/\\-/-/g;
459 $w =~ s/\\\\/\\/g;
460 (push @$pname,"i"),$lastp = $#$pname if $indexing;
461 push @$pname,"$t<$l>$w";
462 $$pname[$lastp] = &addidx($node, $w, "c $w") if $indexing;
463 } else {
464 die "what the hell? $_\n" if !/^(([^\s\\\-]|\\[\\{}\-])*-?)(.*)$/;
465 die "painful death! $_\n" if !length $1;
466 $w = $1;
467 $_ = $3;
468 $w =~ s/\\\{/\{/g;
469 $w =~ s/\\\}/\}/g;
470 $w =~ s/\\-/-/g;
471 $w =~ s/\\\\/\\/g;
472 if ($w eq "-") {
473 push @$pname,"da";
474 } else {
475 push @$pname,"n $w";
479 if ($irewrite ne undef) {
480 &addidx(undef, $irewrite, @$pname);
481 @$pname = ();
482 } else {
483 push @pnames, $pname;
484 push @pflags, $pflags;
485 $pname++;
489 sub addidx {
490 my ($node, $text, @ientry) = @_;
491 $text = $idxalias{$text} || $text;
492 if ($node eq undef || !$idxmap{$text}) {
493 @$ientry = @ientry;
494 $idxmap{$text} = $ientry;
495 $ientry++;
497 if ($node) {
498 $idxnodes{$node,$text} = 1;
499 return "i $text";
503 sub indexsort {
504 my $iitem, $ientry, $i, $piitem, $pcval, $cval, $clrcval;
506 @itags = map { # get back the original data as the 1st elt of each list
507 $_->[0]
508 } sort { # compare auxiliary (non-first) elements of lists
509 $a->[1] cmp $b->[1] ||
510 $a->[2] cmp $b->[2] ||
511 $a->[0] cmp $b->[0]
512 } map { # transform array into list of 3-element lists
513 my $ientry = $idxmap{$_};
514 my $a = substr($$ientry[0],2);
515 $a =~ tr/A-Za-z0-9//cd;
516 [$_, uc($a), substr($$ientry[0],0,2)]
517 } keys %idxmap;
519 # Having done that, check for comma-hood.
520 $cval = 0;
521 foreach $iitem (@itags) {
522 $ientry = $idxmap{$iitem};
523 $clrcval = 1;
524 $pcval = $cval;
525 FL:for ($i=0; $i <= $#$ientry; $i++) {
526 if ($$ientry[$i] =~ /^(n .*,)(.*)/) {
527 $$ientry[$i] = $1;
528 splice @$ientry,$i+1,0,"n $2" if length $2;
529 $commapos{$iitem} = $i+1;
530 $cval = join("\002", @$ientry[0..$i]);
531 $clrcval = 0;
532 last FL;
535 $cval = undef if $clrcval;
536 $commanext{$iitem} = $commaafter{$piitem} = 1
537 if $cval and ($cval eq $pcval);
538 $piitem = $iitem;
542 sub indexdiag {
543 my $iitem,$ientry,$w,$ww,$foo,$node;
544 open INDEXDIAG,">index.diag";
545 foreach $iitem (@itags) {
546 $ientry = $idxmap{$iitem};
547 print INDEXDIAG "<$iitem> ";
548 foreach $w (@$ientry) {
549 $ww = &word_txt($w);
550 print INDEXDIAG $ww unless $ww eq "\001";
552 print INDEXDIAG ":";
553 $foo = " ";
554 foreach $node (@nodes) {
555 (print INDEXDIAG $foo,$node), $foo = ", " if $idxnodes{$node,$iitem};
557 print INDEXDIAG "\n";
559 close INDEXDIAG;
562 sub fixup_xrefs {
563 my $pname, $p, $i, $j, $k, $caps, @repl;
565 for ($p=0; $p<=$#pnames; $p++) {
566 next if $pflags[$p] eq "code";
567 $pname = $pnames[$p];
568 for ($i=$#$pname; $i >= 0; $i--) {
569 if ($$pname[$i] =~ /^k/) {
570 $k = $$pname[$i];
571 $caps = ($k =~ /^kK/);
572 $k = substr($k,2);
573 $repl = $refs{$k};
574 die "undefined keyword `$k'\n" unless $repl;
575 substr($repl,0,1) =~ tr/a-z/A-Z/ if $caps;
576 @repl = ();
577 push @repl,"x $xrefs{$k}";
578 foreach $j (split /\s+/,$repl) {
579 push @repl,"n $j";
580 push @repl,"sp";
582 pop @repl; # remove final space
583 push @repl,"xe$xrefs{$k}";
584 splice @$pname,$i,1,@repl;
590 sub write_txt {
591 # This is called from the top level, so I won't bother using
592 # my or local.
594 # Open file.
595 print "writing file...";
596 open TEXT,">nasmdoc.txt";
597 select TEXT;
599 # Preamble.
600 $title = "The Netwide Assembler: NASM";
601 $spaces = ' ' x ((75-(length $title))/2);
602 ($underscore = $title) =~ s/./=/g;
603 print "$spaces$title\n$spaces$underscore\n";
605 for ($para = 0; $para <= $#pnames; $para++) {
606 $pname = $pnames[$para];
607 $pflags = $pflags[$para];
608 $ptype = substr($pflags,0,4);
610 print "\n"; # always one of these before a new paragraph
612 if ($ptype eq "chap") {
613 # Chapter heading. "Chapter N: Title" followed by a line of
614 # minus signs.
615 $pflags =~ /chap (.*) :(.*)/;
616 $title = "Chapter $1: ";
617 foreach $i (@$pname) {
618 $ww = &word_txt($i);
619 $title .= $ww unless $ww eq "\001";
621 print "$title\n";
622 $title =~ s/./-/g;
623 print "$title\n";
624 } elsif ($ptype eq "appn") {
625 # Appendix heading. "Appendix N: Title" followed by a line of
626 # minus signs.
627 $pflags =~ /appn (.*) :(.*)/;
628 $title = "Appendix $1: ";
629 foreach $i (@$pname) {
630 $ww = &word_txt($i);
631 $title .= $ww unless $ww eq "\001";
633 print "$title\n";
634 $title =~ s/./-/g;
635 print "$title\n";
636 } elsif ($ptype eq "head" || $ptype eq "subh") {
637 # Heading or subheading. Just a number and some text.
638 $pflags =~ /.... (.*) :(.*)/;
639 $title = sprintf "%6s ", $1;
640 foreach $i (@$pname) {
641 $ww = &word_txt($i);
642 $title .= $ww unless $ww eq "\001";
644 print "$title\n";
645 } elsif ($ptype eq "code") {
646 # Code paragraph. Emit each line with a seven character indent.
647 foreach $i (@$pname) {
648 warn "code line longer than 68 chars: $i\n" if length $i > 68;
649 print ' 'x7, $i, "\n";
651 } elsif ($ptype eq "bull" || $ptype eq "norm") {
652 # Ordinary paragraph, optionally bulleted. We wrap, with ragged
653 # 75-char right margin and either 7 or 11 char left margin
654 # depending on bullets.
655 if ($ptype eq "bull") {
656 $line = ' 'x7 . '(*) ';
657 $next = ' 'x11;
658 } else {
659 $line = $next = ' 'x7;
661 @a = @$pname;
662 $wd = $wprev = '';
663 do {
664 do { $w = &word_txt(shift @a) } while $w eq "\001"; # nasty hack
665 $wd .= $wprev;
666 if ($wprev =~ /-$/ || $w eq ' ' || $w eq '' || $w eq undef) {
667 if (length ($line . $wd) > 75) {
668 $line =~ s/\s*$//; # trim trailing spaces
669 print "$line\n";
670 $line = $next;
671 $wd =~ s/^\s*//; # trim leading spaces
673 $line .= $wd;
674 $wd = '';
676 $wprev = $w;
677 } while ($w ne '' && $w ne undef);
678 if ($line =~ /\S/) {
679 $line =~ s/\s*$//; # trim trailing spaces
680 print "$line\n";
685 # Close file.
686 select STDOUT;
687 close TEXT;
690 sub word_txt {
691 my ($w) = @_;
692 my $wtype, $wmajt;
694 return undef if $w eq '' || $w eq undef;
695 $wtype = substr($w,0,2);
696 $wmajt = substr($wtype,0,1);
697 $w = substr($w,2);
698 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
699 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
700 return $w;
701 } elsif ($wtype eq "sp") {
702 return ' ';
703 } elsif ($wtype eq "da") {
704 return '-';
705 } elsif ($wmajt eq "c" || $wtype eq "wc") {
706 return "`${w}'";
707 } elsif ($wtype eq "es") {
708 return "_${w}";
709 } elsif ($wtype eq "ee") {
710 return "${w}_";
711 } elsif ($wtype eq "eo") {
712 return "_${w}_";
713 } elsif ($wmajt eq "x" || $wmajt eq "i") {
714 return "\001";
715 } else {
716 die "panic in word_txt: $wtype$w\n";
720 sub write_html {
721 # This is called from the top level, so I won't bother using
722 # my or local.
724 # Write contents file. Just the preamble, then a menu of links to the
725 # separate chapter files and the nodes therein.
726 print "writing contents file...";
727 open TEXT,">nasmdoc0.html";
728 select TEXT;
729 &html_preamble(0);
730 print "<p>This manual documents NASM, the Netwide Assembler: an assembler\n";
731 print "targetting the Intel x86 series of processors, with portable source.\n";
732 print "<p>";
733 for ($node = $tstruct_next{'Top'}; $node; $node = $tstruct_next{$node}) {
734 if ($tstruct_level{$node} == 1) {
735 # Invent a file name.
736 ($number = lc($xrefnodes{$node})) =~ s/.*-//;
737 $fname="nasmdocx.html";
738 substr($fname,8 - length $number, length $number) = $number;
739 $html_fnames{$node} = $fname;
740 $link = $fname;
741 print "<p>";
742 } else {
743 # Use the preceding filename plus a marker point.
744 $link = $fname . "#$xrefnodes{$node}";
746 $title = "$node: ";
747 $pname = $tstruct_pname{$node};
748 foreach $i (@$pname) {
749 $ww = &word_html($i);
750 $title .= $ww unless $ww eq "\001";
752 print "<a href=\"$link\">$title</a><br>\n";
754 print "<p><a href=\"nasmdoci.html\">Index</a>\n";
755 print "</body></html>\n";
756 select STDOUT;
757 close TEXT;
759 # Open a null file, to ensure output (eg random &html_jumppoints calls)
760 # goes _somewhere_.
761 print "writing chapter files...";
762 open TEXT,">/dev/null";
763 select TEXT;
764 $html_lastf = '';
766 $in_list = 0;
768 for ($para = 0; $para <= $#pnames; $para++) {
769 $pname = $pnames[$para];
770 $pflags = $pflags[$para];
771 $ptype = substr($pflags,0,4);
773 $in_list = 0, print "</ul>\n" if $in_list && $ptype ne "bull";
774 if ($ptype eq "chap") {
775 # Chapter heading. Begin a new file.
776 $pflags =~ /chap (.*) :(.*)/;
777 $title = "Chapter $1: ";
778 $xref = $2;
779 &html_jumppoints; print "</body></html>\n"; select STDOUT; close TEXT;
780 $html_lastf = $html_fnames{$chapternode};
781 $chapternode = $nodexrefs{$xref};
782 $html_nextf = $html_fnames{$tstruct_mnext{$chapternode}};
783 open TEXT,">$html_fnames{$chapternode}"; select TEXT; &html_preamble(1);
784 foreach $i (@$pname) {
785 $ww = &word_html($i);
786 $title .= $ww unless $ww eq "\001";
788 $h = "<h2><a name=\"$xref\">$title</a></h2>\n";
789 print $h; print FULL $h;
790 } elsif ($ptype eq "appn") {
791 # Appendix heading. Begin a new file.
792 $pflags =~ /appn (.*) :(.*)/;
793 $title = "Appendix $1: ";
794 $xref = $2;
795 &html_jumppoints; print "</body></html>\n"; select STDOUT; close TEXT;
796 $html_lastf = $html_fnames{$chapternode};
797 $chapternode = $nodexrefs{$xref};
798 $html_nextf = $html_fnames{$tstruct_mnext{$chapternode}};
799 open TEXT,">$html_fnames{$chapternode}"; select TEXT; &html_preamble(1);
800 foreach $i (@$pname) {
801 $ww = &word_html($i);
802 $title .= $ww unless $ww eq "\001";
804 print "<h2><a name=\"$xref\">$title</a></h2>\n";
805 } elsif ($ptype eq "head" || $ptype eq "subh") {
806 # Heading or subheading.
807 $pflags =~ /.... (.*) :(.*)/;
808 $hdr = ($ptype eq "subh" ? "h4" : "h3");
809 $title = $1 . " ";
810 $xref = $2;
811 foreach $i (@$pname) {
812 $ww = &word_html($i);
813 $title .= $ww unless $ww eq "\001";
815 print "<$hdr><a name=\"$xref\">$title</a></$hdr>\n";
816 } elsif ($ptype eq "code") {
817 # Code paragraph.
818 print "<p><pre>\n";
819 foreach $i (@$pname) {
820 $w = $i;
821 $w =~ s/&/&amp;/g;
822 $w =~ s/</&lt;/g;
823 $w =~ s/>/&gt;/g;
824 print $w, "\n";
826 print "</pre>\n";
827 } elsif ($ptype eq "bull" || $ptype eq "norm") {
828 # Ordinary paragraph, optionally bulleted. We wrap, with ragged
829 # 75-char right margin and either 7 or 11 char left margin
830 # depending on bullets.
831 if ($ptype eq "bull") {
832 $in_list = 1, print "<ul>\n" unless $in_list;
833 $line = '<li>';
834 } else {
835 $line = '<p>';
837 @a = @$pname;
838 $wd = $wprev = '';
839 do {
840 do { $w = &word_html(shift @a) } while $w eq "\001"; # nasty hack
841 $wd .= $wprev;
842 if ($w eq ' ' || $w eq '' || $w eq undef) {
843 if (length ($line . $wd) > 75) {
844 $line =~ s/\s*$//; # trim trailing spaces
845 print "$line\n";
846 $line = '';
847 $wd =~ s/^\s*//; # trim leading spaces
849 $line .= $wd;
850 $wd = '';
852 $wprev = $w;
853 } while ($w ne '' && $w ne undef);
854 if ($line =~ /\S/) {
855 $line =~ s/\s*$//; # trim trailing spaces
856 print "$line\n";
861 # Close whichever file was open.
862 &html_jumppoints;
863 print "</body></html>\n";
864 select STDOUT;
865 close TEXT;
867 print "\n writing index file...";
868 open TEXT,">nasmdoci.html";
869 select TEXT;
870 &html_preamble(0);
871 print "<p align=center><a href=\"nasmdoc0.html\">Contents</a>\n";
872 print "<p>";
873 &html_index;
874 print "<p align=center><a href=\"nasmdoc0.html\">Contents</a>\n";
875 print "</body></html>\n";
876 select STDOUT;
877 close TEXT;
880 sub html_preamble {
881 print "<html><head><title>NASM Manual</title></head>\n";
882 print "<body><h1 align=center>The Netwide Assembler: NASM</h1>\n\n";
883 &html_jumppoints if $_[0];
886 sub html_jumppoints {
887 print "<p align=center>";
888 print "<a href=\"$html_nextf\">Next Chapter</a> |\n" if $html_nextf;
889 print "<a href=\"$html_lastf\">Previous Chapter</a> |\n" if $html_lastf;
890 print "<a href=\"nasmdoc0.html\">Contents</a> |\n";
891 print "<a href=\"nasmdoci.html\">Index</a>\n";
894 sub html_index {
895 my $itag, $a, @ientry, $sep, $w, $wd, $wprev, $line;
897 $chapternode = '';
898 foreach $itag (@itags) {
899 $ientry = $idxmap{$itag};
900 @a = @$ientry;
901 push @a, "n :";
902 $sep = 0;
903 foreach $node (@nodes) {
904 next if !$idxnodes{$node,$itag};
905 push @a, "n ," if $sep;
906 push @a, "sp", "x $xrefnodes{$node}", "n $node", "xe$xrefnodes{$node}";
907 $sep = 1;
909 $line = '';
910 do {
911 do { $w = &word_html(shift @a) } while $w eq "\001"; # nasty hack
912 $wd .= $wprev;
913 if ($w eq ' ' || $w eq '' || $w eq undef) {
914 if (length ($line . $wd) > 75) {
915 $line =~ s/\s*$//; # trim trailing spaces
916 print "$line\n";
917 $line = '';
918 $wd =~ s/^\s*//; # trim leading spaces
920 $line .= $wd;
921 $wd = '';
923 $wprev = $w;
924 } while ($w ne '' && $w ne undef);
925 if ($line =~ /\S/) {
926 $line =~ s/\s*$//; # trim trailing spaces
927 print "$line\n";
929 print "<br>\n";
933 sub word_html {
934 my ($w) = @_;
935 my $wtype, $wmajt, $pfx, $sfx;
937 return undef if $w eq '' || $w eq undef;
939 $wtype = substr($w,0,2);
940 $wmajt = substr($wtype,0,1);
941 $w = substr($w,2);
942 $pfx = $sfx = '';
943 $pfx = "<a href=\"$1\">", $sfx = "</a>", $w = $2
944 if $wmajt eq "w" && $w =~ /^<(.*)>(.*)$/;
945 $w =~ s/&/&amp;/g;
946 $w =~ s/</&lt;/g;
947 $w =~ s/>/&gt;/g;
948 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
949 return $pfx . $w . $sfx;
950 } elsif ($wtype eq "sp") {
951 return ' ';
952 } elsif ($wtype eq "da") {
953 return '-'; # sadly, en-dashes are non-standard in HTML
954 } elsif ($wmajt eq "c" || $wtype eq "wc") {
955 return $pfx . "<code><nobr>${w}</nobr></code>" . $sfx;
956 } elsif ($wtype eq "es") {
957 return "<em>${w}";
958 } elsif ($wtype eq "ee") {
959 return "${w}</em>";
960 } elsif ($wtype eq "eo") {
961 return "<em>${w}</em>";
962 } elsif ($wtype eq "x ") {
963 # Magic: we must resolve the cross reference into file and marker
964 # parts, then dispose of the file part if it's us, and dispose of
965 # the marker part if the cross reference describes the top node of
966 # another file.
967 my $node = $nodexrefs{$w}; # find the node we're aiming at
968 my $level = $tstruct_level{$node}; # and its level
969 my $up = $node, $uplev = $level-1;
970 $up = $tstruct_up{$up} while $uplev--; # get top node of containing file
971 my $file = ($up ne $chapternode) ? $html_fnames{$up} : "";
972 my $marker = ($level == 1 and $file) ? "" : "#$w";
973 return "<a href=\"$file$marker\">";
974 } elsif ($wtype eq "xe") {
975 return "</a>";
976 } elsif ($wmajt eq "i") {
977 return "\001";
978 } else {
979 die "panic in word_html: $wtype$w\n";
983 sub write_texi {
984 # This is called from the top level, so I won't bother using
985 # my or local.
987 # Open file.
988 print "writing file...";
989 open TEXT,">nasmdoc.texi";
990 select TEXT;
992 # Preamble.
993 print "\\input texinfo \@c -*-texinfo-*-\n";
994 print "\@c \%**start of header\n";
995 print "\@setfilename ",$metadata{'infofile'},".info\n";
996 print "\@dircategory ",$metadata{'category'},"\n";
997 print "\@direntry\n";
998 printf "* %-28s %s.\n",
999 sprintf('%s: (%s).', $metadata{'infoname'}, $metadata{'infofile'}),
1000 $metadata{'infotitle'};
1001 print "\@end direntry\n";
1002 print "\@settitle ", $metadata{'title'},"\n";
1003 print "\@setchapternewpage odd\n";
1004 print "\@c \%**end of header\n";
1005 print "\n";
1006 print "\@ifinfo\n";
1007 print $metadata{'summary'}, "\n";
1008 print "\n";
1009 print "Copyright ",$metadata{'year'}," ",$metadata{'author'},"\n";
1010 print "\n";
1011 print $metadata{'license'}, "\n";
1012 print "\@end ifinfo\n";
1013 print "\n";
1014 print "\@titlepage\n";
1015 $title = $metadata{'title'};
1016 $title =~ s/ - / --- /g;
1017 print "\@title ${title}\n";
1018 print "\@author ",$metadata{'author'},"\n";
1019 print "\n";
1020 print "\@page\n";
1021 print "\@vskip 0pt plus 1filll\n";
1022 print "Copyright \@copyright{} ",$metadata{'year'},' ',$metadata{'author'},"\n";
1023 print "\n";
1024 print $metadata{'license'}, "\n";
1025 print "\@end titlepage\n";
1026 print "\n";
1027 print "\@node Top, $tstruct_next{'Top'}, (dir), (dir)\n";
1028 print "\@top ",$metadata{'infotitle'},"\n";
1029 print "\n";
1030 print "\@ifinfo\n";
1031 print $metadata{'summary'}, "\n";
1032 print "\@end ifinfo\n";
1034 $node = "Top";
1036 $bulleting = 0;
1037 for ($para = 0; $para <= $#pnames; $para++) {
1038 $pname = $pnames[$para];
1039 $pflags = $pflags[$para];
1040 $ptype = substr($pflags,0,4);
1042 $bulleting = 0, print "\@end itemize\n" if $bulleting && $ptype ne "bull";
1043 print "\n"; # always one of these before a new paragraph
1045 if ($ptype eq "chap") {
1046 # Chapter heading. Begin a new node.
1047 &texi_menu($node)
1048 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1049 $pflags =~ /chap (.*) :(.*)/;
1050 $node = "Chapter $1";
1051 $title = "Chapter $1: ";
1052 foreach $i (@$pname) {
1053 $ww = &word_texi($i);
1054 $title .= $ww unless $ww eq "\001";
1056 print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},";
1057 print " $tstruct_up{$node}\n\@unnumbered $title\n";
1058 } elsif ($ptype eq "appn") {
1059 # Appendix heading. Begin a new node.
1060 &texi_menu($node)
1061 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1062 $pflags =~ /appn (.*) :(.*)/;
1063 $node = "Appendix $1";
1064 $title = "Appendix $1: ";
1065 foreach $i (@$pname) {
1066 $ww = &word_texi($i);
1067 $title .= $ww unless $ww eq "\001";
1069 print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},";
1070 print " $tstruct_up{$node}\n\@unnumbered $title\n";
1071 } elsif ($ptype eq "head" || $ptype eq "subh") {
1072 # Heading or subheading. Begin a new node.
1073 &texi_menu($node)
1074 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1075 $pflags =~ /.... (.*) :(.*)/;
1076 $node = "Section $1";
1077 $title = "$1. ";
1078 foreach $i (@$pname) {
1079 $ww = &word_texi($i);
1080 $title .= $ww unless $ww eq "\001";
1082 print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},";
1083 print " $tstruct_up{$node}\n";
1084 $hdr = ($ptype eq "subh" ? "\@unnumberedsubsec" : "\@unnumberedsec");
1085 print "$hdr $title\n";
1086 } elsif ($ptype eq "code") {
1087 # Code paragraph. Surround with @example / @end example.
1088 print "\@example\n";
1089 foreach $i (@$pname) {
1090 warn "code line longer than 68 chars: $i\n" if length $i > 68;
1091 $i =~ s/\@/\@\@/g;
1092 $i =~ s/\{/\@\{/g;
1093 $i =~ s/\}/\@\}/g;
1094 print "$i\n";
1096 print "\@end example\n";
1097 } elsif ($ptype eq "bull" || $ptype eq "norm") {
1098 # Ordinary paragraph, optionally bulleted. We wrap, FWIW.
1099 if ($ptype eq "bull") {
1100 $bulleting = 1, print "\@itemize \@bullet\n" if !$bulleting;
1101 print "\@item\n";
1103 $line = '';
1104 @a = @$pname;
1105 $wd = $wprev = '';
1106 do {
1107 do { $w = &word_texi(shift @a); } while $w eq "\001"; # hack
1108 $wd .= $wprev;
1109 if ($wprev =~ /-$/ || $w eq ' ' || $w eq '' || $w eq undef) {
1110 if (length ($line . $wd) > 75) {
1111 $line =~ s/\s*$//; # trim trailing spaces
1112 print "$line\n";
1113 $line = '';
1114 $wd =~ s/^\s*//; # trim leading spaces
1116 $line .= $wd;
1117 $wd = '';
1119 $wprev = $w;
1120 } while ($w ne '' && $w ne undef);
1121 if ($line =~ /\S/) {
1122 $line =~ s/\s*$//; # trim trailing spaces
1123 print "$line\n";
1128 # Write index.
1129 &texi_index;
1131 # Close file.
1132 print "\n\@contents\n\@bye\n";
1133 select STDOUT;
1134 close TEXT;
1137 # Side effect of this procedure: update global `texiwdlen' to be the length
1138 # in chars of the formatted version of the word.
1139 sub word_texi {
1140 my ($w) = @_;
1141 my $wtype, $wmajt;
1143 return undef if $w eq '' || $w eq undef;
1144 $wtype = substr($w,0,2);
1145 $wmajt = substr($wtype,0,1);
1146 $w = substr($w,2);
1147 $wlen = length $w;
1148 $w =~ s/\@/\@\@/g;
1149 $w =~ s/\{/\@\{/g;
1150 $w =~ s/\}/\@\}/g;
1151 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
1152 substr($w,0,1) =~ tr/a-z/A-Z/, $capital = 0 if $capital;
1153 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
1154 $texiwdlen = $wlen;
1155 return $w;
1156 } elsif ($wtype eq "sp") {
1157 $texiwdlen = 1;
1158 return ' ';
1159 } elsif ($wtype eq "da") {
1160 $texiwdlen = 2;
1161 return '--';
1162 } elsif ($wmajt eq "c" || $wtype eq "wc") {
1163 $texiwdlen = 2 + $wlen;
1164 return "\@code\{$w\}";
1165 } elsif ($wtype eq "es") {
1166 $texiwdlen = 1 + $wlen;
1167 return "\@emph\{${w}";
1168 } elsif ($wtype eq "ee") {
1169 $texiwdlen = 1 + $wlen;
1170 return "${w}\}";
1171 } elsif ($wtype eq "eo") {
1172 $texiwdlen = 2 + $wlen;
1173 return "\@emph\{${w}\}";
1174 } elsif ($wtype eq "x ") {
1175 $texiwdlen = 0; # we don't need it in this case
1176 $capital = 1; # hack
1177 return "\@ref\{";
1178 } elsif ($wtype eq "xe") {
1179 $texiwdlen = 0; # we don't need it in this case
1180 return "\}";
1181 } elsif ($wmajt eq "i") {
1182 $texiwdlen = 0; # we don't need it in this case
1183 return "\001";
1184 } else {
1185 die "panic in word_texi: $wtype$w\n";
1189 sub texi_menu {
1190 my ($topitem) = @_;
1191 my $item, $i, $mpname, $title, $wd;
1193 $item = $tstruct_next{$topitem};
1194 print "\@menu\n";
1195 while ($item) {
1196 $title = "";
1197 $mpname = $tstruct_pname{$item};
1198 foreach $i (@$mpname) {
1199 $wd = &word_texi($i);
1200 $title .= $wd unless $wd eq "\001";
1202 print "* ${item}:: $title\n";
1203 $item = $tstruct_mnext{$item};
1205 print "* Index::\n" if $topitem eq "Top";
1206 print "\@end menu\n";
1209 sub texi_index {
1210 my $itag, $ientry, @a, $wd, $item, $len;
1211 my $subnums = "123456789ABCDEFGHIJKLMNOPQRSTU" .
1212 "VWXYZabcdefghijklmnopqrstuvwxyz";
1214 print "\@ifinfo\n\@node Index, , $FIXMElastnode, Top\n";
1215 print "\@unnumbered Index\n\n\@menu\n";
1217 foreach $itag (@itags) {
1218 $ientry = $idxmap{$itag};
1219 @a = @$ientry;
1220 $item = '';
1221 $len = 0;
1222 foreach $i (@a) {
1223 $wd = &word_texi($i);
1224 $item .= $wd, $len += $texiwdlen unless $wd eq "\001";
1226 $i = 0;
1227 foreach $node (@nodes) {
1228 next if !$idxnodes{$node,$itag};
1229 printf "* %s%s (%s): %s.\n",
1230 $item, " " x (40-$len), substr($subnums,$i++,1), $node;
1233 print "\@end menu\n\@end ifinfo\n";
1236 sub write_hlp {
1237 # This is called from the top level, so I won't bother using
1238 # my or local.
1240 # Build the index-tag text forms.
1241 print "building index entries...";
1242 @hlp_index = map {
1243 my $i,$ww;
1244 my $ientry = $idxmap{$_};
1245 my $title = "";
1246 foreach $i (@$ientry) {
1247 $ww = &word_hlp($i,0);
1248 $title .= $ww unless $ww eq "\001";
1250 $title;
1251 } @itags;
1253 # Write the HPJ project-description file.
1254 print "writing .hpj file...";
1255 open HPJ,">nasmdoc.hpj";
1256 print HPJ "[OPTIONS]\ncompress=true\n";
1257 print HPJ "title=NASM: The Netwide Assembler\noldkeyphrase=no\n\n";
1258 print HPJ "[FILES]\nnasmdoc.rtf\n\n";
1259 print HPJ "[CONFIG]\n";
1260 print HPJ 'CreateButton("btn_up", "&Up",'.
1261 ' "JumpContents(`nasmdoc.hlp'."'".')")';
1262 print HPJ "\nBrowseButtons()\n";
1263 close HPJ;
1265 # Open file.
1266 print "\n writing .rtf file...";
1267 open TEXT,">nasmdoc.rtf";
1268 select TEXT;
1270 # Preamble.
1271 print "{\\rtf1\\ansi{\\fonttbl\n";
1272 print "\\f0\\froman Times New Roman;\\f1\\fmodern Courier New;\n";
1273 print "\\f2\\fswiss Arial;\\f3\\ftech Wingdings}\\deff0\n";
1274 print "#{\\footnote Top}\n";
1275 print "\${\\footnote Contents}\n";
1276 print "+{\\footnote browse:00000}\n";
1277 print "!{\\footnote DisableButton(\"btn_up\")}\n";
1278 print "\\keepn\\f2\\b\\fs30\\sb0\n";
1279 print "NASM: The Netwide Assembler\n";
1280 print "\\par\\pard\\plain\\sb120\n";
1281 print "This file documents NASM, the Netwide Assembler: an assembler \n";
1282 print "targetting the Intel x86 series of processors, with portable source.\n";
1284 $node = "Top";
1285 $browse = 0;
1287 $newpar = "\\par\\sb120\n";
1288 for ($para = 0; $para <= $#pnames; $para++) {
1289 $pname = $pnames[$para];
1290 $pflags = $pflags[$para];
1291 $ptype = substr($pflags,0,4);
1293 print $newpar;
1294 $newpar = "\\par\\sb120\n";
1296 if ($ptype eq "chap") {
1297 # Chapter heading. Begin a new node.
1298 &hlp_menu($node)
1299 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1300 $pflags =~ /chap (.*) :(.*)/;
1301 $node = "Chapter $1";
1302 $title = $footnotetitle = "Chapter $1: ";
1303 foreach $i (@$pname) {
1304 $ww = &word_hlp($i,1);
1305 $title .= $ww, $footnotetitle .= &word_hlp($i,0) unless $ww eq "\001";
1307 print "\\page\n";
1308 printf "#{\\footnote %s}\n", &hlp_sectkw($node);
1309 print "\${\\footnote $footnotetitle}\n";
1310 printf "+{\\footnote browse:%05d}\n", ++$browse;
1311 printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," .
1312 "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n",
1313 &hlp_sectkw($tstruct_up{$node});
1314 print "EnableButton(\"btn_up\")}\n";
1315 &hlp_keywords($node);
1316 print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n";
1317 print "$title\n";
1318 $newpar = "\\par\\pard\\plain\\sb120\n";
1319 } elsif ($ptype eq "appn") {
1320 # Appendix heading. Begin a new node.
1321 &hlp_menu($node)
1322 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1323 $pflags =~ /appn (.*) :(.*)/;
1324 $node = "Appendix $1";
1325 $title = $footnotetitle = "Appendix $1: ";
1326 foreach $i (@$pname) {
1327 $ww = &word_hlp($i,1);
1328 $title .= $ww, $footnotetitle .= &word_hlp($i,0) unless $ww eq "\001";
1330 print "\\page\n";
1331 printf "#{\\footnote %s}\n", &hlp_sectkw($node);
1332 print "\${\\footnote $footnotetitle}\n";
1333 printf "+{\\footnote browse:%05d}\n", ++$browse;
1334 printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," .
1335 "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n",
1336 &hlp_sectkw($tstruct_up{$node});
1337 print "EnableButton(\"btn_up\")}\n";
1338 &hlp_keywords($node);
1339 print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n";
1340 print "$title\n";
1341 $newpar = "\\par\\pard\\plain\\sb120\n";
1342 } elsif ($ptype eq "head" || $ptype eq "subh") {
1343 # Heading or subheading. Begin a new node.
1344 &hlp_menu($node)
1345 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1346 $pflags =~ /.... (.*) :(.*)/;
1347 $node = "Section $1";
1348 $title = $footnotetitle = "$1. ";
1349 foreach $i (@$pname) {
1350 $ww = &word_hlp($i,1);
1351 $title .= $ww, $footnotetitle .= &word_hlp($i,0) unless $ww eq "\001";
1353 print "\\page\n";
1354 printf "#{\\footnote %s}\n", &hlp_sectkw($node);
1355 print "\${\\footnote $footnotetitle}\n";
1356 printf "+{\\footnote browse:%05d}\n", ++$browse;
1357 printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," .
1358 "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n",
1359 &hlp_sectkw($tstruct_up{$node});
1360 print "EnableButton(\"btn_up\")}\n";
1361 &hlp_keywords($node);
1362 print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n";
1363 print "$title\n";
1364 $newpar = "\\par\\pard\\plain\\sb120\n";
1365 } elsif ($ptype eq "code") {
1366 # Code paragraph.
1367 print "\\keep\\f1\\sb120\n";
1368 foreach $i (@$pname) {
1369 my $x = $i;
1370 warn "code line longer than 68 chars: $i\n" if length $i > 68;
1371 $x =~ s/\\/\\\\/g;
1372 $x =~ s/\{/\\\{/g;
1373 $x =~ s/\}/\\\}/g;
1374 print "$x\\par\\sb0\n";
1376 $newpar = "\\pard\\f0\\sb120\n";
1377 } elsif ($ptype eq "bull" || $ptype eq "norm") {
1378 # Ordinary paragraph, optionally bulleted. We wrap, FWIW.
1379 if ($ptype eq "bull") {
1380 print "\\tx360\\li360\\fi-360{\\f3\\'9F}\\tab\n";
1381 $newpar = "\\par\\pard\\sb120\n";
1382 } else {
1383 $newpar = "\\par\\sb120\n";
1385 $line = '';
1386 @a = @$pname;
1387 $wd = $wprev = '';
1388 do {
1389 do { $w = &word_hlp((shift @a),1); } while $w eq "\001"; # hack
1390 $wd .= $wprev;
1391 if ($w eq ' ' || $w eq '' || $w eq undef) {
1392 if (length ($line . $wd) > 75) {
1393 $line =~ s/\s*$//; # trim trailing spaces
1394 print "$line \n"; # and put one back
1395 $line = '';
1396 $wd =~ s/^\s*//; # trim leading spaces
1398 $line .= $wd;
1399 $wd = '';
1401 $wprev = $w;
1402 } while ($w ne '' && $w ne undef);
1403 if ($line =~ /\S/) {
1404 $line =~ s/\s*$//; # trim trailing spaces
1405 print "$line\n";
1410 # Close file.
1411 print "\\page}\n";
1412 select STDOUT;
1413 close TEXT;
1416 sub word_hlp {
1417 my ($w, $docode) = @_;
1418 my $wtype, $wmajt;
1420 return undef if $w eq '' || $w eq undef;
1421 $wtype = substr($w,0,2);
1422 $wmajt = substr($wtype,0,1);
1423 $w = substr($w,2);
1424 $w =~ s/\\/\\\\/g;
1425 $w =~ s/\{/\\\{/g;
1426 $w =~ s/\}/\\\}/g;
1427 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
1428 substr($w,0,length($w)-1) =~ s/-/\\\'AD/g if $wmajt ne "x"; #nonbreakhyphens
1429 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
1430 return $w;
1431 } elsif ($wtype eq "sp") {
1432 return ' ';
1433 } elsif ($wtype eq "da") {
1434 return "\\'96";
1435 } elsif ($wmajt eq "c" || $wtype eq "wc") {
1436 $w =~ s/ /\\\'A0/g; # make spaces non-breaking
1437 return $docode ? "{\\f1 ${w}}" : $w;
1438 } elsif ($wtype eq "es") {
1439 return "{\\i ${w}";
1440 } elsif ($wtype eq "ee") {
1441 return "${w}}";
1442 } elsif ($wtype eq "eo") {
1443 return "{\\i ${w}}";
1444 } elsif ($wtype eq "x ") {
1445 return "{\\uldb ";
1446 } elsif ($wtype eq "xe") {
1447 $w = &hlp_sectkw($w);
1448 return "}{\\v ${w}}";
1449 } elsif ($wmajt eq "i") {
1450 return "\001";
1451 } else {
1452 die "panic in word_hlp: $wtype$w\n";
1456 sub hlp_menu {
1457 my ($topitem) = @_;
1458 my $item, $kword, $i, $mpname, $title;
1460 $item = $tstruct_next{$topitem};
1461 print "\\li360\\fi-360\n";
1462 while ($item) {
1463 $title = "";
1464 $mpname = $tstruct_pname{$item};
1465 foreach $i (@$mpname) {
1466 $ww = &word_hlp($i, 0);
1467 $title .= $ww unless $ww eq "\001";
1469 $kword = &hlp_sectkw($item);
1470 print "{\\uldb ${item}: $title}{\\v $kword}\\par\\sb0\n";
1471 $item = $tstruct_mnext{$item};
1473 print "\\pard\\sb120\n";
1476 sub hlp_sectkw {
1477 my ($node) = @_;
1478 $node =~ tr/A-Z/a-z/;
1479 $node =~ tr/- ./___/;
1480 $node;
1483 sub hlp_keywords {
1484 my ($node) = @_;
1485 my $pfx = "K{\\footnote ";
1486 my $done = 0;
1487 foreach $i (0..$#itags) {
1488 (print $pfx,$hlp_index[$i]), $pfx = ";\n", $done++
1489 if $idxnodes{$node,$itags[$i]};
1491 print "}\n" if $done;
1494 # Make tree structures. $tstruct_* is top-level and global.
1495 sub add_item {
1496 my ($item, $level) = @_;
1497 my $i;
1499 $tstruct_pname{$item} = $pname;
1500 $tstruct_next{$tstruct_previtem} = $item;
1501 $tstruct_prev{$item} = $tstruct_previtem;
1502 $tstruct_level{$item} = $level;
1503 $tstruct_up{$item} = $tstruct_last[$level-1];
1504 $tstruct_mnext{$tstruct_last[$level]} = $item;
1505 $tstruct_last[$level] = $item;
1506 for ($i=$level+1; $i<$MAXLEVEL; $i++) { $tstruct_last[$i] = undef; }
1507 $tstruct_previtem = $item;
1508 push @nodes, $item;
1512 # This produces documentation intermediate paragraph format; this is
1513 # basically the digested output of the front end. Intended for use
1514 # by future backends, instead of putting it all in the same script.
1516 sub write_dip {
1517 open(PARAS, "> nasmdoc.dip");
1518 foreach $k (sort(keys(%metadata))) {
1519 print PARAS 'meta :', $k, "\n";
1520 print PARAS $metadata{$k},"\n";
1522 for ($para = 0; $para <= $#pnames; $para++) {
1523 print PARAS $pflags[$para], "\n";
1524 print PARAS join("\037", @{$pnames[$para]}, "\n");
1526 foreach $k (@itags) {
1527 print PARAS 'indx :', $k, "\n";
1528 print PARAS join("\037", @{$idxmap{$k}}), "\n";
1530 close(PARAS);