Reworked test files for better error reporting
[nasm/perl-rewrite.git] / doc / rdsrc.pl
blobab85af8718a7b6d6beb6078e85d98f2f896c3d83
1 #!/usr/bin/perl
3 # Read the source-form of the NASM manual and generate the various
4 # output forms.
6 # TODO:
8 # Ellipsis support would be nice.
10 # Source-form features:
11 # ---------------------
13 # Bullet \b
14 # Bullets the paragraph. Rest of paragraph is indented to cope. In
15 # HTML, consecutive groups of bulleted paragraphs become unordered
16 # lists.
18 # Emphasis \e{foobar}
19 # produces `_foobar_' in text and italics in HTML, PS, RTF
21 # Inline code \c{foobar}
22 # produces ``foobar'' in text, and fixed-pitch font in HTML, PS, RTF
24 # Display code
25 # \c line one
26 # \c line two
27 # produces fixed-pitch font where appropriate, and doesn't break
28 # pages except sufficiently far into the middle of a display.
30 # Chapter, header and subheader
31 # \C{intro} Introduction
32 # \H{whatsnasm} What is NASM?
33 # \S{free} NASM Is Free
34 # dealt with as appropriate. Chapters begin on new sides, possibly
35 # even new _pages_. (Sub)?headers are good places to begin new
36 # pages. Just _after_ a (sub)?header isn't.
37 # The keywords can be substituted with \K and \k.
39 # Keyword \K{cintro} \k{cintro}
40 # Expands to `Chapter 1', `Section 1.1', `Section 1.1.1'. \K has an
41 # initial capital whereas \k doesn't. In HTML, will produce
42 # hyperlinks.
44 # Web link \W{http://foobar/}{text} or \W{mailto:me@here}\c{me@here}
45 # the \W prefix is ignored except in HTML; in HTML the last part
46 # becomes a hyperlink to the first part.
48 # Literals \{ \} \\
49 # In case it's necessary, they expand to the real versions.
51 # Nonbreaking hyphen \-
52 # Need more be said?
54 # Source comment \#
55 # Causes everything after it on the line to be ignored by the
56 # source-form processor.
58 # Indexable word \i{foobar} (or \i\e{foobar} or \i\c{foobar}, equally)
59 # makes word appear in index, referenced to that point
60 # \i\c comes up in code style even in the index; \i\e doesn't come
61 # up in emphasised style.
63 # Indexable non-displayed word \I{foobar} or \I\c{foobar}
64 # just as \i{foobar} except that nothing is displayed for it
66 # Index rewrite
67 # \IR{foobar} \c{foobar} operator, uses of
68 # tidies up the appearance in the index of something the \i or \I
69 # operator was applied to
71 # Index alias
72 # \IA{foobar}{bazquux}
73 # aliases one index tag (as might be supplied to \i or \I) to
74 # another, so that \I{foobar} has the effect of \I{bazquux}, and
75 # \i{foobar} has the effect of \I{bazquux}foobar
77 # Metadata
78 # \M{key}{something}
79 # defines document metadata, such as authorship, title and copyright;
80 # different output formats use this differently.
82 # Include subfile
83 # \&{filename}
84 # Includes filename. Recursion is allowed.
87 use IO::File;
89 $diag = 1, shift @ARGV if $ARGV[0] eq "-d";
91 ($out_format) = @ARGV;
93 $| = 1;
95 $tstruct_previtem = $node = "Top";
96 $nodes = ($node);
97 $tstruct_level{$tstruct_previtem} = 0;
98 $tstruct_last[$tstruct_level{$tstruct_previtem}] = $tstruct_previtem;
99 $MAXLEVEL = 10; # really 3, but play safe ;-)
101 # Read the file; pass a paragraph at a time to the paragraph processor.
102 print "Reading input...";
103 $pname = "para000000";
104 @pnames = @pflags = ();
105 $para = undef;
106 while (defined($_ = <STDIN>)) {
107 $_ = &untabify($_);
108 &check_include($_);
110 &got_para($para);
111 print "done.\n";
113 # Now we've read in the entire document and we know what all the
114 # heading keywords refer to. Go through and fix up the \k references.
115 print "Fixing up cross-references...";
116 &fixup_xrefs;
117 print "done.\n";
119 # Sort the index tags, according to the slightly odd order I've decided on.
120 print "Sorting index tags...";
121 &indexsort;
122 print "done.\n";
124 if ($diag) {
125 print "Writing index-diagnostic file...";
126 &indexdiag;
127 print "done.\n";
130 # OK. Write out the various output files.
131 if ($out_format eq 'txt') {
132 print "Producing text output: ";
133 &write_txt;
134 print "done.\n";
135 } elsif ($out_format eq 'html') {
136 print "Producing HTML output: ";
137 &write_html;
138 print "done.\n";
139 } elsif ($out_format eq 'texi') {
140 print "Producing Texinfo output: ";
141 &write_texi;
142 print "done.\n";
143 } elsif ($out_format eq 'hlp') {
144 print "Producing WinHelp output: ";
145 &write_hlp;
146 print "done.\n";
147 } elsif ($out_format eq 'dip') {
148 print "Producing Documentation Intermediate Paragraphs: ";
149 &write_dip;
150 print "done.\n";
151 } else {
152 die "$0: unknown output format: $out_format\n";
155 sub untabify($) {
156 my($s) = @_;
157 my $o = '';
158 my($c, $i, $p);
160 $p = 0;
161 for ($i = 0; $i < length($s); $i++) {
162 $c = substr($s, $i, 1);
163 if ($c eq "\t") {
164 do {
165 $o .= ' ';
166 $p++;
167 } while ($p & 7);
168 } else {
169 $o .= $c;
170 $p++;
173 return $o;
175 sub check_include {
176 local $_ = shift;
177 if (/\\& (\S+)/) {
178 &include($1);
179 } else {
180 &get_para($_);
183 sub get_para($_) {
184 chomp;
185 if (!/\S/ || /^\\(IA|IR|M)/) { # special case: \IA \IR \M imply new-paragraph
186 &got_para($para);
187 $para = undef;
189 if (/\S/) {
190 s/\\#.*$//; # strip comments
191 $para .= " " . $_;
194 sub include {
195 my $name = shift;
196 my $F = IO::File->new($name)
197 or die "Cannot open $name: $!";
198 while (<$F>) {
199 &check_include($_);
202 sub got_para {
203 local ($_) = @_;
204 my $pflags = "", $i, $w, $l, $t;
205 return if !/\S/;
207 @$pname = ();
209 # Strip off _leading_ spaces, then determine type of paragraph.
210 s/^\s*//;
211 $irewrite = undef;
212 if (/^\\c[^{]/) {
213 # A code paragraph. The paragraph-array will contain the simple
214 # strings which form each line of the paragraph.
215 $pflags = "code";
216 while (/^\\c (([^\\]|\\[^c])*)(.*)$/) {
217 $l = $1;
218 $_ = $3;
219 $l =~ s/\\{/{/g;
220 $l =~ s/\\}/}/g;
221 $l =~ s/\\\\/\\/g;
222 push @$pname, $l;
224 $_ = ''; # suppress word-by-word code
225 } elsif (/^\\C/) {
226 # A chapter heading. Define the keyword and allocate a chapter
227 # number.
228 $cnum++;
229 $hnum = 0;
230 $snum = 0;
231 $xref = "chapter-$cnum";
232 $pflags = "chap $cnum :$xref";
233 die "badly formatted chapter heading: $_\n" if !/^\\C{([^}]*)}\s*(.*)$/;
234 $refs{$1} = "chapter $cnum";
235 $node = "Chapter $cnum";
236 &add_item($node, 1);
237 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
238 $xrefs{$1} = $xref;
239 $_ = $2;
240 # the standard word-by-word code will happen next
241 } elsif (/^\\A/) {
242 # An appendix heading. Define the keyword and allocate an appendix
243 # letter.
244 $cnum++;
245 $cnum = 'A' if $cnum =~ /[0-9]+/;
246 $hnum = 0;
247 $snum = 0;
248 $xref = "appendix-$cnum";
249 $pflags = "appn $cnum :$xref";
250 die "badly formatted appendix heading: $_\n" if !/^\\A{([^}]*)}\s*(.*)$/;
251 $refs{$1} = "appendix $cnum";
252 $node = "Appendix $cnum";
253 &add_item($node, 1);
254 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
255 $xrefs{$1} = $xref;
256 $_ = $2;
257 # the standard word-by-word code will happen next
258 } elsif (/^\\H/) {
259 # A major heading. Define the keyword and allocate a section number.
260 $hnum++;
261 $snum = 0;
262 $xref = "section-$cnum.$hnum";
263 $pflags = "head $cnum.$hnum :$xref";
264 die "badly formatted heading: $_\n" if !/^\\[HP]{([^}]*)}\s*(.*)$/;
265 $refs{$1} = "section $cnum.$hnum";
266 $node = "Section $cnum.$hnum";
267 &add_item($node, 2);
268 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
269 $xrefs{$1} = $xref;
270 $_ = $2;
271 # the standard word-by-word code will happen next
272 } elsif (/^\\S/) {
273 # A sub-heading. Define the keyword and allocate a section number.
274 $snum++;
275 $xref = "section-$cnum.$hnum.$snum";
276 $pflags = "subh $cnum.$hnum.$snum :$xref";
277 die "badly formatted subheading: $_\n" if !/^\\S{([^}]*)}\s*(.*)$/;
278 $refs{$1} = "section $cnum.$hnum.$snum";
279 $node = "Section $cnum.$hnum.$snum";
280 &add_item($node, 3);
281 $xrefnodes{$node} = $xref; $nodexrefs{$xref} = $node;
282 $xrefs{$1} = $xref;
283 $_ = $2;
284 # the standard word-by-word code will happen next
285 } elsif (/^\\IR/) {
286 # An index-rewrite.
287 die "badly formatted index rewrite: $_\n" if !/^\\IR{([^}]*)}\s*(.*)$/;
288 $irewrite = $1;
289 $_ = $2;
290 # the standard word-by-word code will happen next
291 } elsif (/^\\IA/) {
292 # An index-alias.
293 die "badly formatted index alias: $_\n" if !/^\\IA{([^}]*)}{([^}]*)}\s*$/;
294 $idxalias{$1} = $2;
295 return; # avoid word-by-word code
296 } elsif (/^\\M/) {
297 # Metadata
298 die "badly formed metadata: $_\n" if !/^\\M{([^}]*)}{([^}]*)}\s*$/;
299 $metadata{$1} = $2;
300 return; # avoid word-by-word code
301 } elsif (/^\\b/) {
302 # A bulleted paragraph. Strip off the initial \b and let the
303 # word-by-word code take care of the rest.
304 $pflags = "bull";
305 s/^\\b\s*//;
306 } else {
307 # A normal paragraph. Just set $pflags: the word-by-word code does
308 # the rest.
309 $pflags = "norm";
312 # The word-by-word code: unless @$pname is already defined (which it
313 # will be in the case of a code paragraph), split the paragraph up
314 # into words and push each on @$pname.
316 # Each thing pushed on @$pname should have a two-character type
317 # code followed by the text.
319 # Type codes are:
320 # "n " for normal
321 # "da" for a dash
322 # "es" for first emphasised word in emphasised bit
323 # "e " for emphasised in mid-emphasised-bit
324 # "ee" for last emphasised word in emphasised bit
325 # "eo" for single (only) emphasised word
326 # "c " for code
327 # "k " for cross-ref
328 # "kK" for capitalised cross-ref
329 # "w " for Web link
330 # "wc" for code-type Web link
331 # "x " for beginning of resolved cross-ref; generates no visible output,
332 # and the text is the cross-reference code
333 # "xe" for end of resolved cross-ref; text is same as for "x ".
334 # "i " for point to be indexed: the text is the internal index into the
335 # index-items arrays
336 # "sp" for space
337 while (/\S/) {
338 s/^\s*//, push @$pname, "sp" if /^\s/;
339 $indexing = $qindex = 0;
340 if (/^(\\[iI])?\\c/) {
341 $qindex = 1 if $1 eq "\\I";
342 $indexing = 1, s/^\\[iI]// if $1;
343 s/^\\c//;
344 die "badly formatted \\c: \\c$_\n" if !/{(([^\\}]|\\.)*)}(.*)$/;
345 $w = $1;
346 $_ = $3;
347 $w =~ s/\\{/{/g;
348 $w =~ s/\\}/}/g;
349 $w =~ s/\\-/-/g;
350 $w =~ s/\\\\/\\/g;
351 (push @$pname,"i"),$lastp = $#$pname if $indexing;
352 push @$pname,"c $w" if !$qindex;
353 $$pname[$lastp] = &addidx($node, $w, "c $w") if $indexing;
354 } elsif (/^\\[iIe]/) {
355 /^(\\[iI])?(\\e)?/;
356 $emph = 0;
357 $qindex = 1 if $1 eq "\\I";
358 $indexing = 1, $type = "\\i" if $1;
359 $emph = 1, $type = "\\e" if $2;
360 s/^(\\[iI])?(\\e?)//;
361 die "badly formatted $type: $type$_\n" if !/{(([^\\}]|\\.)*)}(.*)$/;
362 $w = $1;
363 $_ = $3;
364 $w =~ s/\\{/{/g;
365 $w =~ s/\\}/}/g;
366 $w =~ s/\\-/-/g;
367 $w =~ s/\\\\/\\/g;
368 $t = $emph ? "es" : "n ";
369 @ientry = ();
370 (push @$pname,"i"),$lastp = $#$pname if $indexing;
371 foreach $i (split /\s+/,$w) { # \e and \i can be multiple words
372 push @$pname,"$t$i","sp" if !$qindex;
373 ($ii=$i) =~ tr/A-Z/a-z/, push @ientry,"n $ii","sp" if $indexing;
374 $t = $emph ? "e " : "n ";
376 $w =~ tr/A-Z/a-z/, pop @ientry if $indexing;
377 $$pname[$lastp] = &addidx($node, $w, @ientry) if $indexing;
378 pop @$pname if !$qindex; # remove final space
379 if (substr($$pname[$#$pname],0,2) eq "es" && !$qindex) {
380 substr($$pname[$#$pname],0,2) = "eo";
381 } elsif ($emph && !$qindex) {
382 substr($$pname[$#$pname],0,2) = "ee";
384 } elsif (/^\\[kK]/) {
385 $t = "k ";
386 $t = "kK" if /^\\K/;
387 s/^\\[kK]//;
388 die "badly formatted \\k: \\c$_\n" if !/{([^}]*)}(.*)$/;
389 $_ = $2;
390 push @$pname,"$t$1";
391 } elsif (/^\\W/) {
392 s/^\\W//;
393 die "badly formatted \\W: \\W$_\n"
394 if !/{([^}]*)}(\\i)?(\\c)?{(([^\\}]|\\.)*)}(.*)$/;
395 $l = $1;
396 $w = $4;
397 $_ = $6;
398 $t = "w ";
399 $t = "wc" if $3 eq "\\c";
400 $indexing = 1 if $2;
401 $w =~ s/\\{/{/g;
402 $w =~ s/\\}/}/g;
403 $w =~ s/\\-/-/g;
404 $w =~ s/\\\\/\\/g;
405 (push @$pname,"i"),$lastp = $#$pname if $indexing;
406 push @$pname,"$t<$l>$w";
407 $$pname[$lastp] = &addidx($node, $w, "c $w") if $indexing;
408 } else {
409 die "what the hell? $_\n" if !/^(([^\s\\\-]|\\[\\{}\-])*-?)(.*)$/;
410 die "painful death! $_\n" if !length $1;
411 $w = $1;
412 $_ = $3;
413 $w =~ s/\\{/{/g;
414 $w =~ s/\\}/}/g;
415 $w =~ s/\\-/-/g;
416 $w =~ s/\\\\/\\/g;
417 if ($w eq "-") {
418 push @$pname,"da";
419 } else {
420 push @$pname,"n $w";
424 if ($irewrite ne undef) {
425 &addidx(undef, $irewrite, @$pname);
426 @$pname = ();
427 } else {
428 push @pnames, $pname;
429 push @pflags, $pflags;
430 $pname++;
434 sub addidx {
435 my ($node, $text, @ientry) = @_;
436 $text = $idxalias{$text} || $text;
437 if ($node eq undef || !$idxmap{$text}) {
438 @$ientry = @ientry;
439 $idxmap{$text} = $ientry;
440 $ientry++;
442 if ($node) {
443 $idxnodes{$node,$text} = 1;
444 return "i $text";
448 sub indexsort {
449 my $iitem, $ientry, $i, $piitem, $pcval, $cval, $clrcval;
451 @itags = map { # get back the original data as the 1st elt of each list
452 $_->[0]
453 } sort { # compare auxiliary (non-first) elements of lists
454 $a->[1] cmp $b->[1] ||
455 $a->[2] cmp $b->[2] ||
456 $a->[0] cmp $b->[0]
457 } map { # transform array into list of 3-element lists
458 my $ientry = $idxmap{$_};
459 my $a = substr($$ientry[0],2);
460 $a =~ tr/A-Za-z0-9//cd;
461 [$_, uc($a), substr($$ientry[0],0,2)]
462 } keys %idxmap;
464 # Having done that, check for comma-hood.
465 $cval = 0;
466 foreach $iitem (@itags) {
467 $ientry = $idxmap{$iitem};
468 $clrcval = 1;
469 $pcval = $cval;
470 FL:for ($i=0; $i <= $#$ientry; $i++) {
471 if ($$ientry[$i] =~ /^(n .*,)(.*)/) {
472 $$ientry[$i] = $1;
473 splice @$ientry,$i+1,0,"n $2" if length $2;
474 $commapos{$iitem} = $i+1;
475 $cval = join("\002", @$ientry[0..$i]);
476 $clrcval = 0;
477 last FL;
480 $cval = undef if $clrcval;
481 $commanext{$iitem} = $commaafter{$piitem} = 1
482 if $cval and ($cval eq $pcval);
483 $piitem = $iitem;
487 sub indexdiag {
488 my $iitem,$ientry,$w,$ww,$foo,$node;
489 open INDEXDIAG,">index.diag";
490 foreach $iitem (@itags) {
491 $ientry = $idxmap{$iitem};
492 print INDEXDIAG "<$iitem> ";
493 foreach $w (@$ientry) {
494 $ww = &word_txt($w);
495 print INDEXDIAG $ww unless $ww eq "\001";
497 print INDEXDIAG ":";
498 $foo = " ";
499 foreach $node (@nodes) {
500 (print INDEXDIAG $foo,$node), $foo = ", " if $idxnodes{$node,$iitem};
502 print INDEXDIAG "\n";
504 close INDEXDIAG;
507 sub fixup_xrefs {
508 my $pname, $p, $i, $j, $k, $caps, @repl;
510 for ($p=0; $p<=$#pnames; $p++) {
511 next if $pflags[$p] eq "code";
512 $pname = $pnames[$p];
513 for ($i=$#$pname; $i >= 0; $i--) {
514 if ($$pname[$i] =~ /^k/) {
515 $k = $$pname[$i];
516 $caps = ($k =~ /^kK/);
517 $k = substr($k,2);
518 $repl = $refs{$k};
519 die "undefined keyword `$k'\n" unless $repl;
520 substr($repl,0,1) =~ tr/a-z/A-Z/ if $caps;
521 @repl = ();
522 push @repl,"x $xrefs{$k}";
523 foreach $j (split /\s+/,$repl) {
524 push @repl,"n $j";
525 push @repl,"sp";
527 pop @repl; # remove final space
528 push @repl,"xe$xrefs{$k}";
529 splice @$pname,$i,1,@repl;
535 sub write_txt {
536 # This is called from the top level, so I won't bother using
537 # my or local.
539 # Open file.
540 print "writing file...";
541 open TEXT,">nasmdoc.txt";
542 select TEXT;
544 # Preamble.
545 $title = "The Netwide Assembler: NASM";
546 $spaces = ' ' x ((75-(length $title))/2);
547 ($underscore = $title) =~ s/./=/g;
548 print "$spaces$title\n$spaces$underscore\n";
550 for ($para = 0; $para <= $#pnames; $para++) {
551 $pname = $pnames[$para];
552 $pflags = $pflags[$para];
553 $ptype = substr($pflags,0,4);
555 print "\n"; # always one of these before a new paragraph
557 if ($ptype eq "chap") {
558 # Chapter heading. "Chapter N: Title" followed by a line of
559 # minus signs.
560 $pflags =~ /chap (.*) :(.*)/;
561 $title = "Chapter $1: ";
562 foreach $i (@$pname) {
563 $ww = &word_txt($i);
564 $title .= $ww unless $ww eq "\001";
566 print "$title\n";
567 $title =~ s/./-/g;
568 print "$title\n";
569 } elsif ($ptype eq "appn") {
570 # Appendix heading. "Appendix N: Title" followed by a line of
571 # minus signs.
572 $pflags =~ /appn (.*) :(.*)/;
573 $title = "Appendix $1: ";
574 foreach $i (@$pname) {
575 $ww = &word_txt($i);
576 $title .= $ww unless $ww eq "\001";
578 print "$title\n";
579 $title =~ s/./-/g;
580 print "$title\n";
581 } elsif ($ptype eq "head" || $ptype eq "subh") {
582 # Heading or subheading. Just a number and some text.
583 $pflags =~ /.... (.*) :(.*)/;
584 $title = sprintf "%6s ", $1;
585 foreach $i (@$pname) {
586 $ww = &word_txt($i);
587 $title .= $ww unless $ww eq "\001";
589 print "$title\n";
590 } elsif ($ptype eq "code") {
591 # Code paragraph. Emit each line with a seven character indent.
592 foreach $i (@$pname) {
593 warn "code line longer than 68 chars: $i\n" if length $i > 68;
594 print ' 'x7, $i, "\n";
596 } elsif ($ptype eq "bull" || $ptype eq "norm") {
597 # Ordinary paragraph, optionally bulleted. We wrap, with ragged
598 # 75-char right margin and either 7 or 11 char left margin
599 # depending on bullets.
600 if ($ptype eq "bull") {
601 $line = ' 'x7 . '(*) ';
602 $next = ' 'x11;
603 } else {
604 $line = $next = ' 'x7;
606 @a = @$pname;
607 $wd = $wprev = '';
608 do {
609 do { $w = &word_txt(shift @a) } while $w eq "\001"; # nasty hack
610 $wd .= $wprev;
611 if ($wprev =~ /-$/ || $w eq ' ' || $w eq '' || $w eq undef) {
612 if (length ($line . $wd) > 75) {
613 $line =~ s/\s*$//; # trim trailing spaces
614 print "$line\n";
615 $line = $next;
616 $wd =~ s/^\s*//; # trim leading spaces
618 $line .= $wd;
619 $wd = '';
621 $wprev = $w;
622 } while ($w ne '' && $w ne undef);
623 if ($line =~ /\S/) {
624 $line =~ s/\s*$//; # trim trailing spaces
625 print "$line\n";
630 # Close file.
631 select STDOUT;
632 close TEXT;
635 sub word_txt {
636 my ($w) = @_;
637 my $wtype, $wmajt;
639 return undef if $w eq '' || $w eq undef;
640 $wtype = substr($w,0,2);
641 $wmajt = substr($wtype,0,1);
642 $w = substr($w,2);
643 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
644 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
645 return $w;
646 } elsif ($wtype eq "sp") {
647 return ' ';
648 } elsif ($wtype eq "da") {
649 return '-';
650 } elsif ($wmajt eq "c" || $wtype eq "wc") {
651 return "`${w}'";
652 } elsif ($wtype eq "es") {
653 return "_${w}";
654 } elsif ($wtype eq "ee") {
655 return "${w}_";
656 } elsif ($wtype eq "eo") {
657 return "_${w}_";
658 } elsif ($wmajt eq "x" || $wmajt eq "i") {
659 return "\001";
660 } else {
661 die "panic in word_txt: $wtype$w\n";
665 sub write_html {
666 # This is called from the top level, so I won't bother using
667 # my or local.
669 # Write contents file. Just the preamble, then a menu of links to the
670 # separate chapter files and the nodes therein.
671 print "writing contents file...";
672 open TEXT,">nasmdoc0.html";
673 select TEXT;
674 &html_preamble(0);
675 print "<p>This manual documents NASM, the Netwide Assembler: an assembler\n";
676 print "targetting the Intel x86 series of processors, with portable source.\n";
677 print "<p>";
678 for ($node = $tstruct_next{'Top'}; $node; $node = $tstruct_next{$node}) {
679 if ($tstruct_level{$node} == 1) {
680 # Invent a file name.
681 ($number = lc($xrefnodes{$node})) =~ s/.*-//;
682 $fname="nasmdocx.html";
683 substr($fname,8 - length $number, length $number) = $number;
684 $html_fnames{$node} = $fname;
685 $link = $fname;
686 print "<p>";
687 } else {
688 # Use the preceding filename plus a marker point.
689 $link = $fname . "#$xrefnodes{$node}";
691 $title = "$node: ";
692 $pname = $tstruct_pname{$node};
693 foreach $i (@$pname) {
694 $ww = &word_html($i);
695 $title .= $ww unless $ww eq "\001";
697 print "<a href=\"$link\">$title</a><br>\n";
699 print "<p><a href=\"nasmdoci.html\">Index</a>\n";
700 print "</body></html>\n";
701 select STDOUT;
702 close TEXT;
704 # Open a null file, to ensure output (eg random &html_jumppoints calls)
705 # goes _somewhere_.
706 print "writing chapter files...";
707 open TEXT,">/dev/null";
708 select TEXT;
709 $html_lastf = '';
711 $in_list = 0;
713 for ($para = 0; $para <= $#pnames; $para++) {
714 $pname = $pnames[$para];
715 $pflags = $pflags[$para];
716 $ptype = substr($pflags,0,4);
718 $in_list = 0, print "</ul>\n" if $in_list && $ptype ne "bull";
719 if ($ptype eq "chap") {
720 # Chapter heading. Begin a new file.
721 $pflags =~ /chap (.*) :(.*)/;
722 $title = "Chapter $1: ";
723 $xref = $2;
724 &html_jumppoints; print "</body></html>\n"; select STDOUT; close TEXT;
725 $html_lastf = $html_fnames{$chapternode};
726 $chapternode = $nodexrefs{$xref};
727 $html_nextf = $html_fnames{$tstruct_mnext{$chapternode}};
728 open TEXT,">$html_fnames{$chapternode}"; select TEXT; &html_preamble(1);
729 foreach $i (@$pname) {
730 $ww = &word_html($i);
731 $title .= $ww unless $ww eq "\001";
733 $h = "<h2><a name=\"$xref\">$title</a></h2>\n";
734 print $h; print FULL $h;
735 } elsif ($ptype eq "appn") {
736 # Appendix heading. Begin a new file.
737 $pflags =~ /appn (.*) :(.*)/;
738 $title = "Appendix $1: ";
739 $xref = $2;
740 &html_jumppoints; print "</body></html>\n"; select STDOUT; close TEXT;
741 $html_lastf = $html_fnames{$chapternode};
742 $chapternode = $nodexrefs{$xref};
743 $html_nextf = $html_fnames{$tstruct_mnext{$chapternode}};
744 open TEXT,">$html_fnames{$chapternode}"; select TEXT; &html_preamble(1);
745 foreach $i (@$pname) {
746 $ww = &word_html($i);
747 $title .= $ww unless $ww eq "\001";
749 print "<h2><a name=\"$xref\">$title</a></h2>\n";
750 } elsif ($ptype eq "head" || $ptype eq "subh") {
751 # Heading or subheading.
752 $pflags =~ /.... (.*) :(.*)/;
753 $hdr = ($ptype eq "subh" ? "h4" : "h3");
754 $title = $1 . " ";
755 $xref = $2;
756 foreach $i (@$pname) {
757 $ww = &word_html($i);
758 $title .= $ww unless $ww eq "\001";
760 print "<$hdr><a name=\"$xref\">$title</a></$hdr>\n";
761 } elsif ($ptype eq "code") {
762 # Code paragraph.
763 print "<p><pre>\n";
764 foreach $i (@$pname) {
765 $w = $i;
766 $w =~ s/&/&amp;/g;
767 $w =~ s/</&lt;/g;
768 $w =~ s/>/&gt;/g;
769 print $w, "\n";
771 print "</pre>\n";
772 } elsif ($ptype eq "bull" || $ptype eq "norm") {
773 # Ordinary paragraph, optionally bulleted. We wrap, with ragged
774 # 75-char right margin and either 7 or 11 char left margin
775 # depending on bullets.
776 if ($ptype eq "bull") {
777 $in_list = 1, print "<ul>\n" unless $in_list;
778 $line = '<li>';
779 } else {
780 $line = '<p>';
782 @a = @$pname;
783 $wd = $wprev = '';
784 do {
785 do { $w = &word_html(shift @a) } while $w eq "\001"; # nasty hack
786 $wd .= $wprev;
787 if ($w eq ' ' || $w eq '' || $w eq undef) {
788 if (length ($line . $wd) > 75) {
789 $line =~ s/\s*$//; # trim trailing spaces
790 print "$line\n";
791 $line = '';
792 $wd =~ s/^\s*//; # trim leading spaces
794 $line .= $wd;
795 $wd = '';
797 $wprev = $w;
798 } while ($w ne '' && $w ne undef);
799 if ($line =~ /\S/) {
800 $line =~ s/\s*$//; # trim trailing spaces
801 print "$line\n";
806 # Close whichever file was open.
807 &html_jumppoints;
808 print "</body></html>\n";
809 select STDOUT;
810 close TEXT;
812 print "\n writing index file...";
813 open TEXT,">nasmdoci.html";
814 select TEXT;
815 &html_preamble(0);
816 print "<p align=center><a href=\"nasmdoc0.html\">Contents</a>\n";
817 print "<p>";
818 &html_index;
819 print "<p align=center><a href=\"nasmdoc0.html\">Contents</a>\n";
820 print "</body></html>\n";
821 select STDOUT;
822 close TEXT;
825 sub html_preamble {
826 print "<html><head><title>NASM Manual</title></head>\n";
827 print "<body><h1 align=center>The Netwide Assembler: NASM</h1>\n\n";
828 &html_jumppoints if $_[0];
831 sub html_jumppoints {
832 print "<p align=center>";
833 print "<a href=\"$html_nextf\">Next Chapter</a> |\n" if $html_nextf;
834 print "<a href=\"$html_lastf\">Previous Chapter</a> |\n" if $html_lastf;
835 print "<a href=\"nasmdoc0.html\">Contents</a> |\n";
836 print "<a href=\"nasmdoci.html\">Index</a>\n";
839 sub html_index {
840 my $itag, $a, @ientry, $sep, $w, $wd, $wprev, $line;
842 $chapternode = '';
843 foreach $itag (@itags) {
844 $ientry = $idxmap{$itag};
845 @a = @$ientry;
846 push @a, "n :";
847 $sep = 0;
848 foreach $node (@nodes) {
849 next if !$idxnodes{$node,$itag};
850 push @a, "n ," if $sep;
851 push @a, "sp", "x $xrefnodes{$node}", "n $node", "xe$xrefnodes{$node}";
852 $sep = 1;
854 $line = '';
855 do {
856 do { $w = &word_html(shift @a) } while $w eq "\001"; # nasty hack
857 $wd .= $wprev;
858 if ($w eq ' ' || $w eq '' || $w eq undef) {
859 if (length ($line . $wd) > 75) {
860 $line =~ s/\s*$//; # trim trailing spaces
861 print "$line\n";
862 $line = '';
863 $wd =~ s/^\s*//; # trim leading spaces
865 $line .= $wd;
866 $wd = '';
868 $wprev = $w;
869 } while ($w ne '' && $w ne undef);
870 if ($line =~ /\S/) {
871 $line =~ s/\s*$//; # trim trailing spaces
872 print "$line\n";
874 print "<br>\n";
878 sub word_html {
879 my ($w) = @_;
880 my $wtype, $wmajt, $pfx, $sfx;
882 return undef if $w eq '' || $w eq undef;
884 $wtype = substr($w,0,2);
885 $wmajt = substr($wtype,0,1);
886 $w = substr($w,2);
887 $pfx = $sfx = '';
888 $pfx = "<a href=\"$1\">", $sfx = "</a>", $w = $2
889 if $wmajt eq "w" && $w =~ /^<(.*)>(.*)$/;
890 $w =~ s/&/&amp;/g;
891 $w =~ s/</&lt;/g;
892 $w =~ s/>/&gt;/g;
893 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
894 return $pfx . $w . $sfx;
895 } elsif ($wtype eq "sp") {
896 return ' ';
897 } elsif ($wtype eq "da") {
898 return '-'; # sadly, en-dashes are non-standard in HTML
899 } elsif ($wmajt eq "c" || $wtype eq "wc") {
900 return $pfx . "<code><nobr>${w}</nobr></code>" . $sfx;
901 } elsif ($wtype eq "es") {
902 return "<em>${w}";
903 } elsif ($wtype eq "ee") {
904 return "${w}</em>";
905 } elsif ($wtype eq "eo") {
906 return "<em>${w}</em>";
907 } elsif ($wtype eq "x ") {
908 # Magic: we must resolve the cross reference into file and marker
909 # parts, then dispose of the file part if it's us, and dispose of
910 # the marker part if the cross reference describes the top node of
911 # another file.
912 my $node = $nodexrefs{$w}; # find the node we're aiming at
913 my $level = $tstruct_level{$node}; # and its level
914 my $up = $node, $uplev = $level-1;
915 $up = $tstruct_up{$up} while $uplev--; # get top node of containing file
916 my $file = ($up ne $chapternode) ? $html_fnames{$up} : "";
917 my $marker = ($level == 1 and $file) ? "" : "#$w";
918 return "<a href=\"$file$marker\">";
919 } elsif ($wtype eq "xe") {
920 return "</a>";
921 } elsif ($wmajt eq "i") {
922 return "\001";
923 } else {
924 die "panic in word_html: $wtype$w\n";
928 sub write_texi {
929 # This is called from the top level, so I won't bother using
930 # my or local.
932 # Open file.
933 print "writing file...";
934 open TEXT,">nasmdoc.texi";
935 select TEXT;
937 # Preamble.
938 print "\\input texinfo \@c -*-texinfo-*-\n";
939 print "\@c \%**start of header\n";
940 print "\@setfilename ",$metadata{'infofile'},".info\n";
941 print "\@dircategory ",$metadata{'category'},"\n";
942 print "\@direntry\n";
943 printf "* %-28s %s.\n",
944 sprintf('%s: (%s).', $metadata{'infoname'}, $metadata{'infofile'}),
945 $metadata{'infotitle'};
946 print "\@end direntry\n";
947 print "\@settitle ", $metadata{'title'},"\n";
948 print "\@setchapternewpage odd\n";
949 print "\@c \%**end of header\n";
950 print "\n";
951 print "\@ifinfo\n";
952 print $metadata{'summary'}, "\n";
953 print "\n";
954 print "Copyright ",$metadata{'year'}," ",$metadata{'author'},"\n";
955 print "\n";
956 print $metadata{'license'}, "\n";
957 print "\@end ifinfo\n";
958 print "\n";
959 print "\@titlepage\n";
960 $title = $metadata{'title'};
961 $title =~ s/ - / --- /g;
962 print "\@title ${title}\n";
963 print "\@author ",$metadata{'author'},"\n";
964 print "\n";
965 print "\@page\n";
966 print "\@vskip 0pt plus 1filll\n";
967 print "Copyright \@copyright{} ",$metadata{'year'},' ',$metadata{'author'},"\n";
968 print "\n";
969 print $metadata{'license'}, "\n";
970 print "\@end titlepage\n";
971 print "\n";
972 print "\@node Top, $tstruct_next{'Top'}, (dir), (dir)\n";
973 print "\@top ",$metadata{'infotitle'},"\n";
974 print "\n";
975 print "\@ifinfo\n";
976 print $metadata{'summary'}, "\n";
977 print "\@end ifinfo\n";
979 $node = "Top";
981 $bulleting = 0;
982 for ($para = 0; $para <= $#pnames; $para++) {
983 $pname = $pnames[$para];
984 $pflags = $pflags[$para];
985 $ptype = substr($pflags,0,4);
987 $bulleting = 0, print "\@end itemize\n" if $bulleting && $ptype ne "bull";
988 print "\n"; # always one of these before a new paragraph
990 if ($ptype eq "chap") {
991 # Chapter heading. Begin a new node.
992 &texi_menu($node)
993 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
994 $pflags =~ /chap (.*) :(.*)/;
995 $node = "Chapter $1";
996 $title = "Chapter $1: ";
997 foreach $i (@$pname) {
998 $ww = &word_texi($i);
999 $title .= $ww unless $ww eq "\001";
1001 print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},";
1002 print " $tstruct_up{$node}\n\@unnumbered $title\n";
1003 } elsif ($ptype eq "appn") {
1004 # Appendix heading. Begin a new node.
1005 &texi_menu($node)
1006 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1007 $pflags =~ /appn (.*) :(.*)/;
1008 $node = "Appendix $1";
1009 $title = "Appendix $1: ";
1010 foreach $i (@$pname) {
1011 $ww = &word_texi($i);
1012 $title .= $ww unless $ww eq "\001";
1014 print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},";
1015 print " $tstruct_up{$node}\n\@unnumbered $title\n";
1016 } elsif ($ptype eq "head" || $ptype eq "subh") {
1017 # Heading or subheading. Begin a new node.
1018 &texi_menu($node)
1019 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1020 $pflags =~ /.... (.*) :(.*)/;
1021 $node = "Section $1";
1022 $title = "$1. ";
1023 foreach $i (@$pname) {
1024 $ww = &word_texi($i);
1025 $title .= $ww unless $ww eq "\001";
1027 print "\@node $node, $tstruct_next{$node}, $tstruct_prev{$node},";
1028 print " $tstruct_up{$node}\n";
1029 $hdr = ($ptype eq "subh" ? "\@unnumberedsubsec" : "\@unnumberedsec");
1030 print "$hdr $title\n";
1031 } elsif ($ptype eq "code") {
1032 # Code paragraph. Surround with @example / @end example.
1033 print "\@example\n";
1034 foreach $i (@$pname) {
1035 warn "code line longer than 68 chars: $i\n" if length $i > 68;
1036 $i =~ s/\@/\@\@/g;
1037 $i =~ s/\{/\@\{/g;
1038 $i =~ s/\}/\@\}/g;
1039 print "$i\n";
1041 print "\@end example\n";
1042 } elsif ($ptype eq "bull" || $ptype eq "norm") {
1043 # Ordinary paragraph, optionally bulleted. We wrap, FWIW.
1044 if ($ptype eq "bull") {
1045 $bulleting = 1, print "\@itemize \@bullet\n" if !$bulleting;
1046 print "\@item\n";
1048 $line = '';
1049 @a = @$pname;
1050 $wd = $wprev = '';
1051 do {
1052 do { $w = &word_texi(shift @a); } while $w eq "\001"; # hack
1053 $wd .= $wprev;
1054 if ($wprev =~ /-$/ || $w eq ' ' || $w eq '' || $w eq undef) {
1055 if (length ($line . $wd) > 75) {
1056 $line =~ s/\s*$//; # trim trailing spaces
1057 print "$line\n";
1058 $line = '';
1059 $wd =~ s/^\s*//; # trim leading spaces
1061 $line .= $wd;
1062 $wd = '';
1064 $wprev = $w;
1065 } while ($w ne '' && $w ne undef);
1066 if ($line =~ /\S/) {
1067 $line =~ s/\s*$//; # trim trailing spaces
1068 print "$line\n";
1073 # Write index.
1074 &texi_index;
1076 # Close file.
1077 print "\n\@contents\n\@bye\n";
1078 select STDOUT;
1079 close TEXT;
1082 # Side effect of this procedure: update global `texiwdlen' to be the length
1083 # in chars of the formatted version of the word.
1084 sub word_texi {
1085 my ($w) = @_;
1086 my $wtype, $wmajt;
1088 return undef if $w eq '' || $w eq undef;
1089 $wtype = substr($w,0,2);
1090 $wmajt = substr($wtype,0,1);
1091 $w = substr($w,2);
1092 $wlen = length $w;
1093 $w =~ s/\@/\@\@/g;
1094 $w =~ s/\{/\@\{/g;
1095 $w =~ s/\}/\@\}/g;
1096 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
1097 substr($w,0,1) =~ tr/a-z/A-Z/, $capital = 0 if $capital;
1098 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
1099 $texiwdlen = $wlen;
1100 return $w;
1101 } elsif ($wtype eq "sp") {
1102 $texiwdlen = 1;
1103 return ' ';
1104 } elsif ($wtype eq "da") {
1105 $texiwdlen = 2;
1106 return '--';
1107 } elsif ($wmajt eq "c" || $wtype eq "wc") {
1108 $texiwdlen = 2 + $wlen;
1109 return "\@code\{$w\}";
1110 } elsif ($wtype eq "es") {
1111 $texiwdlen = 1 + $wlen;
1112 return "\@emph\{${w}";
1113 } elsif ($wtype eq "ee") {
1114 $texiwdlen = 1 + $wlen;
1115 return "${w}\}";
1116 } elsif ($wtype eq "eo") {
1117 $texiwdlen = 2 + $wlen;
1118 return "\@emph\{${w}\}";
1119 } elsif ($wtype eq "x ") {
1120 $texiwdlen = 0; # we don't need it in this case
1121 $capital = 1; # hack
1122 return "\@ref\{";
1123 } elsif ($wtype eq "xe") {
1124 $texiwdlen = 0; # we don't need it in this case
1125 return "\}";
1126 } elsif ($wmajt eq "i") {
1127 $texiwdlen = 0; # we don't need it in this case
1128 return "\001";
1129 } else {
1130 die "panic in word_texi: $wtype$w\n";
1134 sub texi_menu {
1135 my ($topitem) = @_;
1136 my $item, $i, $mpname, $title, $wd;
1138 $item = $tstruct_next{$topitem};
1139 print "\@menu\n";
1140 while ($item) {
1141 $title = "";
1142 $mpname = $tstruct_pname{$item};
1143 foreach $i (@$mpname) {
1144 $wd = &word_texi($i);
1145 $title .= $wd unless $wd eq "\001";
1147 print "* ${item}:: $title\n";
1148 $item = $tstruct_mnext{$item};
1150 print "* Index::\n" if $topitem eq "Top";
1151 print "\@end menu\n";
1154 sub texi_index {
1155 my $itag, $ientry, @a, $wd, $item, $len;
1156 my $subnums = "123456789ABCDEFGHIJKLMNOPQRSTU" .
1157 "VWXYZabcdefghijklmnopqrstuvwxyz";
1159 print "\@ifinfo\n\@node Index, , $FIXMElastnode, Top\n";
1160 print "\@unnumbered Index\n\n\@menu\n";
1162 foreach $itag (@itags) {
1163 $ientry = $idxmap{$itag};
1164 @a = @$ientry;
1165 $item = '';
1166 $len = 0;
1167 foreach $i (@a) {
1168 $wd = &word_texi($i);
1169 $item .= $wd, $len += $texiwdlen unless $wd eq "\001";
1171 $i = 0;
1172 foreach $node (@nodes) {
1173 next if !$idxnodes{$node,$itag};
1174 printf "* %s%s (%s): %s.\n",
1175 $item, " " x (40-$len), substr($subnums,$i++,1), $node;
1178 print "\@end menu\n\@end ifinfo\n";
1181 sub write_hlp {
1182 # This is called from the top level, so I won't bother using
1183 # my or local.
1185 # Build the index-tag text forms.
1186 print "building index entries...";
1187 @hlp_index = map {
1188 my $i,$ww;
1189 my $ientry = $idxmap{$_};
1190 my $title = "";
1191 foreach $i (@$ientry) {
1192 $ww = &word_hlp($i,0);
1193 $title .= $ww unless $ww eq "\001";
1195 $title;
1196 } @itags;
1198 # Write the HPJ project-description file.
1199 print "writing .hpj file...";
1200 open HPJ,">nasmdoc.hpj";
1201 print HPJ "[OPTIONS]\ncompress=true\n";
1202 print HPJ "title=NASM: The Netwide Assembler\noldkeyphrase=no\n\n";
1203 print HPJ "[FILES]\nnasmdoc.rtf\n\n";
1204 print HPJ "[CONFIG]\n";
1205 print HPJ 'CreateButton("btn_up", "&Up",'.
1206 ' "JumpContents(`nasmdoc.hlp'."'".')")';
1207 print HPJ "\nBrowseButtons()\n";
1208 close HPJ;
1210 # Open file.
1211 print "\n writing .rtf file...";
1212 open TEXT,">nasmdoc.rtf";
1213 select TEXT;
1215 # Preamble.
1216 print "{\\rtf1\\ansi{\\fonttbl\n";
1217 print "\\f0\\froman Times New Roman;\\f1\\fmodern Courier New;\n";
1218 print "\\f2\\fswiss Arial;\\f3\\ftech Wingdings}\\deff0\n";
1219 print "#{\\footnote Top}\n";
1220 print "\${\\footnote Contents}\n";
1221 print "+{\\footnote browse:00000}\n";
1222 print "!{\\footnote DisableButton(\"btn_up\")}\n";
1223 print "\\keepn\\f2\\b\\fs30\\sb0\n";
1224 print "NASM: The Netwide Assembler\n";
1225 print "\\par\\pard\\plain\\sb120\n";
1226 print "This file documents NASM, the Netwide Assembler: an assembler \n";
1227 print "targetting the Intel x86 series of processors, with portable source.\n";
1229 $node = "Top";
1230 $browse = 0;
1232 $newpar = "\\par\\sb120\n";
1233 for ($para = 0; $para <= $#pnames; $para++) {
1234 $pname = $pnames[$para];
1235 $pflags = $pflags[$para];
1236 $ptype = substr($pflags,0,4);
1238 print $newpar;
1239 $newpar = "\\par\\sb120\n";
1241 if ($ptype eq "chap") {
1242 # Chapter heading. Begin a new node.
1243 &hlp_menu($node)
1244 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1245 $pflags =~ /chap (.*) :(.*)/;
1246 $node = "Chapter $1";
1247 $title = $footnotetitle = "Chapter $1: ";
1248 foreach $i (@$pname) {
1249 $ww = &word_hlp($i,1);
1250 $title .= $ww, $footnotetitle .= &word_hlp($i,0) unless $ww eq "\001";
1252 print "\\page\n";
1253 printf "#{\\footnote %s}\n", &hlp_sectkw($node);
1254 print "\${\\footnote $footnotetitle}\n";
1255 printf "+{\\footnote browse:%05d}\n", ++$browse;
1256 printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," .
1257 "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n",
1258 &hlp_sectkw($tstruct_up{$node});
1259 print "EnableButton(\"btn_up\")}\n";
1260 &hlp_keywords($node);
1261 print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n";
1262 print "$title\n";
1263 $newpar = "\\par\\pard\\plain\\sb120\n";
1264 } elsif ($ptype eq "appn") {
1265 # Appendix heading. Begin a new node.
1266 &hlp_menu($node)
1267 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1268 $pflags =~ /appn (.*) :(.*)/;
1269 $node = "Appendix $1";
1270 $title = $footnotetitle = "Appendix $1: ";
1271 foreach $i (@$pname) {
1272 $ww = &word_hlp($i,1);
1273 $title .= $ww, $footnotetitle .= &word_hlp($i,0) unless $ww eq "\001";
1275 print "\\page\n";
1276 printf "#{\\footnote %s}\n", &hlp_sectkw($node);
1277 print "\${\\footnote $footnotetitle}\n";
1278 printf "+{\\footnote browse:%05d}\n", ++$browse;
1279 printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," .
1280 "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n",
1281 &hlp_sectkw($tstruct_up{$node});
1282 print "EnableButton(\"btn_up\")}\n";
1283 &hlp_keywords($node);
1284 print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n";
1285 print "$title\n";
1286 $newpar = "\\par\\pard\\plain\\sb120\n";
1287 } elsif ($ptype eq "head" || $ptype eq "subh") {
1288 # Heading or subheading. Begin a new node.
1289 &hlp_menu($node)
1290 if $tstruct_level{$tstruct_next{$node}} > $tstruct_level{$node};
1291 $pflags =~ /.... (.*) :(.*)/;
1292 $node = "Section $1";
1293 $title = $footnotetitle = "$1. ";
1294 foreach $i (@$pname) {
1295 $ww = &word_hlp($i,1);
1296 $title .= $ww, $footnotetitle .= &word_hlp($i,0) unless $ww eq "\001";
1298 print "\\page\n";
1299 printf "#{\\footnote %s}\n", &hlp_sectkw($node);
1300 print "\${\\footnote $footnotetitle}\n";
1301 printf "+{\\footnote browse:%05d}\n", ++$browse;
1302 printf "!{\\footnote ChangeButtonBinding(\"btn_up\"," .
1303 "\"JumpId(\`nasmdoc.hlp',\`%s')\");\n",
1304 &hlp_sectkw($tstruct_up{$node});
1305 print "EnableButton(\"btn_up\")}\n";
1306 &hlp_keywords($node);
1307 print "\\keepn\\f2\\b\\fs30\\sb60\\sa60\n";
1308 print "$title\n";
1309 $newpar = "\\par\\pard\\plain\\sb120\n";
1310 } elsif ($ptype eq "code") {
1311 # Code paragraph.
1312 print "\\keep\\f1\\sb120\n";
1313 foreach $i (@$pname) {
1314 my $x = $i;
1315 warn "code line longer than 68 chars: $i\n" if length $i > 68;
1316 $x =~ s/\\/\\\\/g;
1317 $x =~ s/\{/\\\{/g;
1318 $x =~ s/\}/\\\}/g;
1319 print "$x\\par\\sb0\n";
1321 $newpar = "\\pard\\f0\\sb120\n";
1322 } elsif ($ptype eq "bull" || $ptype eq "norm") {
1323 # Ordinary paragraph, optionally bulleted. We wrap, FWIW.
1324 if ($ptype eq "bull") {
1325 print "\\tx360\\li360\\fi-360{\\f3\\'9F}\\tab\n";
1326 $newpar = "\\par\\pard\\sb120\n";
1327 } else {
1328 $newpar = "\\par\\sb120\n";
1330 $line = '';
1331 @a = @$pname;
1332 $wd = $wprev = '';
1333 do {
1334 do { $w = &word_hlp((shift @a),1); } while $w eq "\001"; # hack
1335 $wd .= $wprev;
1336 if ($w eq ' ' || $w eq '' || $w eq undef) {
1337 if (length ($line . $wd) > 75) {
1338 $line =~ s/\s*$//; # trim trailing spaces
1339 print "$line \n"; # and put one back
1340 $line = '';
1341 $wd =~ s/^\s*//; # trim leading spaces
1343 $line .= $wd;
1344 $wd = '';
1346 $wprev = $w;
1347 } while ($w ne '' && $w ne undef);
1348 if ($line =~ /\S/) {
1349 $line =~ s/\s*$//; # trim trailing spaces
1350 print "$line\n";
1355 # Close file.
1356 print "\\page}\n";
1357 select STDOUT;
1358 close TEXT;
1361 sub word_hlp {
1362 my ($w, $docode) = @_;
1363 my $wtype, $wmajt;
1365 return undef if $w eq '' || $w eq undef;
1366 $wtype = substr($w,0,2);
1367 $wmajt = substr($wtype,0,1);
1368 $w = substr($w,2);
1369 $w =~ s/\\/\\\\/g;
1370 $w =~ s/\{/\\\{/g;
1371 $w =~ s/\}/\\\}/g;
1372 $w =~ s/<.*>// if $wmajt eq "w"; # remove web links
1373 substr($w,0,length($w)-1) =~ s/-/\\\'AD/g if $wmajt ne "x"; #nonbreakhyphens
1374 if ($wmajt eq "n" || $wtype eq "e " || $wtype eq "w ") {
1375 return $w;
1376 } elsif ($wtype eq "sp") {
1377 return ' ';
1378 } elsif ($wtype eq "da") {
1379 return "\\'96";
1380 } elsif ($wmajt eq "c" || $wtype eq "wc") {
1381 $w =~ s/ /\\\'A0/g; # make spaces non-breaking
1382 return $docode ? "{\\f1 ${w}}" : $w;
1383 } elsif ($wtype eq "es") {
1384 return "{\\i ${w}";
1385 } elsif ($wtype eq "ee") {
1386 return "${w}}";
1387 } elsif ($wtype eq "eo") {
1388 return "{\\i ${w}}";
1389 } elsif ($wtype eq "x ") {
1390 return "{\\uldb ";
1391 } elsif ($wtype eq "xe") {
1392 $w = &hlp_sectkw($w);
1393 return "}{\\v ${w}}";
1394 } elsif ($wmajt eq "i") {
1395 return "\001";
1396 } else {
1397 die "panic in word_hlp: $wtype$w\n";
1401 sub hlp_menu {
1402 my ($topitem) = @_;
1403 my $item, $kword, $i, $mpname, $title;
1405 $item = $tstruct_next{$topitem};
1406 print "\\li360\\fi-360\n";
1407 while ($item) {
1408 $title = "";
1409 $mpname = $tstruct_pname{$item};
1410 foreach $i (@$mpname) {
1411 $ww = &word_hlp($i, 0);
1412 $title .= $ww unless $ww eq "\001";
1414 $kword = &hlp_sectkw($item);
1415 print "{\\uldb ${item}: $title}{\\v $kword}\\par\\sb0\n";
1416 $item = $tstruct_mnext{$item};
1418 print "\\pard\\sb120\n";
1421 sub hlp_sectkw {
1422 my ($node) = @_;
1423 $node =~ tr/A-Z/a-z/;
1424 $node =~ tr/- ./___/;
1425 $node;
1428 sub hlp_keywords {
1429 my ($node) = @_;
1430 my $pfx = "K{\\footnote ";
1431 my $done = 0;
1432 foreach $i (0..$#itags) {
1433 (print $pfx,$hlp_index[$i]), $pfx = ";\n", $done++
1434 if $idxnodes{$node,$itags[$i]};
1436 print "}\n" if $done;
1439 # Make tree structures. $tstruct_* is top-level and global.
1440 sub add_item {
1441 my ($item, $level) = @_;
1442 my $i;
1444 $tstruct_pname{$item} = $pname;
1445 $tstruct_next{$tstruct_previtem} = $item;
1446 $tstruct_prev{$item} = $tstruct_previtem;
1447 $tstruct_level{$item} = $level;
1448 $tstruct_up{$item} = $tstruct_last[$level-1];
1449 $tstruct_mnext{$tstruct_last[$level]} = $item;
1450 $tstruct_last[$level] = $item;
1451 for ($i=$level+1; $i<$MAXLEVEL; $i++) { $tstruct_last[$i] = undef; }
1452 $tstruct_previtem = $item;
1453 push @nodes, $item;
1457 # This produces documentation intermediate paragraph format; this is
1458 # basically the digested output of the front end. Intended for use
1459 # by future backends, instead of putting it all in the same script.
1461 sub write_dip {
1462 open(PARAS, "> nasmdoc.dip");
1463 foreach $k (keys(%metadata)) {
1464 print PARAS 'meta :', $k, "\n";
1465 print PARAS $metadata{$k},"\n";
1467 for ($para = 0; $para <= $#pnames; $para++) {
1468 print PARAS $pflags[$para], "\n";
1469 print PARAS join("\037", @{$pnames[$para]}, "\n");
1471 foreach $k (@itags) {
1472 print PARAS 'indx :', $k, "\n";
1473 print PARAS join("\037", @{$idxmap{$k}}), "\n";
1475 close(PARAS);