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