bin: Implement sectalign handler
[nasm/sigaren-mirror.git] / doc / rdsrc.pl
blobde3a862fa99dc1a719acbb839ccdd07a2f3f942d
1 #!/usr/bin/perl
2 ## --------------------------------------------------------------------------
3 ##
4 ## Copyright 1996-2009 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.
18 ##
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 IO::File;
122 $diag = 1, shift @ARGV if $ARGV[0] eq "-d";
124 ($out_format) = @ARGV;
126 $| = 1;
128 $tstruct_previtem = $node = "Top";
129 $nodes = ($node);
130 $tstruct_level{$tstruct_previtem} = 0;
131 $tstruct_last[$tstruct_level{$tstruct_previtem}] = $tstruct_previtem;
132 $MAXLEVEL = 10; # really 3, but play safe ;-)
134 # Read the file; pass a paragraph at a time to the paragraph processor.
135 print "Reading input...";
136 $pname = "para000000";
137 @pnames = @pflags = ();
138 $para = undef;
139 while (defined($_ = <STDIN>)) {
140 $_ = &untabify($_);
141 &check_include($_);
143 &got_para($para);
144 print "done.\n";
146 # Now we've read in the entire document and we know what all the
147 # heading keywords refer to. Go through and fix up the \k references.
148 print "Fixing up cross-references...";
149 &fixup_xrefs;
150 print "done.\n";
152 # Sort the index tags, according to the slightly odd order I've decided on.
153 print "Sorting index tags...";
154 &indexsort;
155 print "done.\n";
157 if ($diag) {
158 print "Writing index-diagnostic file...";
159 &indexdiag;
160 print "done.\n";
163 # OK. Write out the various output files.
164 if ($out_format eq 'txt') {
165 print "Producing text output: ";
166 &write_txt;
167 print "done.\n";
168 } elsif ($out_format eq 'html') {
169 print "Producing HTML output: ";
170 &write_html;
171 print "done.\n";
172 } elsif ($out_format eq 'texi') {
173 print "Producing Texinfo output: ";
174 &write_texi;
175 print "done.\n";
176 } elsif ($out_format eq 'hlp') {
177 print "Producing WinHelp output: ";
178 &write_hlp;
179 print "done.\n";
180 } elsif ($out_format eq 'dip') {
181 print "Producing Documentation Intermediate Paragraphs: ";
182 &write_dip;
183 print "done.\n";
184 } else {
185 die "$0: unknown output format: $out_format\n";
188 sub untabify($) {
189 my($s) = @_;
190 my $o = '';
191 my($c, $i, $p);
193 $p = 0;
194 for ($i = 0; $i < length($s); $i++) {
195 $c = substr($s, $i, 1);
196 if ($c eq "\t") {
197 do {
198 $o .= ' ';
199 $p++;
200 } while ($p & 7);
201 } else {
202 $o .= $c;
203 $p++;
206 return $o;
208 sub check_include {
209 local $_ = shift;
210 if (/\\& (\S+)/) {
211 &include($1);
212 } else {
213 &get_para($_);
216 sub get_para($_) {
217 chomp;
218 if (!/\S/ || /^\\(IA|IR|M)/) { # special case: \IA \IR \M imply new-paragraph
219 &got_para($para);
220 $para = undef;
222 if (/\S/) {
223 s/\\#.*$//; # strip comments
224 $para .= " " . $_;
227 sub include {
228 my $name = shift;
229 my $F = IO::File->new($name)
230 or die "Cannot open $name: $!";
231 while (<$F>) {
232 &check_include($_);
235 sub got_para {
236 local ($_) = @_;
237 my $pflags = "", $i, $w, $l, $t;
238 return if !/\S/;
240 @$pname = ();
242 # Strip off _leading_ spaces, then determine type of paragraph.
243 s/^\s*//;
244 $irewrite = undef;
245 if (/^\\c[^{]/) {
246 # A code paragraph. The paragraph-array will contain the simple
247 # strings which form each line of the paragraph.
248 $pflags = "code";
249 while (/^\\c (([^\\]|\\[^c])*)(.*)$/) {
250 $l = $1;
251 $_ = $3;
252 $l =~ s/\\{/{/g;
253 $l =~ s/\\}/}/g;
254 $l =~ s/\\\\/\\/g;
255 push @$pname, $l;
257 $_ = ''; # suppress word-by-word code
258 } elsif (/^\\C/) {
259 # A chapter heading. Define the keyword and allocate a chapter
260 # number.
261 $cnum++;
262 $hnum = 0;
263 $snum = 0;
264 $xref = "chapter-$cnum";
265 $pflags = "chap $cnum :$xref";
266 die "badly formatted chapter heading: $_\n" if !/^\\C{([^}]*)}\s*(.*)$/;
267 $refs{$1} = "chapter $cnum";
268 $node = "Chapter $cnum";
269 &add_item($node, 1);
270 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
271 $xrefs{$1} = $xref;
272 $_ = $2;
273 # the standard word-by-word code will happen next
274 } elsif (/^\\A/) {
275 # An appendix heading. Define the keyword and allocate an appendix
276 # letter.
277 $cnum++;
278 $cnum = 'A' if $cnum =~ /[0-9]+/;
279 $hnum = 0;
280 $snum = 0;
281 $xref = "appendix-$cnum";
282 $pflags = "appn $cnum :$xref";
283 die "badly formatted appendix heading: $_\n" if !/^\\A{([^}]*)}\s*(.*)$/;
284 $refs{$1} = "appendix $cnum";
285 $node = "Appendix $cnum";
286 &add_item($node, 1);
287 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
288 $xrefs{$1} = $xref;
289 $_ = $2;
290 # the standard word-by-word code will happen next
291 } elsif (/^\\H/) {
292 # A major heading. Define the keyword and allocate a section number.
293 $hnum++;
294 $snum = 0;
295 $xref = "section-$cnum.$hnum";
296 $pflags = "head $cnum.$hnum :$xref";
297 die "badly formatted heading: $_\n" if !/^\\[HP]{([^}]*)}\s*(.*)$/;
298 $refs{$1} = "section $cnum.$hnum";
299 $node = "Section $cnum.$hnum";
300 &add_item($node, 2);
301 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
302 $xrefs{$1} = $xref;
303 $_ = $2;
304 # the standard word-by-word code will happen next
305 } elsif (/^\\S/) {
306 # A sub-heading. Define the keyword and allocate a section number.
307 $snum++;
308 $xref = "section-$cnum.$hnum.$snum";
309 $pflags = "subh $cnum.$hnum.$snum :$xref";
310 die "badly formatted subheading: $_\n" if !/^\\S{([^}]*)}\s*(.*)$/;
311 $refs{$1} = "section $cnum.$hnum.$snum";
312 $node = "Section $cnum.$hnum.$snum";
313 &add_item($node, 3);
314 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
315 $xrefs{$1} = $xref;
316 $_ = $2;
317 # the standard word-by-word code will happen next
318 } elsif (/^\\IR/) {
319 # An index-rewrite.
320 die "badly formatted index rewrite: $_\n" if !/^\\IR{([^}]*)}\s*(.*)$/;
321 $irewrite = $1;
322 $_ = $2;
323 # the standard word-by-word code will happen next
324 } elsif (/^\\IA/) {
325 # An index-alias.
326 die "badly formatted index alias: $_\n" if !/^\\IA{([^}]*)}{([^}]*)}\s*$/;
327 $idxalias{$1} = $2;
328 return; # avoid word-by-word code
329 } elsif (/^\\M/) {
330 # Metadata
331 die "badly formed metadata: $_\n" if !/^\\M{([^}]*)}{([^}]*)}\s*$/;
332 $metadata{$1} = $2;
333 return; # avoid word-by-word code
334 } elsif (/^\\b/) {
335 # A bulleted paragraph. Strip off the initial \b and let the
336 # word-by-word code take care of the rest.
337 $pflags = "bull";
338 s/^\\b\s*//;
339 } else {
340 # A normal paragraph. Just set $pflags: the word-by-word code does
341 # the rest.
342 $pflags = "norm";
345 # The word-by-word code: unless @$pname is already defined (which it
346 # will be in the case of a code paragraph), split the paragraph up
347 # into words and push each on @$pname.
349 # Each thing pushed on @$pname should have a two-character type
350 # code followed by the text.
352 # Type codes are:
353 # "n " for normal
354 # "da" for a dash
355 # "es" for first emphasised word in emphasised bit
356 # "e " for emphasised in mid-emphasised-bit
357 # "ee" for last emphasised word in emphasised bit
358 # "eo" for single (only) emphasised word
359 # "c " for code
360 # "k " for cross-ref
361 # "kK" for capitalised cross-ref
362 # "w " for Web link
363 # "wc" for code-type Web link
364 # "x " for beginning of resolved cross-ref; generates no visible output,
365 # and the text is the cross-reference code
366 # "xe" for end of resolved cross-ref; text is same as for "x ".
367 # "i " for point to be indexed: the text is the internal index into the
368 # index-items arrays
369 # "sp" for space
370 while (/\S/) {
371 s/^\s*//, push @$pname, "sp" if /^\s/;
372 $indexing = $qindex = 0;
373 if (/^(\\[iI])?\\c/) {
374 $qindex = 1 if $1 eq "\\I";
375 $indexing = 1, s/^\\[iI]// if $1;
376 s/^\\c//;
377 die "badly formatted \\c: \\c$_\n" if !/{(([^\\}]|\\.)*)}(.*)$/;
378 $w = $1;
379 $_ = $3;
380 $w =~ s/\\{/{/g;
381 $w =~ s/\\}/}/g;
382 $w =~ s/\\-/-/g;
383 $w =~ s/\\\\/\\/g;
384 (push @$pname,"i"),$lastp = $#$pname if $indexing;
385 push @$pname,"c $w" if !$qindex;
386 $$pname[$lastp] = &addidx($node, $w, "c $w") if $indexing;
387 } elsif (/^\\[iIe]/) {
388 /^(\\[iI])?(\\e)?/;
389 $emph = 0;
390 $qindex = 1 if $1 eq "\\I";
391 $indexing = 1, $type = "\\i" if $1;
392 $emph = 1, $type = "\\e" if $2;
393 s/^(\\[iI])?(\\e?)//;
394 die "badly formatted $type: $type$_\n" if !/{(([^\\}]|\\.)*)}(.*)$/;
395 $w = $1;
396 $_ = $3;
397 $w =~ s/\\{/{/g;
398 $w =~ s/\\}/}/g;
399 $w =~ s/\\-/-/g;
400 $w =~ s/\\\\/\\/g;
401 $t = $emph ? "es" : "n ";
402 @ientry = ();
403 (push @$pname,"i"),$lastp = $#$pname if $indexing;
404 foreach $i (split /\s+/,$w) { # \e and \i can be multiple words
405 push @$pname,"$t$i","sp" if !$qindex;
406 ($ii=$i) =~ tr/A-Z/a-z/, push @ientry,"n $ii","sp" if $indexing;
407 $t = $emph ? "e " : "n ";
409 $w =~ tr/A-Z/a-z/, pop @ientry if $indexing;
410 $$pname[$lastp] = &addidx($node, $w, @ientry) if $indexing;
411 pop @$pname if !$qindex; # remove final space
412 if (substr($$pname[$#$pname],0,2) eq "es" && !$qindex) {
413 substr($$pname[$#$pname],0,2) = "eo";
414 } elsif ($emph && !$qindex) {
415 substr($$pname[$#$pname],0,2) = "ee";
417 } elsif (/^\\[kK]/) {
418 $t = "k ";
419 $t = "kK" if /^\\K/;
420 s/^\\[kK]//;
421 die "badly formatted \\k: \\c$_\n" if !/{([^}]*)}(.*)$/;
422 $_ = $2;
423 push @$pname,"$t$1";
424 } elsif (/^\\W/) {
425 s/^\\W//;
426 die "badly formatted \\W: \\W$_\n"
427 if !/{([^}]*)}(\\i)?(\\c)?{(([^\\}]|\\.)*)}(.*)$/;
428 $l = $1;
429 $w = $4;
430 $_ = $6;
431 $t = "w ";
432 $t = "wc" if $3 eq "\\c";
433 $indexing = 1 if $2;
434 $w =~ s/\\{/{/g;
435 $w =~ s/\\}/}/g;
436 $w =~ s/\\-/-/g;
437 $w =~ s/\\\\/\\/g;
438 (push @$pname,"i"),$lastp = $#$pname if $indexing;
439 push @$pname,"$t<$l>$w";
440 $$pname[$lastp] = &addidx($node, $w, "c $w") if $indexing;
441 } else {
442 die "what the hell? $_\n" if !/^(([^\s\\\-]|\\[\\{}\-])*-?)(.*)$/;
443 die "painful death! $_\n" if !length $1;
444 $w = $1;
445 $_ = $3;
446 $w =~ s/\\{/{/g;
447 $w =~ s/\\}/}/g;
448 $w =~ s/\\-/-/g;
449 $w =~ s/\\\\/\\/g;
450 if ($w eq "-") {
451 push @$pname,"da";
452 } else {
453 push @$pname,"n $w";
457 if ($irewrite ne undef) {
458 &addidx(undef, $irewrite, @$pname);
459 @$pname = ();
460 } else {
461 push @pnames, $pname;
462 push @pflags, $pflags;
463 $pname++;
467 sub addidx {
468 my ($node, $text, @ientry) = @_;
469 $text = $idxalias{$text} || $text;
470 if ($node eq undef || !$idxmap{$text}) {
471 @$ientry = @ientry;
472 $idxmap{$text} = $ientry;
473 $ientry++;
475 if ($node) {
476 $idxnodes{$node,$text} = 1;
477 return "i $text";
481 sub indexsort {
482 my $iitem, $ientry, $i, $piitem, $pcval, $cval, $clrcval;
484 @itags = map { # get back the original data as the 1st elt of each list
485 $_->[0]
486 } sort { # compare auxiliary (non-first) elements of lists
487 $a->[1] cmp $b->[1] ||
488 $a->[2] cmp $b->[2] ||
489 $a->[0] cmp $b->[0]
490 } map { # transform array into list of 3-element lists
491 my $ientry = $idxmap{$_};
492 my $a = substr($$ientry[0],2);
493 $a =~ tr/A-Za-z0-9//cd;
494 [$_, uc($a), substr($$ientry[0],0,2)]
495 } keys %idxmap;
497 # Having done that, check for comma-hood.
498 $cval = 0;
499 foreach $iitem (@itags) {
500 $ientry = $idxmap{$iitem};
501 $clrcval = 1;
502 $pcval = $cval;
503 FL:for ($i=0; $i <= $#$ientry; $i++) {
504 if ($$ientry[$i] =~ /^(n .*,)(.*)/) {
505 $$ientry[$i] = $1;
506 splice @$ientry,$i+1,0,"n $2" if length $2;
507 $commapos{$iitem} = $i+1;
508 $cval = join("\002", @$ientry[0..$i]);
509 $clrcval = 0;
510 last FL;
513 $cval = undef if $clrcval;
514 $commanext{$iitem} = $commaafter{$piitem} = 1
515 if $cval and ($cval eq $pcval);
516 $piitem = $iitem;
520 sub indexdiag {
521 my $iitem,$ientry,$w,$ww,$foo,$node;
522 open INDEXDIAG,">index.diag";
523 foreach $iitem (@itags) {
524 $ientry = $idxmap{$iitem};
525 print INDEXDIAG "<$iitem> ";
526 foreach $w (@$ientry) {
527 $ww = &word_txt($w);
528 print INDEXDIAG $ww unless $ww eq "\001";
530 print INDEXDIAG ":";
531 $foo = " ";
532 foreach $node (@nodes) {
533 (print INDEXDIAG $foo,$node), $foo = ", " if $idxnodes{$node,$iitem};
535 print INDEXDIAG "\n";
537 close INDEXDIAG;
540 sub fixup_xrefs {
541 my $pname, $p, $i, $j, $k, $caps, @repl;
543 for ($p=0; $p<=$#pnames; $p++) {
544 next if $pflags[$p] eq "code";
545 $pname = $pnames[$p];
546 for ($i=$#$pname; $i >= 0; $i--) {
547 if ($$pname[$i] =~ /^k/) {
548 $k = $$pname[$i];
549 $caps = ($k =~ /^kK/);
550 $k = substr($k,2);
551 $repl = $refs{$k};
552 die "undefined keyword `$k'\n" unless $repl;
553 substr($repl,0,1) =~ tr/a-z/A-Z/ if $caps;
554 @repl = ();
555 push @repl,"x $xrefs{$k}";
556 foreach $j (split /\s+/,$repl) {
557 push @repl,"n $j";
558 push @repl,"sp";
560 pop @repl; # remove final space
561 push @repl,"xe$xrefs{$k}";
562 splice @$pname,$i,1,@repl;
568 sub write_txt {
569 # This is called from the top level, so I won't bother using
570 # my or local.
572 # Open file.
573 print "writing file...";
574 open TEXT,">nasmdoc.txt";
575 select TEXT;
577 # Preamble.
578 $title = "The Netwide Assembler: NASM";
579 $spaces = ' ' x ((75-(length $title))/2);
580 ($underscore = $title) =~ s/./=/g;
581 print "$spaces$title\n$spaces$underscore\n";
583 for ($para = 0; $para <= $#pnames; $para++) {
584 $pname = $pnames[$para];
585 $pflags = $pflags[$para];
586 $ptype = substr($pflags,0,4);
588 print "\n"; # always one of these before a new paragraph
590 if ($ptype eq "chap") {
591 # Chapter heading. "Chapter N: Title" followed by a line of
592 # minus signs.
593 $pflags =~ /chap (.*) :(.*)/;
594 $title = "Chapter $1: ";
595 foreach $i (@$pname) {
596 $ww = &word_txt($i);
597 $title .= $ww unless $ww eq "\001";
599 print "$title\n";
600 $title =~ s/./-/g;
601 print "$title\n";
602 } elsif ($ptype eq "appn") {
603 # Appendix heading. "Appendix N: Title" followed by a line of
604 # minus signs.
605 $pflags =~ /appn (.*) :(.*)/;
606 $title = "Appendix $1: ";
607 foreach $i (@$pname) {
608 $ww = &word_txt($i);
609 $title .= $ww unless $ww eq "\001";
611 print "$title\n";
612 $title =~ s/./-/g;
613 print "$title\n";
614 } elsif ($ptype eq "head" || $ptype eq "subh") {
615 # Heading or subheading. Just a number and some text.
616 $pflags =~ /.... (.*) :(.*)/;
617 $title = sprintf "%6s ", $1;
618 foreach $i (@$pname) {
619 $ww = &word_txt($i);
620 $title .= $ww unless $ww eq "\001";
622 print "$title\n";
623 } elsif ($ptype eq "code") {
624 # Code paragraph. Emit each line with a seven character indent.
625 foreach $i (@$pname) {
626 warn "code line longer than 68 chars: $i\n" if length $i > 68;
627 print ' 'x7, $i, "\n";
629 } elsif ($ptype eq "bull" || $ptype eq "norm") {
630 # Ordinary paragraph, optionally bulleted. We wrap, with ragged
631 # 75-char right margin and either 7 or 11 char left margin
632 # depending on bullets.
633 if ($ptype eq "bull") {
634 $line = ' 'x7 . '(*) ';
635 $next = ' 'x11;
636 } else {
637 $line = $next = ' 'x7;
639 @a = @$pname;
640 $wd = $wprev = '';
641 do {
642 do { $w = &word_txt(shift @a) } while $w eq "\001"; # nasty hack
643 $wd .= $wprev;
644 if ($wprev =~ /-$/ || $w eq ' ' || $w eq '' || $w eq undef) {
645 if (length ($line . $wd) > 75) {
646 $line =~ s/\s*$//; # trim trailing spaces
647 print "$line\n";
648 $line = $next;
649 $wd =~ s/^\s*//; # trim leading spaces
651 $line .= $wd;
652 $wd = '';
654 $wprev = $w;
655 } while ($w ne '' && $w ne undef);
656 if ($line =~ /\S/) {
657 $line =~ s/\s*$//; # trim trailing spaces
658 print "$line\n";
663 # Close file.
664 select STDOUT;
665 close TEXT;
668 sub word_txt {
669 my ($w) = @_;
670 my $wtype, $wmajt;
672 return undef if $w eq '' || $w eq undef;
673 $wtype = substr($w,0,2);
674 $wmajt = substr($wtype,0,1);
675 $w = substr($w,2);
676 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
677 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
678 return $w;
679 } elsif ($wtype eq "sp") {
680 return ' ';
681 } elsif ($wtype eq "da") {
682 return '-';
683 } elsif ($wmajt eq "c" || $wtype eq "wc") {
684 return "`${w}'";
685 } elsif ($wtype eq "es") {
686 return "_${w}";
687 } elsif ($wtype eq "ee") {
688 return "${w}_";
689 } elsif ($wtype eq "eo") {
690 return "_${w}_";
691 } elsif ($wmajt eq "x" || $wmajt eq "i") {
692 return "\001";
693 } else {
694 die "panic in word_txt: $wtype$w\n";
698 sub write_html {
699 # This is called from the top level, so I won't bother using
700 # my or local.
702 # Write contents file. Just the preamble, then a menu of links to the
703 # separate chapter files and the nodes therein.
704 print "writing contents file...";
705 open TEXT,">nasmdoc0.html";
706 select TEXT;
707 &html_preamble(0);
708 print "<p>This manual documents NASM, the Netwide Assembler: an assembler\n";
709 print "targetting the Intel x86 series of processors, with portable source.\n";
710 print "<p>";
711 for ($node = $tstruct_next{'Top'}; $node; $node = $tstruct_next{$node}) {
712 if ($tstruct_level{$node} == 1) {
713 # Invent a file name.
714 ($number = lc($xrefnodes{$node})) =~ s/.*-//;
715 $fname="nasmdocx.html";
716 substr($fname,8 - length $number, length $number) = $number;
717 $html_fnames{$node} = $fname;
718 $link = $fname;
719 print "<p>";
720 } else {
721 # Use the preceding filename plus a marker point.
722 $link = $fname . "#$xrefnodes{$node}";
724 $title = "$node: ";
725 $pname = $tstruct_pname{$node};
726 foreach $i (@$pname) {
727 $ww = &word_html($i);
728 $title .= $ww unless $ww eq "\001";
730 print "<a href=\"$link\">$title</a><br>\n";
732 print "<p><a href=\"nasmdoci.html\">Index</a>\n";
733 print "</body></html>\n";
734 select STDOUT;
735 close TEXT;
737 # Open a null file, to ensure output (eg random &html_jumppoints calls)
738 # goes _somewhere_.
739 print "writing chapter files...";
740 open TEXT,">/dev/null";
741 select TEXT;
742 $html_lastf = '';
744 $in_list = 0;
746 for ($para = 0; $para <= $#pnames; $para++) {
747 $pname = $pnames[$para];
748 $pflags = $pflags[$para];
749 $ptype = substr($pflags,0,4);
751 $in_list = 0, print "</ul>\n" if $in_list && $ptype ne "bull";
752 if ($ptype eq "chap") {
753 # Chapter heading. Begin a new file.
754 $pflags =~ /chap (.*) :(.*)/;
755 $title = "Chapter $1: ";
756 $xref = $2;
757 &html_jumppoints; print "</body></html>\n"; select STDOUT; close TEXT;
758 $html_lastf = $html_fnames{$chapternode};
759 $chapternode = $nodexrefs{$xref};
760 $html_nextf = $html_fnames{$tstruct_mnext{$chapternode}};
761 open TEXT,">$html_fnames{$chapternode}"; select TEXT; &html_preamble(1);
762 foreach $i (@$pname) {
763 $ww = &word_html($i);
764 $title .= $ww unless $ww eq "\001";
766 $h = "<h2><a name=\"$xref\">$title</a></h2>\n";
767 print $h; print FULL $h;
768 } elsif ($ptype eq "appn") {
769 # Appendix heading. Begin a new file.
770 $pflags =~ /appn (.*) :(.*)/;
771 $title = "Appendix $1: ";
772 $xref = $2;
773 &html_jumppoints; print "</body></html>\n"; select STDOUT; close TEXT;
774 $html_lastf = $html_fnames{$chapternode};
775 $chapternode = $nodexrefs{$xref};
776 $html_nextf = $html_fnames{$tstruct_mnext{$chapternode}};
777 open TEXT,">$html_fnames{$chapternode}"; select TEXT; &html_preamble(1);
778 foreach $i (@$pname) {
779 $ww = &word_html($i);
780 $title .= $ww unless $ww eq "\001";
782 print "<h2><a name=\"$xref\">$title</a></h2>\n";
783 } elsif ($ptype eq "head" || $ptype eq "subh") {
784 # Heading or subheading.
785 $pflags =~ /.... (.*) :(.*)/;
786 $hdr = ($ptype eq "subh" ? "h4" : "h3");
787 $title = $1 . " ";
788 $xref = $2;
789 foreach $i (@$pname) {
790 $ww = &word_html($i);
791 $title .= $ww unless $ww eq "\001";
793 print "<$hdr><a name=\"$xref\">$title</a></$hdr>\n";
794 } elsif ($ptype eq "code") {
795 # Code paragraph.
796 print "<p><pre>\n";
797 foreach $i (@$pname) {
798 $w = $i;
799 $w =~ s/&/&amp;/g;
800 $w =~ s/</&lt;/g;
801 $w =~ s/>/&gt;/g;
802 print $w, "\n";
804 print "</pre>\n";
805 } elsif ($ptype eq "bull" || $ptype eq "norm") {
806 # Ordinary paragraph, optionally bulleted. We wrap, with ragged
807 # 75-char right margin and either 7 or 11 char left margin
808 # depending on bullets.
809 if ($ptype eq "bull") {
810 $in_list = 1, print "<ul>\n" unless $in_list;
811 $line = '<li>';
812 } else {
813 $line = '<p>';
815 @a = @$pname;
816 $wd = $wprev = '';
817 do {
818 do { $w = &word_html(shift @a) } while $w eq "\001"; # nasty hack
819 $wd .= $wprev;
820 if ($w eq ' ' || $w eq '' || $w eq undef) {
821 if (length ($line . $wd) > 75) {
822 $line =~ s/\s*$//; # trim trailing spaces
823 print "$line\n";
824 $line = '';
825 $wd =~ s/^\s*//; # trim leading spaces
827 $line .= $wd;
828 $wd = '';
830 $wprev = $w;
831 } while ($w ne '' && $w ne undef);
832 if ($line =~ /\S/) {
833 $line =~ s/\s*$//; # trim trailing spaces
834 print "$line\n";
839 # Close whichever file was open.
840 &html_jumppoints;
841 print "</body></html>\n";
842 select STDOUT;
843 close TEXT;
845 print "\n writing index file...";
846 open TEXT,">nasmdoci.html";
847 select TEXT;
848 &html_preamble(0);
849 print "<p align=center><a href=\"nasmdoc0.html\">Contents</a>\n";
850 print "<p>";
851 &html_index;
852 print "<p align=center><a href=\"nasmdoc0.html\">Contents</a>\n";
853 print "</body></html>\n";
854 select STDOUT;
855 close TEXT;
858 sub html_preamble {
859 print "<html><head><title>NASM Manual</title></head>\n";
860 print "<body><h1 align=center>The Netwide Assembler: NASM</h1>\n\n";
861 &html_jumppoints if $_[0];
864 sub html_jumppoints {
865 print "<p align=center>";
866 print "<a href=\"$html_nextf\">Next Chapter</a> |\n" if $html_nextf;
867 print "<a href=\"$html_lastf\">Previous Chapter</a> |\n" if $html_lastf;
868 print "<a href=\"nasmdoc0.html\">Contents</a> |\n";
869 print "<a href=\"nasmdoci.html\">Index</a>\n";
872 sub html_index {
873 my $itag, $a, @ientry, $sep, $w, $wd, $wprev, $line;
875 $chapternode = '';
876 foreach $itag (@itags) {
877 $ientry = $idxmap{$itag};
878 @a = @$ientry;
879 push @a, "n :";
880 $sep = 0;
881 foreach $node (@nodes) {
882 next if !$idxnodes{$node,$itag};
883 push @a, "n ," if $sep;
884 push @a, "sp", "x $xrefnodes{$node}", "n $node", "xe$xrefnodes{$node}";
885 $sep = 1;
887 $line = '';
888 do {
889 do { $w = &word_html(shift @a) } while $w eq "\001"; # nasty hack
890 $wd .= $wprev;
891 if ($w eq ' ' || $w eq '' || $w eq undef) {
892 if (length ($line . $wd) > 75) {
893 $line =~ s/\s*$//; # trim trailing spaces
894 print "$line\n";
895 $line = '';
896 $wd =~ s/^\s*//; # trim leading spaces
898 $line .= $wd;
899 $wd = '';
901 $wprev = $w;
902 } while ($w ne '' && $w ne undef);
903 if ($line =~ /\S/) {
904 $line =~ s/\s*$//; # trim trailing spaces
905 print "$line\n";
907 print "<br>\n";
911 sub word_html {
912 my ($w) = @_;
913 my $wtype, $wmajt, $pfx, $sfx;
915 return undef if $w eq '' || $w eq undef;
917 $wtype = substr($w,0,2);
918 $wmajt = substr($wtype,0,1);
919 $w = substr($w,2);
920 $pfx = $sfx = '';
921 $pfx = "<a href=\"$1\">", $sfx = "</a>", $w = $2
922 if $wmajt eq "w" && $w =~ /^<(.*)>(.*)$/;
923 $w =~ s/&/&amp;/g;
924 $w =~ s/</&lt;/g;
925 $w =~ s/>/&gt;/g;
926 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
927 return $pfx . $w . $sfx;
928 } elsif ($wtype eq "sp") {
929 return ' ';
930 } elsif ($wtype eq "da") {
931 return '-'; # sadly, en-dashes are non-standard in HTML
932 } elsif ($wmajt eq "c" || $wtype eq "wc") {
933 return $pfx . "<code><nobr>${w}</nobr></code>" . $sfx;
934 } elsif ($wtype eq "es") {
935 return "<em>${w}";
936 } elsif ($wtype eq "ee") {
937 return "${w}</em>";
938 } elsif ($wtype eq "eo") {
939 return "<em>${w}</em>";
940 } elsif ($wtype eq "x ") {
941 # Magic: we must resolve the cross reference into file and marker
942 # parts, then dispose of the file part if it's us, and dispose of
943 # the marker part if the cross reference describes the top node of
944 # another file.
945 my $node = $nodexrefs{$w}; # find the node we're aiming at
946 my $level = $tstruct_level{$node}; # and its level
947 my $up = $node, $uplev = $level-1;
948 $up = $tstruct_up{$up} while $uplev--; # get top node of containing file
949 my $file = ($up ne $chapternode) ? $html_fnames{$up} : "";
950 my $marker = ($level == 1 and $file) ? "" : "#$w";
951 return "<a href=\"$file$marker\">";
952 } elsif ($wtype eq "xe") {
953 return "</a>";
954 } elsif ($wmajt eq "i") {
955 return "\001";
956 } else {
957 die "panic in word_html: $wtype$w\n";
961 sub write_texi {
962 # This is called from the top level, so I won't bother using
963 # my or local.
965 # Open file.
966 print "writing file...";
967 open TEXT,">nasmdoc.texi";
968 select TEXT;
970 # Preamble.
971 print "\\input texinfo \@c -*-texinfo-*-\n";
972 print "\@c \%**start of header\n";
973 print "\@setfilename ",$metadata{'infofile'},".info\n";
974 print "\@dircategory ",$metadata{'category'},"\n";
975 print "\@direntry\n";
976 printf "* %-28s %s.\n",
977 sprintf('%s: (%s).', $metadata{'infoname'}, $metadata{'infofile'}),
978 $metadata{'infotitle'};
979 print "\@end direntry\n";
980 print "\@settitle ", $metadata{'title'},"\n";
981 print "\@setchapternewpage odd\n";
982 print "\@c \%**end of header\n";
983 print "\n";
984 print "\@ifinfo\n";
985 print $metadata{'summary'}, "\n";
986 print "\n";
987 print "Copyright ",$metadata{'year'}," ",$metadata{'author'},"\n";
988 print "\n";
989 print $metadata{'license'}, "\n";
990 print "\@end ifinfo\n";
991 print "\n";
992 print "\@titlepage\n";
993 $title = $metadata{'title'};
994 $title =~ s/ - / --- /g;
995 print "\@title ${title}\n";
996 print "\@author ",$metadata{'author'},"\n";
997 print "\n";
998 print "\@page\n";
999 print "\@vskip 0pt plus 1filll\n";
1000 print "Copyright \@copyright{} ",$metadata{'year'},' ',$metadata{'author'},"\n";
1001 print "\n";
1002 print $metadata{'license'}, "\n";
1003 print "\@end titlepage\n";
1004 print "\n";
1005 print "\@node Top, $tstruct_next{'Top'}, (dir), (dir)\n";
1006 print "\@top ",$metadata{'infotitle'},"\n";
1007 print "\n";
1008 print "\@ifinfo\n";
1009 print $metadata{'summary'}, "\n";
1010 print "\@end ifinfo\n";
1012 $node = "Top";
1014 $bulleting = 0;
1015 for ($para = 0; $para <= $#pnames; $para++) {
1016 $pname = $pnames[$para];
1017 $pflags = $pflags[$para];
1018 $ptype = substr($pflags,0,4);
1020 $bulleting = 0, print "\@end itemize\n" if $bulleting && $ptype ne "bull";
1021 print "\n"; # always one of these before a new paragraph
1023 if ($ptype eq "chap") {
1024 # Chapter heading. Begin a new node.
1025 &texi_menu($node)
1026 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1027 $pflags =~ /chap (.*) :(.*)/;
1028 $node = "Chapter $1";
1029 $title = "Chapter $1: ";
1030 foreach $i (@$pname) {
1031 $ww = &word_texi($i);
1032 $title .= $ww unless $ww eq "\001";
1034 print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},";
1035 print " $tstruct_up{$node}\n\@unnumbered $title\n";
1036 } elsif ($ptype eq "appn") {
1037 # Appendix heading. Begin a new node.
1038 &texi_menu($node)
1039 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1040 $pflags =~ /appn (.*) :(.*)/;
1041 $node = "Appendix $1";
1042 $title = "Appendix $1: ";
1043 foreach $i (@$pname) {
1044 $ww = &word_texi($i);
1045 $title .= $ww unless $ww eq "\001";
1047 print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},";
1048 print " $tstruct_up{$node}\n\@unnumbered $title\n";
1049 } elsif ($ptype eq "head" || $ptype eq "subh") {
1050 # Heading or subheading. Begin a new node.
1051 &texi_menu($node)
1052 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1053 $pflags =~ /.... (.*) :(.*)/;
1054 $node = "Section $1";
1055 $title = "$1. ";
1056 foreach $i (@$pname) {
1057 $ww = &word_texi($i);
1058 $title .= $ww unless $ww eq "\001";
1060 print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},";
1061 print " $tstruct_up{$node}\n";
1062 $hdr = ($ptype eq "subh" ? "\@unnumberedsubsec" : "\@unnumberedsec");
1063 print "$hdr $title\n";
1064 } elsif ($ptype eq "code") {
1065 # Code paragraph. Surround with @example / @end example.
1066 print "\@example\n";
1067 foreach $i (@$pname) {
1068 warn "code line longer than 68 chars: $i\n" if length $i > 68;
1069 $i =~ s/\@/\@\@/g;
1070 $i =~ s/\{/\@\{/g;
1071 $i =~ s/\}/\@\}/g;
1072 print "$i\n";
1074 print "\@end example\n";
1075 } elsif ($ptype eq "bull" || $ptype eq "norm") {
1076 # Ordinary paragraph, optionally bulleted. We wrap, FWIW.
1077 if ($ptype eq "bull") {
1078 $bulleting = 1, print "\@itemize \@bullet\n" if !$bulleting;
1079 print "\@item\n";
1081 $line = '';
1082 @a = @$pname;
1083 $wd = $wprev = '';
1084 do {
1085 do { $w = &word_texi(shift @a); } while $w eq "\001"; # hack
1086 $wd .= $wprev;
1087 if ($wprev =~ /-$/ || $w eq ' ' || $w eq '' || $w eq undef) {
1088 if (length ($line . $wd) > 75) {
1089 $line =~ s/\s*$//; # trim trailing spaces
1090 print "$line\n";
1091 $line = '';
1092 $wd =~ s/^\s*//; # trim leading spaces
1094 $line .= $wd;
1095 $wd = '';
1097 $wprev = $w;
1098 } while ($w ne '' && $w ne undef);
1099 if ($line =~ /\S/) {
1100 $line =~ s/\s*$//; # trim trailing spaces
1101 print "$line\n";
1106 # Write index.
1107 &texi_index;
1109 # Close file.
1110 print "\n\@contents\n\@bye\n";
1111 select STDOUT;
1112 close TEXT;
1115 # Side effect of this procedure: update global `texiwdlen' to be the length
1116 # in chars of the formatted version of the word.
1117 sub word_texi {
1118 my ($w) = @_;
1119 my $wtype, $wmajt;
1121 return undef if $w eq '' || $w eq undef;
1122 $wtype = substr($w,0,2);
1123 $wmajt = substr($wtype,0,1);
1124 $w = substr($w,2);
1125 $wlen = length $w;
1126 $w =~ s/\@/\@\@/g;
1127 $w =~ s/\{/\@\{/g;
1128 $w =~ s/\}/\@\}/g;
1129 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
1130 substr($w,0,1) =~ tr/a-z/A-Z/, $capital = 0 if $capital;
1131 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
1132 $texiwdlen = $wlen;
1133 return $w;
1134 } elsif ($wtype eq "sp") {
1135 $texiwdlen = 1;
1136 return ' ';
1137 } elsif ($wtype eq "da") {
1138 $texiwdlen = 2;
1139 return '--';
1140 } elsif ($wmajt eq "c" || $wtype eq "wc") {
1141 $texiwdlen = 2 + $wlen;
1142 return "\@code\{$w\}";
1143 } elsif ($wtype eq "es") {
1144 $texiwdlen = 1 + $wlen;
1145 return "\@emph\{${w}";
1146 } elsif ($wtype eq "ee") {
1147 $texiwdlen = 1 + $wlen;
1148 return "${w}\}";
1149 } elsif ($wtype eq "eo") {
1150 $texiwdlen = 2 + $wlen;
1151 return "\@emph\{${w}\}";
1152 } elsif ($wtype eq "x ") {
1153 $texiwdlen = 0; # we don't need it in this case
1154 $capital = 1; # hack
1155 return "\@ref\{";
1156 } elsif ($wtype eq "xe") {
1157 $texiwdlen = 0; # we don't need it in this case
1158 return "\}";
1159 } elsif ($wmajt eq "i") {
1160 $texiwdlen = 0; # we don't need it in this case
1161 return "\001";
1162 } else {
1163 die "panic in word_texi: $wtype$w\n";
1167 sub texi_menu {
1168 my ($topitem) = @_;
1169 my $item, $i, $mpname, $title, $wd;
1171 $item = $tstruct_next{$topitem};
1172 print "\@menu\n";
1173 while ($item) {
1174 $title = "";
1175 $mpname = $tstruct_pname{$item};
1176 foreach $i (@$mpname) {
1177 $wd = &word_texi($i);
1178 $title .= $wd unless $wd eq "\001";
1180 print "* ${item}:: $title\n";
1181 $item = $tstruct_mnext{$item};
1183 print "* Index::\n" if $topitem eq "Top";
1184 print "\@end menu\n";
1187 sub texi_index {
1188 my $itag, $ientry, @a, $wd, $item, $len;
1189 my $subnums = "123456789ABCDEFGHIJKLMNOPQRSTU" .
1190 "VWXYZabcdefghijklmnopqrstuvwxyz";
1192 print "\@ifinfo\n\@node Index, , $FIXMElastnode, Top\n";
1193 print "\@unnumbered Index\n\n\@menu\n";
1195 foreach $itag (@itags) {
1196 $ientry = $idxmap{$itag};
1197 @a = @$ientry;
1198 $item = '';
1199 $len = 0;
1200 foreach $i (@a) {
1201 $wd = &word_texi($i);
1202 $item .= $wd, $len += $texiwdlen unless $wd eq "\001";
1204 $i = 0;
1205 foreach $node (@nodes) {
1206 next if !$idxnodes{$node,$itag};
1207 printf "* %s%s (%s): %s.\n",
1208 $item, " " x (40-$len), substr($subnums,$i++,1), $node;
1211 print "\@end menu\n\@end ifinfo\n";
1214 sub write_hlp {
1215 # This is called from the top level, so I won't bother using
1216 # my or local.
1218 # Build the index-tag text forms.
1219 print "building index entries...";
1220 @hlp_index = map {
1221 my $i,$ww;
1222 my $ientry = $idxmap{$_};
1223 my $title = "";
1224 foreach $i (@$ientry) {
1225 $ww = &word_hlp($i,0);
1226 $title .= $ww unless $ww eq "\001";
1228 $title;
1229 } @itags;
1231 # Write the HPJ project-description file.
1232 print "writing .hpj file...";
1233 open HPJ,">nasmdoc.hpj";
1234 print HPJ "[OPTIONS]\ncompress=true\n";
1235 print HPJ "title=NASM: The Netwide Assembler\noldkeyphrase=no\n\n";
1236 print HPJ "[FILES]\nnasmdoc.rtf\n\n";
1237 print HPJ "[CONFIG]\n";
1238 print HPJ 'CreateButton("btn_up", "&Up",'.
1239 ' "JumpContents(`nasmdoc.hlp'."'".')")';
1240 print HPJ "\nBrowseButtons()\n";
1241 close HPJ;
1243 # Open file.
1244 print "\n writing .rtf file...";
1245 open TEXT,">nasmdoc.rtf";
1246 select TEXT;
1248 # Preamble.
1249 print "{\\rtf1\\ansi{\\fonttbl\n";
1250 print "\\f0\\froman Times New Roman;\\f1\\fmodern Courier New;\n";
1251 print "\\f2\\fswiss Arial;\\f3\\ftech Wingdings}\\deff0\n";
1252 print "#{\\footnote Top}\n";
1253 print "\${\\footnote Contents}\n";
1254 print "+{\\footnote browse:00000}\n";
1255 print "!{\\footnote DisableButton(\"btn_up\")}\n";
1256 print "\\keepn\\f2\\b\\fs30\\sb0\n";
1257 print "NASM: The Netwide Assembler\n";
1258 print "\\par\\pard\\plain\\sb120\n";
1259 print "This file documents NASM, the Netwide Assembler: an assembler \n";
1260 print "targetting the Intel x86 series of processors, with portable source.\n";
1262 $node = "Top";
1263 $browse = 0;
1265 $newpar = "\\par\\sb120\n";
1266 for ($para = 0; $para <= $#pnames; $para++) {
1267 $pname = $pnames[$para];
1268 $pflags = $pflags[$para];
1269 $ptype = substr($pflags,0,4);
1271 print $newpar;
1272 $newpar = "\\par\\sb120\n";
1274 if ($ptype eq "chap") {
1275 # Chapter heading. Begin a new node.
1276 &hlp_menu($node)
1277 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1278 $pflags =~ /chap (.*) :(.*)/;
1279 $node = "Chapter $1";
1280 $title = $footnotetitle = "Chapter $1: ";
1281 foreach $i (@$pname) {
1282 $ww = &word_hlp($i,1);
1283 $title .= $ww, $footnotetitle .= &word_hlp($i,0) unless $ww eq "\001";
1285 print "\\page\n";
1286 printf "#{\\footnote %s}\n", &hlp_sectkw($node);
1287 print "\${\\footnote $footnotetitle}\n";
1288 printf "+{\\footnote browse:%05d}\n", ++$browse;
1289 printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," .
1290 "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n",
1291 &hlp_sectkw($tstruct_up{$node});
1292 print "EnableButton(\"btn_up\")}\n";
1293 &hlp_keywords($node);
1294 print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n";
1295 print "$title\n";
1296 $newpar = "\\par\\pard\\plain\\sb120\n";
1297 } elsif ($ptype eq "appn") {
1298 # Appendix heading. Begin a new node.
1299 &hlp_menu($node)
1300 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1301 $pflags =~ /appn (.*) :(.*)/;
1302 $node = "Appendix $1";
1303 $title = $footnotetitle = "Appendix $1: ";
1304 foreach $i (@$pname) {
1305 $ww = &word_hlp($i,1);
1306 $title .= $ww, $footnotetitle .= &word_hlp($i,0) unless $ww eq "\001";
1308 print "\\page\n";
1309 printf "#{\\footnote %s}\n", &hlp_sectkw($node);
1310 print "\${\\footnote $footnotetitle}\n";
1311 printf "+{\\footnote browse:%05d}\n", ++$browse;
1312 printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," .
1313 "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n",
1314 &hlp_sectkw($tstruct_up{$node});
1315 print "EnableButton(\"btn_up\")}\n";
1316 &hlp_keywords($node);
1317 print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n";
1318 print "$title\n";
1319 $newpar = "\\par\\pard\\plain\\sb120\n";
1320 } elsif ($ptype eq "head" || $ptype eq "subh") {
1321 # Heading or subheading. Begin a new node.
1322 &hlp_menu($node)
1323 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1324 $pflags =~ /.... (.*) :(.*)/;
1325 $node = "Section $1";
1326 $title = $footnotetitle = "$1. ";
1327 foreach $i (@$pname) {
1328 $ww = &word_hlp($i,1);
1329 $title .= $ww, $footnotetitle .= &word_hlp($i,0) unless $ww eq "\001";
1331 print "\\page\n";
1332 printf "#{\\footnote %s}\n", &hlp_sectkw($node);
1333 print "\${\\footnote $footnotetitle}\n";
1334 printf "+{\\footnote browse:%05d}\n", ++$browse;
1335 printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," .
1336 "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n",
1337 &hlp_sectkw($tstruct_up{$node});
1338 print "EnableButton(\"btn_up\")}\n";
1339 &hlp_keywords($node);
1340 print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n";
1341 print "$title\n";
1342 $newpar = "\\par\\pard\\plain\\sb120\n";
1343 } elsif ($ptype eq "code") {
1344 # Code paragraph.
1345 print "\\keep\\f1\\sb120\n";
1346 foreach $i (@$pname) {
1347 my $x = $i;
1348 warn "code line longer than 68 chars: $i\n" if length $i > 68;
1349 $x =~ s/\\/\\\\/g;
1350 $x =~ s/\{/\\\{/g;
1351 $x =~ s/\}/\\\}/g;
1352 print "$x\\par\\sb0\n";
1354 $newpar = "\\pard\\f0\\sb120\n";
1355 } elsif ($ptype eq "bull" || $ptype eq "norm") {
1356 # Ordinary paragraph, optionally bulleted. We wrap, FWIW.
1357 if ($ptype eq "bull") {
1358 print "\\tx360\\li360\\fi-360{\\f3\\'9F}\\tab\n";
1359 $newpar = "\\par\\pard\\sb120\n";
1360 } else {
1361 $newpar = "\\par\\sb120\n";
1363 $line = '';
1364 @a = @$pname;
1365 $wd = $wprev = '';
1366 do {
1367 do { $w = &word_hlp((shift @a),1); } while $w eq "\001"; # hack
1368 $wd .= $wprev;
1369 if ($w eq ' ' || $w eq '' || $w eq undef) {
1370 if (length ($line . $wd) > 75) {
1371 $line =~ s/\s*$//; # trim trailing spaces
1372 print "$line \n"; # and put one back
1373 $line = '';
1374 $wd =~ s/^\s*//; # trim leading spaces
1376 $line .= $wd;
1377 $wd = '';
1379 $wprev = $w;
1380 } while ($w ne '' && $w ne undef);
1381 if ($line =~ /\S/) {
1382 $line =~ s/\s*$//; # trim trailing spaces
1383 print "$line\n";
1388 # Close file.
1389 print "\\page}\n";
1390 select STDOUT;
1391 close TEXT;
1394 sub word_hlp {
1395 my ($w, $docode) = @_;
1396 my $wtype, $wmajt;
1398 return undef if $w eq '' || $w eq undef;
1399 $wtype = substr($w,0,2);
1400 $wmajt = substr($wtype,0,1);
1401 $w = substr($w,2);
1402 $w =~ s/\\/\\\\/g;
1403 $w =~ s/\{/\\\{/g;
1404 $w =~ s/\}/\\\}/g;
1405 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
1406 substr($w,0,length($w)-1) =~ s/-/\\\'AD/g if $wmajt ne "x"; #nonbreakhyphens
1407 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
1408 return $w;
1409 } elsif ($wtype eq "sp") {
1410 return ' ';
1411 } elsif ($wtype eq "da") {
1412 return "\\'96";
1413 } elsif ($wmajt eq "c" || $wtype eq "wc") {
1414 $w =~ s/ /\\\'A0/g; # make spaces non-breaking
1415 return $docode ? "{\\f1 ${w}}" : $w;
1416 } elsif ($wtype eq "es") {
1417 return "{\\i ${w}";
1418 } elsif ($wtype eq "ee") {
1419 return "${w}}";
1420 } elsif ($wtype eq "eo") {
1421 return "{\\i ${w}}";
1422 } elsif ($wtype eq "x ") {
1423 return "{\\uldb ";
1424 } elsif ($wtype eq "xe") {
1425 $w = &hlp_sectkw($w);
1426 return "}{\\v ${w}}";
1427 } elsif ($wmajt eq "i") {
1428 return "\001";
1429 } else {
1430 die "panic in word_hlp: $wtype$w\n";
1434 sub hlp_menu {
1435 my ($topitem) = @_;
1436 my $item, $kword, $i, $mpname, $title;
1438 $item = $tstruct_next{$topitem};
1439 print "\\li360\\fi-360\n";
1440 while ($item) {
1441 $title = "";
1442 $mpname = $tstruct_pname{$item};
1443 foreach $i (@$mpname) {
1444 $ww = &word_hlp($i, 0);
1445 $title .= $ww unless $ww eq "\001";
1447 $kword = &hlp_sectkw($item);
1448 print "{\\uldb ${item}: $title}{\\v $kword}\\par\\sb0\n";
1449 $item = $tstruct_mnext{$item};
1451 print "\\pard\\sb120\n";
1454 sub hlp_sectkw {
1455 my ($node) = @_;
1456 $node =~ tr/A-Z/a-z/;
1457 $node =~ tr/- ./___/;
1458 $node;
1461 sub hlp_keywords {
1462 my ($node) = @_;
1463 my $pfx = "K{\\footnote ";
1464 my $done = 0;
1465 foreach $i (0..$#itags) {
1466 (print $pfx,$hlp_index[$i]), $pfx = ";\n", $done++
1467 if $idxnodes{$node,$itags[$i]};
1469 print "}\n" if $done;
1472 # Make tree structures. $tstruct_* is top-level and global.
1473 sub add_item {
1474 my ($item, $level) = @_;
1475 my $i;
1477 $tstruct_pname{$item} = $pname;
1478 $tstruct_next{$tstruct_previtem} = $item;
1479 $tstruct_prev{$item} = $tstruct_previtem;
1480 $tstruct_level{$item} = $level;
1481 $tstruct_up{$item} = $tstruct_last[$level-1];
1482 $tstruct_mnext{$tstruct_last[$level]} = $item;
1483 $tstruct_last[$level] = $item;
1484 for ($i=$level+1; $i<$MAXLEVEL; $i++) { $tstruct_last[$i] = undef; }
1485 $tstruct_previtem = $item;
1486 push @nodes, $item;
1490 # This produces documentation intermediate paragraph format; this is
1491 # basically the digested output of the front end. Intended for use
1492 # by future backends, instead of putting it all in the same script.
1494 sub write_dip {
1495 open(PARAS, "> nasmdoc.dip");
1496 foreach $k (keys(%metadata)) {
1497 print PARAS 'meta :', $k, "\n";
1498 print PARAS $metadata{$k},"\n";
1500 for ($para = 0; $para <= $#pnames; $para++) {
1501 print PARAS $pflags[$para], "\n";
1502 print PARAS join("\037", @{$pnames[$para]}, "\n");
1504 foreach $k (@itags) {
1505 print PARAS 'indx :', $k, "\n";
1506 print PARAS join("\037", @{$idxmap{$k}}), "\n";
1508 close(PARAS);