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