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