1 #!/usr/local/bin/perl 2 'di '; 3 'ig 00 '; 4 #+############################################################################## 5 # # 6 # File: texi2html # 7 # # 8 # Description: Program to transform most Texinfo documents to HTML # 9 # # 10 #-############################################################################## 11 12 # @(#)texi2html 1.52b 01/05/98 Written (mainly) by Lionel Cons, Lionel.Cons (at] cern.ch 13 # 1.52a: Use acute accent instead of apostrophe. Add support for ISO-8859-1 14 # characters with cedilla, circumflex etc. 15 # 1.52b: Add option -expandtex. Expand @ifhtml by default, not @ifinfo. 16 # Use Unicode quotation marks instead of grave and acute accents. 17 # Emit charset=UTF-8 declaration. 18 19 # The man page for this program is included at the end of this file and can be 20 # viewed using the command 'nroff -man texi2html'. 21 # Please read the copyright at the end of the man page. 22 23 #+++############################################################################ 24 # # 25 # Constants # 26 # # 27 #---############################################################################ 28 29 $DEBUG_TOC = 1; 30 $DEBUG_INDEX = 2; 31 $DEBUG_BIB = 4; 32 $DEBUG_GLOSS = 8; 33 $DEBUG_DEF = 16; 34 $DEBUG_HTML = 32; 35 $DEBUG_USER = 64; 36 37 $BIBRE = '\[[\w\/-]+\]'; # RE for a bibliography reference 38 $FILERE = '[\/\w.+-]+'; # RE for a file name 39 $VARRE = '[^\s\{\}]+'; # RE for a variable name 40 $NODERE = '[^@{}:\'`",]+'; # RE for a node name 41 $NODESRE = '[^@{}:\'`"]+'; # RE for a list of node names 42 $XREFRE = '[^@{}]+'; # RE for a xref (should use NODERE) 43 44 $ERROR = "***"; # prefix for errors and warnings 45 $THISPROG = "texi2html 1.52b"; # program name and version 46 $HOMEPAGE = "http://wwwinfo.cern.ch/dis/texi2html/"; # program home page 47 $TODAY = &pretty_date; # like "20 September 1993" 48 $SPLITTAG = "<!-- SPLIT HERE -->\n"; # tag to know where to split 49 $PROTECTTAG = "_ThisIsProtected_"; # tag to recognize protected sections 50 $html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//EN">'; 51 52 # 53 # language dependent constants 54 # 55 #$LDC_SEE = 'see'; 56 #$LDC_SECTION = 'section'; 57 #$LDC_IN = 'in'; 58 #$LDC_TOC = 'Table of Contents'; 59 #$LDC_GOTO = 'Go to the'; 60 #$LDC_FOOT = 'Footnotes'; 61 # TODO: @def* shortcuts 62 63 # 64 # pre-defined indices 65 # 66 %predefined_index = ( 67 'cp', 'c', 68 'fn', 'f', 69 'vr', 'v', 70 'ky', 'k', 71 'pg', 'p', 72 'tp', 't', 73 ); 74 75 # 76 # valid indices 77 # 78 %valid_index = ( 79 'c', 1, 80 'f', 1, 81 'v', 1, 82 'k', 1, 83 'p', 1, 84 't', 1, 85 ); 86 87 # 88 # texinfo section names to level 89 # 90 %sec2level = ( 91 'top', 0, 92 'chapter', 1, 93 'unnumbered', 1, 94 'majorheading', 1, 95 'chapheading', 1, 96 'appendix', 1, 97 'section', 2, 98 'unnumberedsec', 2, 99 'heading', 2, 100 'appendixsec', 2, 101 'appendixsection', 2, 102 'subsection', 3, 103 'unnumberedsubsec', 3, 104 'subheading', 3, 105 'appendixsubsec', 3, 106 'subsubsection', 4, 107 'unnumberedsubsubsec', 4, 108 'subsubheading', 4, 109 'appendixsubsubsec', 4, 110 ); 111 112 # 113 # accent map, TeX command to ISO name 114 # 115 %accent_map = ( 116 '"', 'uml', 117 '~', 'tilde', 118 '^', 'circ', 119 '`', 'grave', 120 '\'', 'acute', 121 ); 122 123 # 124 # texinfo "simple things" (@foo) to HTML ones 125 # 126 %simple_map = ( 127 # cf. makeinfo.c 128 "*", "<BR>", # HTML+ 129 " ", " ", 130 "\n", "\n", 131 "|", "", 132 # spacing commands 133 ":", "", 134 "!", "!", 135 "?", "?", 136 ".", ".", 137 "-", "", 138 ); 139 140 # 141 # texinfo "things" (@foo{}) to HTML ones 142 # 143 %things_map = ( 144 'TeX', 'TeX', 145 'br', '<P>', # paragraph break 146 'bullet', '*', 147 'copyright', '(C)', 148 'dots', '...', 149 'equiv', '==', 150 'error', 'error-->', 151 'expansion', '==>', 152 'minus', '-', 153 'point', '-!-', 154 'print', '-|', 155 'result', '=>', 156 'today', $TODAY, 157 'aa', 'å', 158 'AA', 'Å', 159 'ae', 'æ', 160 'AE', 'Æ', 161 'o', 'ø', 162 'O', 'Ø', 163 'ss', 'ß', 164 'exclamdown', '¡', 165 'questiondown', '¿', 166 'pounds', '£' 167 ); 168 169 # 170 # texinfo styles (@foo{bar}) to HTML ones 171 # 172 %style_map = ( 173 'asis', '', 174 'b', 'B', 175 'cite', 'CITE', 176 'code', 'CODE', 177 'ctrl', '&do_ctrl', # special case 178 'dfn', 'EM', # DFN tag is illegal in the standard 179 'dmn', '', # useless 180 'email', '&do_email', # insert a clickable email address 181 'emph', 'EM', 182 'file', '"TT', # will put quotes, cf. &apply_style 183 'i', 'I', 184 'kbd', 'KBD', 185 'key', 'KBD', 186 'math', 'EM', 187 'r', '', # unsupported 188 'samp', '"SAMP', # will put quotes, cf. &apply_style 189 'sc', '&do_sc', # special case 190 'strong', 'STRONG', 191 't', 'TT', 192 'titlefont', '', # useless 193 'uref', '&do_uref', # insert a clickable URL 194 'url', '&do_url', # insert a clickable URL 195 'var', 'VAR', 196 'w', '', # unsupported 197 '"', '&do_diaeresis', 198 '\'', '&do_acuteaccent', # doesn't work?? 199 '\`', '&do_graveaccent', # doesn't work?? 200 '~', '&do_tildeaccent', 201 ',', '&do_cedilla', 202 '^', '&do_circumflex', 203 ); 204 205 # 206 # texinfo format (@foo/@end foo) to HTML ones 207 # 208 %format_map = ( 209 'display', 'PRE', 210 'example', 'PRE', 211 'format', 'PRE', 212 'lisp', 'PRE', 213 'quotation', 'BLOCKQUOTE', 214 'smallexample', 'PRE', 215 'smalllisp', 'PRE', 216 # lists 217 'itemize', 'UL', 218 'enumerate', 'OL', 219 # poorly supported 220 'flushleft', 'PRE', 221 'flushright', 'PRE', 222 ); 223 224 # 225 # texinfo definition shortcuts to real ones 226 # 227 %def_map = ( 228 # basic commands 229 'deffn', 0, 230 'defvr', 0, 231 'deftypefn', 0, 232 'deftypevr', 0, 233 'defcv', 0, 234 'defop', 0, 235 'deftp', 0, 236 # basic x commands 237 'deffnx', 0, 238 'defvrx', 0, 239 'deftypefnx', 0, 240 'deftypevrx', 0, 241 'defcvx', 0, 242 'defopx', 0, 243 'deftpx', 0, 244 # shortcuts 245 'defun', 'deffn Function', 246 'defmac', 'deffn Macro', 247 'defspec', 'deffn {Special Form}', 248 'defvar', 'defvr Variable', 249 'defopt', 'defvr {User Option}', 250 'deftypefun', 'deftypefn Function', 251 'deftypevar', 'deftypevr Variable', 252 'defivar', 'defcv {Instance Variable}', 253 'defmethod', 'defop Method', 254 # x shortcuts 255 'defunx', 'deffnx Function', 256 'defmacx', 'deffnx Macro', 257 'defspecx', 'deffnx {Special Form}', 258 'defvarx', 'defvrx Variable', 259 'defoptx', 'defvrx {User Option}', 260 'deftypefunx', 'deftypefnx Function', 261 'deftypevarx', 'deftypevrx Variable', 262 'defivarx', 'defcvx {Instance Variable}', 263 'defmethodx', 'defopx Method', 264 ); 265 266 # 267 # things to skip 268 # 269 %to_skip = ( 270 # comments 271 'c', 1, 272 'comment', 1, 273 # useless 274 'contents', 1, 275 'shortcontents', 1, 276 'summarycontents', 1, 277 'footnotestyle', 1, 278 'end ifclear', 1, 279 'end ifset', 1, 280 'titlepage', 1, 281 'end titlepage', 1, 282 # unsupported commands (formatting) 283 'afourpaper', 1, 284 'cropmarks', 1, 285 'finalout', 1, 286 'headings', 1, 287 'need', 1, 288 'page', 1, 289 'setchapternewpage', 1, 290 'everyheading', 1, 291 'everyfooting', 1, 292 'evenheading', 1, 293 'evenfooting', 1, 294 'oddheading', 1, 295 'oddfooting', 1, 296 'smallbook', 1, 297 'vskip', 1, 298 'filbreak', 1, 299 'paragraphindent', 1, 300 # unsupported formats 301 'cartouche', 1, 302 'end cartouche', 1, 303 'group', 1, 304 'end group', 1, 305 ); 306 307 #+++############################################################################ 308 # # 309 # Argument parsing, initialisation # 310 # # 311 #---############################################################################ 312 313 %value = (); # hold texinfo variables, see also -D 314 315 $use_bibliography = 1; 316 $use_acc = 0; 317 $debug = 0; 318 $doctype = ''; 319 $check = 0; 320 $expandinfo = 0; 321 $expandtex = 0; 322 $use_glossary = 0; 323 $invisible_mark = ''; 324 $use_iso = 0; 325 @include_dirs = (); 326 $show_menu = 0; 327 $number_sections = 0; 328 $split_node = 0; 329 $split_chapter = 0; 330 $monolithic = 0; 331 $verbose = 0; 332 $usage = <<EOT; 333 This is $THISPROG 334 To convert a Texinfo file to HMTL: $0 [options] file 335 where options can be: 336 -expandinfo : use \@ifinfo sections, not \@ifhtml 337 -expandtex : use \@iftex sections, not \@ifhtml 338 -glossary : handle a glossary 339 -invisible name: use 'name' as an invisible anchor 340 -Dname : define name like with \@set 341 -I dir : search also for files in 'dir' 342 -menu : handle menus 343 -monolithic : output only one file including ToC 344 -number : number sections 345 -split_chapter : split on main sections 346 -split_node : split on nodes 347 -usage : print usage instructions 348 -verbose : verbose output 349 To check converted files: $0 -check [-verbose] files 350 EOT 351 352 while (@ARGV && $ARGV[0] =~ /^-/) { 353 $_ = shift(@ARGV); 354 if (/^-acc$/) { $use_acc = 1; next; } 355 if (/^-d(ebug)?(\d+)?$/) { $debug = $2 || shift(@ARGV); next; } 356 if (/^-doctype$/) { $doctype = shift(@ARGV); next; } 357 if (/^-c(heck)?$/) { $check = 1; next; } 358 if (/^-expandi(nfo)?$/) { $expandinfo = 1; next; } 359 if (/^-expandt(ex)?$/) { $expandtex = 1; next; } 360 if (/^-g(lossary)?$/) { $use_glossary = 1; next; } 361 if (/^-i(nvisible)?$/) { $invisible_mark = shift(@ARGV); next; } 362 if (/^-iso$/) { $use_iso = 1; next; } 363 if (/^-D(.+)?$/) { $value{$1 || shift(@ARGV)} = 1; next; } 364 if (/^-I(.+)?$/) { push(@include_dirs, $1 || shift(@ARGV)); next; } 365 if (/^-m(enu)?$/) { $show_menu = 1; next; } 366 if (/^-mono(lithic)?$/) { $monolithic = 1; next; } 367 if (/^-n(umber)?$/) { $number_sections = 1; next; } 368 if (/^-s(plit)?_?(n(ode)?|c(hapter)?)?$/) { 369 if ($2 =~ /^n/) { 370 $split_node = 1; 371 } else { 372 $split_chapter = 1; 373 } 374 next; 375 } 376 if (/^-v(erbose)?$/) { $verbose = 1; next; } 377 die $usage; 378 } 379 if ($check) { 380 die $usage unless @ARGV > 0; 381 ✓ 382 exit; 383 } 384 385 if (($split_node || $split_chapter) && $monolithic) { 386 warn "Can't use -monolithic with -split, -monolithic ignored.\n"; 387 $monolithic = 0; 388 } 389 if ($expandinfo) { 390 $to_skip{'ifinfo'}++; 391 $to_skip{'end ifinfo'}++; 392 $to_skip{'ifnottex'}++; 393 $to_skip{'end ifnottex'}++; 394 $to_skip{'ifnothtml'}++; 395 $to_skip{'end ifnothtml'}++; 396 } elsif ($expandtex) { 397 $to_skip{'ifnotinfo'}++; 398 $to_skip{'end ifnotinfo'}++; 399 $to_skip{'iftex'}++; 400 $to_skip{'end iftex'}++; 401 $to_skip{'ifnothtml'}++; 402 $to_skip{'end ifnothtml'}++; 403 } else { 404 $to_skip{'ifnotinfo'}++; 405 $to_skip{'end ifnotinfo'}++; 406 $to_skip{'ifnottex'}++; 407 $to_skip{'end ifnottex'}++; 408 $to_skip{'ifhtml'}++; 409 $to_skip{'end ifhtml'}++; 410 } 411 $invisible_mark = '<IMG SRC="invisible.xbm">' if $invisible_mark eq 'xbm'; 412 die $usage unless @ARGV == 1; 413 $docu = shift(@ARGV); 414 if ($docu =~ /.*\//) { 415 chop($docu_dir = $&); 416 $docu_name = $'; 417 } else { 418 $docu_dir = '.'; 419 $docu_name = $docu; 420 } 421 unshift(@include_dirs, $docu_dir); 422 $docu_name =~ s/\.te?x(i|info)?$//; # basename of the document 423 424 $docu_doc = "$docu_name.html"; # document's contents 425 if ($monolithic) { 426 $docu_toc = $docu_foot = $docu_doc; 427 } else { 428 $docu_toc = "${docu_name}_toc.html"; # document's table of contents 429 $docu_foot = "${docu_name}_foot.html"; # document's footnotes 430 } 431 432 # 433 # variables 434 # 435 $value{'html'} = 1; # predefine html (the output format) 436 $value{'texi2html'} = '1.52b'; # predefine texi2html (the translator) 437 # _foo: internal to track @foo 438 foreach ('_author', '_title', '_subtitle', 439 '_settitle', '_setfilename') { 440 $value{$_} = ''; # prevent -w warnings 441 } 442 %node2sec = (); # node to section name 443 %node2href = (); # node to HREF 444 %bib2href = (); # bibliography reference to HREF 445 %gloss2href = (); # glossary term to HREF 446 @sections = (); # list of sections 447 %tag2pro = (); # protected sections 448 449 # 450 # initial indexes 451 # 452 $bib_num = 0; 453 $foot_num = 0; 454 $gloss_num = 0; 455 $idx_num = 0; 456 $sec_num = 0; 457 $doc_num = 0; 458 $html_num = 0; 459 460 # 461 # can I use ISO8879 characters? (HTML+) 462 # 463 if ($use_iso) { 464 $things_map{'bullet'} = "•"; 465 $things_map{'copyright'} = "©"; 466 $things_map{'dots'} = "…"; 467 $things_map{'equiv'} = "≡"; 468 $things_map{'expansion'} = "→"; 469 $things_map{'point'} = "∗"; 470 $things_map{'result'} = "⇒"; 471 } 472 473 # 474 # read texi2html extensions (if any) 475 # 476 $extensions = 'texi2html.ext'; # extensions in working directory 477 if (-f $extensions) { 478 print "# reading extensions from $extensions\n" if $verbose; 479 require($extensions); 480 } 481 ($progdir = $0) =~ s/[^\/]+$//; 482 if ($progdir && ($progdir ne './')) { 483 $extensions = "${progdir}texi2html.ext"; # extensions in texi2html directory 484 if (-f $extensions) { 485 print "# reading extensions from $extensions\n" if $verbose; 486 require($extensions); 487 } 488 } 489 490 print "# reading from $docu\n" if $verbose; 491 492 #+++############################################################################ 493 # # 494 # Pass 1: read source, handle command, variable, simple substitution # 495 # # 496 #---############################################################################ 497 498 @lines = (); # whole document 499 @toc_lines = (); # table of contents 500 $toplevel = 0; # top level seen in hierarchy 501 $curlevel = 0; # current level in TOC 502 $node = ''; # current node name 503 $in_table = 0; # am I inside a table 504 $table_type = ''; # type of table ('', 'f', 'v', 'multi') 505 @tables = (); # nested table support 506 $in_bibliography = 0; # am I inside a bibliography 507 $in_glossary = 0; # am I inside a glossary 508 $in_top = 0; # am I inside the top node 509 $in_pre = 0; # am I inside a preformatted section 510 $in_list = 0; # am I inside a list 511 $in_html = 0; # am I inside an HTML section 512 $first_line = 1; # is it the first line 513 $dont_html = 0; # don't protect HTML on this line 514 $split_num = 0; # split index 515 $deferred_ref = ''; # deferred reference for indexes 516 @html_stack = (); # HTML elements stack 517 $html_element = ''; # current HTML element 518 &html_reset; 519 520 # build code for simple substitutions 521 # the maps used (%simple_map and %things_map) MUST be aware of this 522 # watch out for regexps, / and escaped characters! 523 $subst_code = ''; 524 foreach (keys(%simple_map)) { 525 ($re = $_) =~ s/(\W)/\\$1/g; # protect regexp chars 526 $subst_code .= "s/\\\@$re/$simple_map{$_}/g;\n"; 527 } 528 foreach (keys(%things_map)) { 529 $subst_code .= "s/\\\@$_\\{\\}/$things_map{$_}/g;\n"; 530 } 531 if ($use_acc) { 532 # accentuated characters 533 foreach (keys(%accent_map)) { 534 if ($_ eq "`") { 535 $subst_code .= "s/$;3"; 536 } elsif ($_ eq "'") { 537 $subst_code .= "s/$;4"; 538 } else { 539 $subst_code .= "s/\\\@\\$_"; 540 } 541 $subst_code .= "([aeiou])/&\${1}$accent_map{$_};/gi;\n"; 542 } 543 } 544 eval("sub simple_substitutions { $subst_code }"); 545 546 &init_input; 547 while ($_ = &next_line) { 548 # 549 # remove \input on the first lines only 550 # 551 if ($first_line) { 552 next if /^\\input/; 553 $first_line = 0; 554 } 555 # 556 # parse texinfo tags 557 # 558 $tag = ''; 559 $end_tag = ''; 560 if (/^\@end\s+(\w+)\b/) { 561 $end_tag = $1; 562 } elsif (/^\@(\w+)\b/) { 563 $tag = $1; 564 } 565 # 566 # handle @ifhtml / @end ifhtml 567 # 568 if ($in_html) { 569 if ($end_tag eq 'ifhtml') { 570 $in_html = 0; 571 } else { 572 $tag2pro{$in_html} .= $_; 573 } 574 next; 575 } elsif ($tag eq 'ifhtml') { 576 $in_html = $PROTECTTAG . ++$html_num; 577 push(@lines, $in_html); 578 next; 579 } 580 # 581 # try to skip the line 582 # 583 if ($end_tag) { 584 next if $to_skip{"end $end_tag"}; 585 } elsif ($tag) { 586 next if $to_skip{$tag}; 587 last if $tag eq 'bye'; 588 } 589 if ($in_top) { 590 # parsing the top node 591 if ($tag eq 'node' || $tag eq 'include' || $sec2level{$tag}) { 592 # no more in top 593 $in_top = 0; 594 } else { 595 # skip it 596 next; 597 } 598 } 599 # 600 # try to remove inlined comments 601 # syntax from tex-mode.el comment-start-skip 602 # 603 s/((^|[^\@])(\@\@)*)\@c(omment)? .*/$1/; 604 # non-@ substitutions cf. texinfmt.el 605 unless ($in_pre) { 606 s/``//g; 607 s/''//g; 608 s/([\w ])---([\w ])/$1--$2/g; 609 } 610 # 611 # analyze the tag 612 # 613 if ($tag) { 614 # skip lines 615 &skip_until($tag), next if $tag eq 'ignore'; 616 if ($expandinfo) { 617 &skip_until($tag), next if $tag eq 'ifnotinfo'; 618 &skip_until($tag), next if $tag eq 'iftex'; 619 &skip_until($tag), next if $tag eq 'ifhtml'; 620 } elsif ($expandtex) { 621 &skip_until($tag), next if $tag eq 'ifinfo'; 622 &skip_until($tag), next if $tag eq 'ifnottex'; 623 &skip_until($tag), next if $tag eq 'ifhtml'; 624 } else { 625 &skip_until($tag), next if $tag eq 'ifinfo'; 626 &skip_until($tag), next if $tag eq 'iftex'; 627 &skip_until($tag), next if $tag eq 'ifnothtml'; 628 } 629 &skip_until($tag), next if $tag eq 'tex'; 630 # handle special tables 631 if ($tag =~ /^(|f|v|multi)table$/) { 632 $table_type = $1; 633 $tag = 'table'; 634 } 635 # special cases 636 if ($tag eq 'top' || ($tag eq 'node' && /^\@node\s+top\s*,/i)) { 637 $in_top = 1; 638 @lines = (); # ignore all lines before top (title page garbage) 639 next; 640 } elsif ($tag eq 'node') { 641 $in_top = 0; 642 warn "$ERROR Bad node line: $_" unless $_ =~ /^\@node\s$NODESRE$/o; 643 $_ = &protect_html($_); # if node contains '&' for instance 644 s/^\@node\s+//; 645 ($node) = split(/,/); 646 &normalise_node($node); 647 if ($split_node) { 648 &next_doc; 649 push(@lines, $SPLITTAG) if $split_num++; 650 push(@sections, $node); 651 } 652 next; 653 } elsif ($tag eq 'include') { 654 if (/^\@include\s+($FILERE)\s*$/o) { 655 $file = $1; 656 unless (-e $file) { 657 foreach $dir (@include_dirs) { 658 $file = "$dir/$1"; 659 last if -e $file; 660 } 661 } 662 if (-e $file) { 663 &open($file); 664 print "# including $file\n" if $verbose; 665 } else { 666 warn "$ERROR Can't find $file, skipping"; 667 } 668 } else { 669 warn "$ERROR Bad include line: $_"; 670 } 671 next; 672 } elsif ($tag eq 'ifclear') { 673 if (/^\@ifclear\s+($VARRE)\s*$/o) { 674 next unless defined($value{$1}); 675 &skip_until($tag); 676 } else { 677 warn "$ERROR Bad ifclear line: $_"; 678 } 679 next; 680 } elsif ($tag eq 'ifset') { 681 if (/^\@ifset\s+($VARRE)\s*$/o) { 682 next if defined($value{$1}); 683 &skip_until($tag); 684 } else { 685 warn "$ERROR Bad ifset line: $_"; 686 } 687 next; 688 } elsif ($tag eq 'menu') { 689 unless ($show_menu) { 690 &skip_until($tag); 691 next; 692 } 693 &html_push_if($tag); 694 push(@lines, &html_debug("\n", __LINE__)); 695 } elsif ($format_map{$tag}) { 696 $in_pre = 1 if $format_map{$tag} eq 'PRE'; 697 &html_push_if($format_map{$tag}); 698 push(@lines, &html_debug("\n", __LINE__)); 699 $in_list++ if $format_map{$tag} eq 'UL' || $format_map{$tag} eq 'OL' ; 700 push(@lines, &debug("<$format_map{$tag}>\n", __LINE__)); 701 next; 702 } elsif ($tag eq 'table') { 703 if (/^\@(|f|v|multi)table\s+\@(\w+)/) { 704 $in_table = $2; 705 unshift(@tables, join($;, $table_type, $in_table)); 706 if ($table_type eq "multi") { 707 push(@lines, &debug("<TABLE BORDER>\n", __LINE__)); 708 &html_push_if('TABLE'); 709 } else { 710 push(@lines, &debug("<DL COMPACT>\n", __LINE__)); 711 &html_push_if('DL'); 712 } 713 push(@lines, &html_debug("\n", __LINE__)); 714 } else { 715 warn "$ERROR Bad table line: $_"; 716 } 717 next; 718 } elsif ($tag eq 'synindex' || $tag eq 'syncodeindex') { 719 if (/^\@$tag\s+(\w)\w\s+(\w)\w\s*$/) { 720 eval("*${1}index = *${2}index"); 721 } else { 722 warn "$ERROR Bad syn*index line: $_"; 723 } 724 next; 725 } elsif ($tag eq 'sp') { 726 push(@lines, &debug("<P>\n", __LINE__)); 727 next; 728 } elsif ($tag eq 'setref') { 729 &protect_html; # if setref contains '&' for instance 730 if (/^\@$tag\s*{($NODERE)}\s*$/) { 731 $setref = $1; 732 $setref =~ s/\s+/ /g; # normalize 733 $setref =~ s/ $//; 734 $node2sec{$setref} = $name; 735 $node2href{$setref} = "$docu_doc#$docid"; 736 } else { 737 warn "$ERROR Bad setref line: $_"; 738 } 739 next; 740 } elsif ($tag eq 'defindex' || $tag eq 'defcodeindex') { 741 if (/^\@$tag\s+(\w\w)\s*$/) { 742 $valid_index{$1} = 1; 743 } else { 744 warn "$ERROR Bad defindex line: $_"; 745 } 746 next; 747 } elsif (defined($def_map{$tag})) { 748 if ($def_map{$tag}) { 749 s/^\@$tag\s+//; 750 $tag = $def_map{$tag}; 751 $_ = "\@$tag $_"; 752 $tag =~ s/\s.*//; 753 } 754 } elsif (defined($user_sub{$tag})) { 755 s/^\@$tag\s+//; 756 $sub = $user_sub{$tag}; 757 print "# user $tag = $sub, arg: $_" if $debug & $DEBUG_USER; 758 if (defined(&$sub)) { 759 chop($_); 760 &$sub($_); 761 } else { 762 warn "$ERROR Bad user sub for $tag: $sub\n"; 763 } 764 next; 765 } 766 if (defined($def_map{$tag})) { 767 s/^\@$tag\s+//; 768 if ($tag =~ /x$/) { 769 # extra definition line 770 $tag = $`; 771 $is_extra = 1; 772 } else { 773 $is_extra = 0; 774 } 775 while (/\{([^\{\}]*)\}/) { 776 # this is a {} construct 777 ($before, $contents, $after) = ($`, $1, $'); 778 # protect spaces 779 $contents =~ s/\s+/$;9/g; 780 # restore $_ protecting {} 781 $_ = "$before$;7$contents$;8$after"; 782 } 783 @args = split(/\s+/, &protect_html($_)); 784 foreach (@args) { 785 s/$;9/ /g; # unprotect spaces 786 s/$;7/\{/g; # ... { 787 s/$;8/\}/g; # ... } 788 } 789 $type = shift(@args); 790 $type =~ s/^\{(.*)\}$/$1/; 791 print "# def ($tag): {$type} ", join(', ', @args), "\n" 792 if $debug & $DEBUG_DEF; 793 $type .= ':'; # it's nicer like this 794 $name = shift(@args); 795 $name =~ s/^\{(.*)\}$/$1/; 796 if ($is_extra) { 797 $_ = &debug("<DT>", __LINE__); 798 } else { 799 $_ = &debug("<DL>\n<DT>", __LINE__); 800 } 801 if ($tag eq 'deffn' || $tag eq 'defvr' || $tag eq 'deftp') { 802 $_ .= "<U>$type</U> <B>$name</B>"; 803 $_ .= " <I>@args</I>" if @args; 804 } elsif ($tag eq 'deftypefn' || $tag eq 'deftypevr' 805 || $tag eq 'defcv' || $tag eq 'defop') { 806 $ftype = $name; 807 $name = shift(@args); 808 $name =~ s/^\{(.*)\}$/$1/; 809 $_ .= "<U>$type</U> $ftype <B>$name</B>"; 810 $_ .= " <I>@args</I>" if @args; 811 } else { 812 warn "$ERROR Unknown definition type: $tag\n"; 813 $_ .= "<U>$type</U> <B>$name</B>"; 814 $_ .= " <I>@args</I>" if @args; 815 } 816 $_ .= &debug("\n<DD>", __LINE__); 817 $name = &unprotect_html($name); 818 if ($tag eq 'deffn' || $tag eq 'deftypefn') { 819 unshift(@input_spool, "\@findex $name\n"); 820 } elsif ($tag eq 'defop') { 821 unshift(@input_spool, "\@findex $name on $ftype\n"); 822 } elsif ($tag eq 'defvr' || $tag eq 'deftypevr' || $tag eq 'defcv') { 823 unshift(@input_spool, "\@vindex $name\n"); 824 } else { 825 unshift(@input_spool, "\@tindex $name\n"); 826 } 827 $dont_html = 1; 828 } 829 } elsif ($end_tag) { 830 if ($format_map{$end_tag}) { 831 $in_pre = 0 if $format_map{$end_tag} eq 'PRE'; 832 $in_list-- if $format_map{$end_tag} eq 'UL' || $format_map{$end_tag} eq 'OL' ; 833 &html_pop_if('LI', 'P'); 834 &html_pop_if(); 835 push(@lines, &debug("</$format_map{$end_tag}>\n", __LINE__)); 836 push(@lines, &html_debug("\n", __LINE__)); 837 } elsif ($end_tag =~ /^(|f|v|multi)table$/) { 838 unless (@tables) { 839 warn "$ERROR \@end $end_tag without \@*table\n"; 840 next; 841 } 842 ($table_type, $in_table) = split($;, shift(@tables)); 843 unless ($1 eq $table_type) { 844 warn "$ERROR \@end $end_tag without matching \@$end_tag\n"; 845 next; 846 } 847 if ($table_type eq "multi") { 848 push(@lines, "</TR></TABLE>\n"); 849 &html_pop_if('TR'); 850 } else { 851 push(@lines, "</DL>\n"); 852 &html_pop_if('DD'); 853 } 854 &html_pop_if(); 855 if (@tables) { 856 ($table_type, $in_table) = split($;, $tables[0]); 857 } else { 858 $in_table = 0; 859 } 860 } elsif (defined($def_map{$end_tag})) { 861 push(@lines, &debug("</DL>\n", __LINE__)); 862 } elsif ($end_tag eq 'menu') { 863 &html_pop_if(); 864 push(@lines, $_); # must keep it for pass 2 865 } 866 next; 867 } 868 # 869 # misc things 870 # 871 # protect texi and HTML things 872 &protect_texi; 873 $_ = &protect_html($_) unless $dont_html; 874 $dont_html = 0; 875 # substitution (unsupported things) 876 s/^\@center\s+//g; 877 s/^\@exdent\s+//g; 878 s/\@noindent\s+//g; 879 s/\@refill\s+//g; 880 # other substitutions 881 &simple_substitutions; 882 s/\@value{($VARRE)}/$value{$1}/eg; 883 s/\@footnote\{/\@footnote$docu_doc\{/g; # mark footnotes, cf. pass 4 884 # 885 # analyze the tag again 886 # 887 if ($tag) { 888 if (defined($sec2level{$tag}) && $sec2level{$tag} > 0) { 889 if (/^\@$tag\s+(.+)$/) { 890 $name = $1; 891 $name =~ s/\s+$//; 892 $level = $sec2level{$tag}; 893 $name = &update_sec_num($tag, $level) . " $name" 894 if $number_sections && $tag !~ /^unnumbered/; 895 if ($tag =~ /heading$/) { 896 push(@lines, &html_debug("\n", __LINE__)); 897 if ($html_element ne 'body') { 898 # We are in a nice pickle here. We are trying to get a H? heading 899 # even though we are not in the body level. So, we convert it to a 900 # nice, bold, line by itself. 901 $_ = &debug("\n\n<P><STRONG>$name</STRONG></P>\n\n", __LINE__); 902 } else { 903 $_ = &debug("<H$level>$name</H$level>\n", __LINE__); 904 &html_push_if('body'); 905 } 906 print "# heading, section $name, level $level\n" 907 if $debug & $DEBUG_TOC; 908 } else { 909 if ($split_chapter) { 910 unless ($toplevel) { 911 # first time we see a "section" 912 unless ($level == 1) { 913 warn "$ERROR The first section found is not of level 1: $_"; 914 warn "$ERROR I'll split on sections of level $level...\n"; 915 } 916 $toplevel = $level; 917 } 918 if ($level == $toplevel) { 919 &next_doc; 920 push(@lines, $SPLITTAG) if $split_num++; 921 push(@sections, $name); 922 } 923 } 924 $sec_num++; 925 $docid = "SEC$sec_num"; 926 $tocid = "TOC$sec_num"; 927 # check biblio and glossary 928 $in_bibliography = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*bibliography$/i); 929 $in_glossary = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*glossary$/i); 930 # check node 931 if ($node) { 932 if ($node2sec{$node}) { 933 warn "$ERROR Duplicate node found: $node\n"; 934 } else { 935 $node2sec{$node} = $name; 936 $node2href{$node} = "$docu_doc#$docid"; 937 print "# node $node, section $name, level $level\n" 938 if $debug & $DEBUG_TOC; 939 } 940 $node = ''; 941 } else { 942 print "# no node, section $name, level $level\n" 943 if $debug & $DEBUG_TOC; 944 } 945 # update TOC 946 while ($level > $curlevel) { 947 $curlevel++; 948 push(@toc_lines, "<UL>\n"); 949 } 950 while ($level < $curlevel) { 951 $curlevel--; 952 push(@toc_lines, "</UL>\n"); 953 } 954 $_ = "<LI>" . &anchor($tocid, "$docu_doc#$docid", $name, 1); 955 push(@toc_lines, &substitute_style($_)); 956 # update DOC 957 push(@lines, &html_debug("\n", __LINE__)); 958 &html_reset; 959 $_ = "<H$level>".&anchor($docid, "$docu_toc#$tocid", $name)."</H$level>\n"; 960 $_ = &debug($_, __LINE__); 961 push(@lines, &html_debug("\n", __LINE__)); 962 } 963 # update DOC 964 foreach $line (split(/\n+/, $_)) { 965 push(@lines, "$line\n"); 966 } 967 next; 968 } else { 969 warn "$ERROR Bad section line: $_"; 970 } 971 } else { 972 # track variables 973 $value{$1} = $2, next if /^\@set\s+($VARRE)\s+(.*)$/o; 974 delete $value{$1}, next if /^\@clear\s+($VARRE)\s*$/o; 975 # store things 976 $value{'_setfilename'} = $1, next if /^\@setfilename\s+(.*)$/; 977 $value{'_settitle'} = $1, next if /^\@settitle\s+(.*)$/; 978 $value{'_author'} .= "$1\n", next if /^\@author\s+(.*)$/; 979 $value{'_subtitle'} .= "$1\n", next if /^\@subtitle\s+(.*)$/; 980 $value{'_title'} .= "$1\n", next if /^\@title\s+(.*)$/; 981 # index 982 if (/^\@(..?)index\s+/) { 983 unless ($valid_index{$1}) { 984 warn "$ERROR Undefined index command: $_"; 985 next; 986 } 987 $id = 'IDX' . ++$idx_num; 988 $index = $1 . 'index'; 989 $what = &substitute_style($'); 990 $what =~ s/\s+$//; 991 print "# found $index for '$what' id $id\n" 992 if $debug & $DEBUG_INDEX; 993 eval(<<EOC); 994 if (defined(\$$index\{\$what\})) { 995 \$$index\{\$what\} .= "$;$docu_doc#$id"; 996 } else { 997 \$$index\{\$what\} = "$docu_doc#$id"; 998 } 999 EOC 1000 # 1001 # dirty hack to see if I can put an invisible anchor... 1002 # 1003 if ($html_element eq 'P' || 1004 $html_element eq 'LI' || 1005 $html_element eq 'DT' || 1006 $html_element eq 'DD' || 1007 $html_element eq 'ADDRESS' || 1008 $html_element eq 'B' || 1009 $html_element eq 'BLOCKQUOTE' || 1010 $html_element eq 'PRE' || 1011 $html_element eq 'SAMP') { 1012 push(@lines, &anchor($id, '', $invisible_mark, !$in_pre)); 1013 } elsif ($html_element eq 'body') { 1014 push(@lines, &debug("<P>\n", __LINE__)); 1015 push(@lines, &anchor($id, '', $invisible_mark, !$in_pre)); 1016 &html_push('P'); 1017 } elsif ($html_element eq 'DL' || 1018 $html_element eq 'UL' || 1019 $html_element eq 'OL' ) { 1020 $deferred_ref .= &anchor($id, '', $invisible_mark, !$in_pre) . " "; 1021 } 1022 next; 1023 } 1024 # list item 1025 if (/^\@itemx?\s+/) { 1026 $what = $'; 1027 $what =~ s/\s+$//; 1028 if ($in_bibliography && $use_bibliography) { 1029 if ($what =~ /^$BIBRE$/o) { 1030 $id = 'BIB' . ++$bib_num; 1031 $bib2href{$what} = "$docu_doc#$id"; 1032 print "# found bibliography for '$what' id $id\n" 1033 if $debug & $DEBUG_BIB; 1034 $what = &anchor($id, '', $what); 1035 } 1036 } elsif ($in_glossary && $use_glossary) { 1037 $id = 'GLOSS' . ++$gloss_num; 1038 $entry = $what; 1039 $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/; 1040 $gloss2href{$entry} = "$docu_doc#$id"; 1041 print "# found glossary for '$entry' id $id\n" 1042 if $debug & $DEBUG_GLOSS; 1043 $what = &anchor($id, '', $what); 1044 } 1045 &html_pop_if('P'); 1046 if ($html_element eq 'DL' || $html_element eq 'DD') { 1047 if ($things_map{$in_table} && !$what) { 1048 # special case to allow @table @bullet for instance 1049 push(@lines, &debug("<DT>$things_map{$in_table}\n", __LINE__)); 1050 } else { 1051 push(@lines, &debug("<DT>\@$in_table\{$what\}\n", __LINE__)); 1052 } 1053 push(@lines, "<DD>"); 1054 &html_push('DD') unless $html_element eq 'DD'; 1055 if ($table_type) { # add also an index 1056 unshift(@input_spool, "\@${table_type}index $what\n"); 1057 } 1058 } elsif ($html_element eq 'TABLE') { 1059 push(@lines, &debug("<TR><TD>$what</TD>\n", __LINE__)); 1060 &html_push('TR'); 1061 } elsif ($html_element eq 'TR') { 1062 push(@lines, &debug("</TR>\n", __LINE__)); 1063 push(@lines, &debug("<TR><TD>$what</TD>\n", __LINE__)); 1064 } else { 1065 push(@lines, &debug("<LI>$what\n", __LINE__)); 1066 &html_push('LI') unless $html_element eq 'LI'; 1067 } 1068 push(@lines, &html_debug("\n", __LINE__)); 1069 if ($deferred_ref) { 1070 push(@lines, &debug("$deferred_ref\n", __LINE__)); 1071 $deferred_ref = ''; 1072 } 1073 next; 1074 } elsif (/^\@tab\s+(.*)$/) { 1075 push(@lines, "<TD>$1</TD>\n"); 1076 next; 1077 } 1078 } 1079 } 1080 # paragraph separator 1081 if ($_ eq "\n") { 1082 next if $#lines >= 0 && $lines[$#lines] eq "\n"; 1083 if ($html_element eq 'P') { 1084 push(@lines, "\n"); 1085 $_ = &debug("</P>\n", __LINE__); 1086 &html_pop; 1087 } 1088 } elsif ($html_element eq 'body' || $html_element eq 'BLOCKQUOTE') { 1089 push(@lines, "<P>\n"); 1090 &html_push('P'); 1091 $_ = &debug($_, __LINE__); 1092 } 1093 # otherwise 1094 push(@lines, $_); 1095 } 1096 1097 # finish TOC 1098 $level = 0; 1099 while ($level < $curlevel) { 1100 $curlevel--; 1101 push(@toc_lines, "</UL>\n"); 1102 } 1103 1104 print "# end of pass 1\n" if $verbose; 1105 1106 #+++############################################################################ 1107 # # 1108 # Pass 2/3: handle style, menu, index, cross-reference # 1109 # # 1110 #---############################################################################ 1111 1112 @lines2 = (); # whole document (2nd pass) 1113 @lines3 = (); # whole document (3rd pass) 1114 $in_menu = 0; # am I inside a menu 1115 1116 while (@lines) { 1117 $_ = shift(@lines); 1118 # 1119 # special case (protected sections) 1120 # 1121 if (/^$PROTECTTAG/o) { 1122 push(@lines2, $_); 1123 next; 1124 } 1125 # 1126 # menu 1127 # 1128 $in_menu = 1, push(@lines2, &debug("<UL>\n", __LINE__)), next if /^\@menu\b/; 1129 $in_menu = 0, push(@lines2, &debug("</UL>\n", __LINE__)), next if /^\@end\s+menu\b/; 1130 if ($in_menu) { 1131 if (/^\*\s+($NODERE)::/o) { 1132 $descr = $'; 1133 chop($descr); 1134 &menu_entry($1, $1, $descr); 1135 } elsif (/^\*\s+(.+):\s+([^\t,\.\n]+)[\t,\.\n]/) { 1136 $descr = $'; 1137 chop($descr); 1138 &menu_entry($1, $2, $descr); 1139 } elsif (/^\*/) { 1140 warn "$ERROR Bad menu line: $_"; 1141 } else { # description continued? 1142 push(@lines2, $_); 1143 } 1144 next; 1145 } 1146 # 1147 # printindex 1148 # 1149 if (/^\@printindex\s+(\w\w)\b/) { 1150 local($index, *ary, @keys, $key, $letter, $last_letter, @refs); 1151 if ($predefined_index{$1}) { 1152 $index = $predefined_index{$1} . 'index'; 1153 } else { 1154 $index = $1 . 'index'; 1155 } 1156 eval("*ary = *$index"); 1157 @keys = keys(%ary); 1158 foreach $key (@keys) { 1159 $_ = $key; 1160 1 while s/<(\w+)>\`(.*)\´<\/\1>/$2/; # remove HTML tags with quotes 1161 1 while s/<(\w+)>(.*)<\/\1>/$2/; # remove HTML tags 1162 $_ = &unprotect_html($_); 1163 &unprotect_texi; 1164 tr/A-Z/a-z/; # lowercase 1165 $key2alpha{$key} = $_; 1166 print "# index $key sorted as $_\n" 1167 if $key ne $_ && $debug & $DEBUG_INDEX; 1168 } 1169 push(@lines2, "Jump to:\n"); 1170 $last_letter = undef; 1171 foreach $key (sort byalpha @keys) { 1172 $letter = substr($key2alpha{$key}, 0, 1); 1173 $letter = substr($key2alpha{$key}, 0, 2) if $letter eq $;; 1174 if (!defined($last_letter) || $letter ne $last_letter) { 1175 push(@lines2, "-\n") if defined($last_letter); 1176 push(@lines2, "<A HREF=\"#$index\_$letter\">" . &protect_html($letter) . "</A>\n"); 1177 $last_letter = $letter; 1178 } 1179 } 1180 push(@lines2, "<P>\n"); 1181 $last_letter = undef; 1182 foreach $key (sort byalpha @keys) { 1183 $letter = substr($key2alpha{$key}, 0, 1); 1184 $letter = substr($key2alpha{$key}, 0, 2) if $letter eq $;; 1185 if (!defined($last_letter) || $letter ne $last_letter) { 1186 push(@lines2, "</DIR>\n") if defined($last_letter); 1187 push(@lines2, "<H2><A NAME=\"$index\_$letter\">" . &protect_html($letter) . "</A></H2>\n"); 1188 push(@lines2, "<DIR>\n"); 1189 $last_letter = $letter; 1190 } 1191 @refs = (); 1192 foreach (split(/$;/, $ary{$key})) { 1193 push(@refs, &anchor('', $_, $key, 0)); 1194 } 1195 push(@lines2, "<LI>" . join(", ", @refs) . "\n"); 1196 } 1197 push(@lines2, "</DIR>\n") if defined($last_letter); 1198 next; 1199 } 1200 # 1201 # simple style substitutions 1202 # 1203 $_ = &substitute_style($_); 1204 # 1205 # xref 1206 # 1207 while (/\@(x|px|info|)ref{($XREFRE)(}?)/o) { 1208 # note: Texinfo may accept other characters 1209 ($type, $nodes, $full) = ($1, $2, $3); 1210 ($before, $after) = ($`, $'); 1211 if (! $full && $after) { 1212 warn "$ERROR Bad xref (no ending } on line): $_"; 1213 $_ = "$before$;0${type}ref\{$nodes$after"; 1214 next; # while xref 1215 } 1216 if ($type eq 'x') { 1217 $type = 'See '; 1218 } elsif ($type eq 'px') { 1219 $type = 'see '; 1220 } elsif ($type eq 'info') { 1221 $type = 'See Info'; 1222 } else { 1223 $type = ''; 1224 } 1225 unless ($full) { 1226 $next = shift(@lines); 1227 $next = &substitute_style($next); 1228 chop($nodes); # remove final newline 1229 if ($next =~ /\}/) { # split on 2 lines 1230 $nodes .= " $`"; 1231 $after = $'; 1232 } else { 1233 $nodes .= " $next"; 1234 $next = shift(@lines); 1235 $next = &substitute_style($next); 1236 chop($nodes); 1237 if ($next =~ /\}/) { # split on 3 lines 1238 $nodes .= " $`"; 1239 $after = $'; 1240 } else { 1241 warn "$ERROR Bad xref (no ending }): $_"; 1242 $_ = "$before$;0xref\{$nodes$after"; 1243 unshift(@lines, $next); 1244 next; # while xref 1245 } 1246 } 1247 } 1248 $nodes =~ s/\s+/ /g; # remove useless spaces 1249 @args = split(/\s*,\s*/, $nodes); 1250 $node = $args[0]; # the node is always the first arg 1251 &normalise_node($node); 1252 $sec = $node2sec{$node}; 1253 if (@args == 5) { # reference to another manual 1254 $sec = $args[2] || $node; 1255 $man = $args[4] || $args[3]; 1256 $_ = "${before}${type}section $sec in \@cite{$man}$after"; 1257 } elsif ($type =~ /Info/) { # inforef 1258 warn "$ERROR Wrong number of arguments: $_" unless @args == 3; 1259 ($nn, $_, $in) = @args; 1260 $_ = "${before}${type} file $in, node $nn$after"; 1261 } elsif ($sec) { 1262 $href = $node2href{$node}; 1263 $_ = "${before}${type}section " . &anchor('', $href, $sec) . $after; 1264 } else { 1265 warn "$ERROR Undefined node ($node): $_"; 1266 $_ = "$before$;0xref{$nodes}$after"; 1267 } 1268 } 1269 # 1270 # try to guess bibliography references or glossary terms 1271 # 1272 unless (/^<H\d><A NAME=\"SEC\d/) { 1273 if ($use_bibliography) { 1274 $done = ''; 1275 while (/$BIBRE/o) { 1276 ($pre, $what, $post) = ($`, $&, $'); 1277 $href = $bib2href{$what}; 1278 if (defined($href) && $post !~ /^[^<]*<\/A>/) { 1279 $done .= $pre . &anchor('', $href, $what); 1280 } else { 1281 $done .= "$pre$what"; 1282 } 1283 $_ = $post; 1284 } 1285 $_ = $done . $_; 1286 } 1287 if ($use_glossary) { 1288 $done = ''; 1289 while (/\b\w+\b/) { 1290 ($pre, $what, $post) = ($`, $&, $'); 1291 $entry = $what; 1292 $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/; 1293 $href = $gloss2href{$entry}; 1294 if (defined($href) && $post !~ /^[^<]*<\/A>/) { 1295 $done .= $pre . &anchor('', $href, $what); 1296 } else { 1297 $done .= "$pre$what"; 1298 } 1299 $_ = $post; 1300 } 1301 $_ = $done . $_; 1302 } 1303 } 1304 # otherwise 1305 push(@lines2, $_); 1306 } 1307 print "# end of pass 2\n" if $verbose; 1308 1309 # 1310 # split style substitutions 1311 # 1312 while (@lines2) { 1313 $_ = shift(@lines2); 1314 # 1315 # special case (protected sections) 1316 # 1317 if (/^$PROTECTTAG/o) { 1318 push(@lines3, $_); 1319 next; 1320 } 1321 # 1322 # split style substitutions 1323 # 1324 $old = ''; 1325 while ($old ne $_) { 1326 $old = $_; 1327 if (/\@(\w+|"|\~|,|\^)\{/) { 1328 ($before, $style, $after) = ($`, $1, $'); 1329 if (defined($style_map{$style})) { 1330 $_ = $after; 1331 $text = ''; 1332 $after = ''; 1333 $failed = 1; 1334 while (@lines2) { 1335 if (/\}/) { 1336 $text .= $`; 1337 $after = $'; 1338 $failed = 0; 1339 last; 1340 } else { 1341 $text .= $_; 1342 $_ = shift(@lines2); 1343 } 1344 } 1345 if ($failed) { 1346 die "* Bad syntax (\@$style) after: $before\n"; 1347 } else { 1348 $text = &apply_style($style, $text); 1349 $_ = "$before$text$after"; 1350 } 1351 } 1352 } 1353 } 1354 # otherwise 1355 push(@lines3, $_); 1356 } 1357 print "# end of pass 3\n" if $verbose; 1358 1359 #+++############################################################################ 1360 # # 1361 # Pass 4: foot notes, final cleanup # 1362 # # 1363 #---############################################################################ 1364 1365 @foot_lines = (); # footnotes 1366 @doc_lines = (); # final document 1367 $end_of_para = 0; # true if last line is <P> 1368 1369 while (@lines3) { 1370 $_ = shift(@lines3); 1371 # 1372 # special case (protected sections) 1373 # 1374 if (/^$PROTECTTAG/o) { 1375 push(@doc_lines, $_); 1376 $end_of_para = 0; 1377 next; 1378 } 1379 # 1380 # footnotes 1381 # 1382 while (/\@footnote([^\{\s]+)\{/) { 1383 ($before, $d, $after) = ($`, $1, $'); 1384 $_ = $after; 1385 $text = ''; 1386 $after = ''; 1387 $failed = 1; 1388 while (@lines3) { 1389 if (/\}/) { 1390 $text .= $`; 1391 $after = $'; 1392 $failed = 0; 1393 last; 1394 } else { 1395 $text .= $_; 1396 $_ = shift(@lines3); 1397 } 1398 } 1399 if ($failed) { 1400 die "* Bad syntax (\@footnote) after: $before\n"; 1401 } else { 1402 $foot_num++; 1403 $docid = "DOCF$foot_num"; 1404 $footid = "FOOT$foot_num"; 1405 $foot = "($foot_num)"; 1406 push(@foot_lines, "<H3>" . &anchor($footid, "$d#$docid", $foot) . "</H3>\n"); 1407 $text = "<P>$text" unless $text =~ /^\s*<P>/; 1408 push(@foot_lines, "$text\n"); 1409 $_ = $before . &anchor($docid, "$docu_foot#$footid", $foot) . $after; 1410 } 1411 } 1412 # 1413 # remove unnecessary <P> 1414 # 1415 if (/^\s*<P>\s*$/) { 1416 next if $end_of_para++; 1417 } else { 1418 $end_of_para = 0; 1419 } 1420 # otherwise 1421 push(@doc_lines, $_); 1422 } 1423 print "# end of pass 4\n" if $verbose; 1424 1425 #+++############################################################################ 1426 # # 1427 # Pass 5: print things # 1428 # # 1429 #---############################################################################ 1430 1431 $header = <<EOT; 1432 <!-- This HTML file has been created by $THISPROG 1433 from $docu on $TODAY --> 1434 EOT 1435 1436 $full_title = $value{'_title'} || $value{'_settitle'} || "Untitled Document"; 1437 $title = $value{'_settitle'} || $full_title; 1438 $_ = &substitute_style($full_title); 1439 &unprotect_texi; 1440 s/\n$//; # rmv last \n (if any) 1441 $full_title = "<H1>" . join("</H1>\n<H1>", split(/\n/, $_)) . "</H1>\n"; 1442 1443 # 1444 # print ToC 1445 # 1446 if (!$monolithic && @toc_lines) { 1447 if (open(FILE, "> $docu_toc")) { 1448 print "# creating $docu_toc...\n" if $verbose; 1449 &print_toplevel_header("$title - Table of Contents"); 1450 &print_ruler; 1451 &print(*toc_lines, FILE); 1452 &print_toplevel_footer; 1453 close(FILE); 1454 } else { 1455 warn "$ERROR Can't write to $docu_toc: $!\n"; 1456 } 1457 } 1458 1459 # 1460 # print footnotes 1461 # 1462 if (!$monolithic && @foot_lines) { 1463 if (open(FILE, "> $docu_foot")) { 1464 print "# creating $docu_foot...\n" if $verbose; 1465 &print_toplevel_header("$title - Footnotes"); 1466 &print_ruler; 1467 &print(*foot_lines, FILE); 1468 &print_toplevel_footer; 1469 close(FILE); 1470 } else { 1471 warn "$ERROR Can't write to $docu_foot: $!\n"; 1472 } 1473 } 1474 1475 # 1476 # print document 1477 # 1478 if ($split_chapter || $split_node) { # split 1479 $doc_num = 0; 1480 $last_num = scalar(@sections); 1481 $first_doc = &doc_name(1); 1482 $last_doc = &doc_name($last_num); 1483 while (@sections) { 1484 $section = shift(@sections); 1485 &next_doc; 1486 if (open(FILE, "> $docu_doc")) { 1487 print "# creating $docu_doc...\n" if $verbose; 1488 &print_header("$title - $section"); 1489 $prev_doc = ($doc_num == 1 ? undef : &doc_name($doc_num - 1)); 1490 $next_doc = ($doc_num == $last_num ? undef : &doc_name($doc_num + 1)); 1491 $navigation = "Go to the "; 1492 $navigation .= ($prev_doc ? &anchor('', $first_doc, "first") : "first"); 1493 $navigation .= ", "; 1494 $navigation .= ($prev_doc ? &anchor('', $prev_doc, "previous") : "previous"); 1495 $navigation .= ", "; 1496 $navigation .= ($next_doc ? &anchor('', $next_doc, "next") : "next"); 1497 $navigation .= ", "; 1498 $navigation .= ($next_doc ? &anchor('', $last_doc, "last") : "last"); 1499 $navigation .= " section, " . &anchor('', $docu_toc, "table of contents") . ".\n"; 1500 print FILE $navigation; 1501 &print_ruler; 1502 # find corresponding lines 1503 @tmp_lines = (); 1504 while (@doc_lines) { 1505 $_ = shift(@doc_lines); 1506 last if ($_ eq $SPLITTAG); 1507 push(@tmp_lines, $_); 1508 } 1509 &print(*tmp_lines, FILE); 1510 &print_ruler; 1511 print FILE $navigation; 1512 &print_footer; 1513 close(FILE); 1514 } else { 1515 warn "$ERROR Can't write to $docu_doc: $!\n"; 1516 } 1517 } 1518 } else { # not split 1519 if (open(FILE, "> $docu_doc")) { 1520 print "# creating $docu_doc...\n" if $verbose; 1521 if ($monolithic || !@toc_lines) { 1522 &print_toplevel_header($title); 1523 } else { 1524 &print_header($title); 1525 print FILE $full_title; 1526 } 1527 if ($monolithic && @toc_lines) { 1528 &print_ruler; 1529 print FILE "<H1>Table of Contents</H1>\n"; 1530 &print(*toc_lines, FILE); 1531 } 1532 &print_ruler; 1533 &print(*doc_lines, FILE); 1534 if ($monolithic && @foot_lines) { 1535 &print_ruler; 1536 print FILE "<H1>Footnotes</H1>\n"; 1537 &print(*foot_lines, FILE); 1538 } 1539 if ($monolithic || !@toc_lines) { 1540 &print_toplevel_footer; 1541 } else { 1542 &print_footer; 1543 } 1544 close(FILE); 1545 } else { 1546 warn "$ERROR Can't write to $docu_doc: $!\n"; 1547 } 1548 } 1549 1550 print "# that's all folks\n" if $verbose; 1551 1552 #+++############################################################################ 1553 # # 1554 # Low level functions # 1555 # # 1556 #---############################################################################ 1557 1558 sub update_sec_num { 1559 local($name, $level) = @_; 1560 1561 $level--; # here we start at 0 1562 if ($name =~ /^appendix/) { 1563 # appendix style 1564 if (@appendix_sec_num) { 1565 &incr_sec_num($level, @appendix_sec_num); 1566 } else { 1567 @appendix_sec_num = ('A', 0, 0, 0); 1568 } 1569 return(join('.', @appendix_sec_num[0..$level])); 1570 } else { 1571 # normal style 1572 if (@normal_sec_num) { 1573 &incr_sec_num($level, @normal_sec_num); 1574 } else { 1575 @normal_sec_num = (1, 0, 0, 0); 1576 } 1577 return(join('.', @normal_sec_num[0..$level])); 1578 } 1579 } 1580 1581 sub incr_sec_num { 1582 local($level, $l); 1583 $level = shift(@_); 1584 $_[$level]++; 1585 foreach $l ($level+1 .. 3) { 1586 $_[$l] = 0; 1587 } 1588 } 1589 1590 sub check { 1591 local($_, %seen, %context, $before, $match, $after); 1592 1593 while (<>) { 1594 if (/\@(\*|\.|\:|\@|\{|\})/) { 1595 $seen{$&}++; 1596 $context{$&} .= "> $_" if $verbose; 1597 $_ = "$`XX$'"; 1598 redo; 1599 } 1600 if (/\@(\w+)/) { 1601 ($before, $match, $after) = ($`, $&, $'); 1602 if ($before =~ /\b[\w-]+$/ && $after =~ /^[\w-.]*\b/) { # e-mail address 1603 $seen{'e-mail address'}++; 1604 $context{'e-mail address'} .= "> $_" if $verbose; 1605 } else { 1606 $seen{$match}++; 1607 $context{$match} .= "> $_" if $verbose; 1608 } 1609 $match =~ s/^\@/X/; 1610 $_ = "$before$match$after"; 1611 redo; 1612 } 1613 } 1614 1615 foreach (sort(keys(%seen))) { 1616 if ($verbose) { 1617 print "$_\n"; 1618 print $context{$_}; 1619 } else { 1620 print "$_ ($seen{$_})\n"; 1621 } 1622 } 1623 } 1624 1625 sub open { 1626 local($name) = @_; 1627 1628 ++$fh_name; 1629 if (open($fh_name, $name)) { 1630 unshift(@fhs, $fh_name); 1631 } else { 1632 warn "$ERROR Can't read file $name: $!\n"; 1633 } 1634 } 1635 1636 sub init_input { 1637 @fhs = (); # hold the file handles to read 1638 @input_spool = (); # spooled lines to read 1639 $fh_name = 'FH000'; 1640 &open($docu); 1641 } 1642 1643 sub next_line { 1644 local($fh, $line); 1645 1646 if (@input_spool) { 1647 $line = shift(@input_spool); 1648 return($line); 1649 } 1650 while (@fhs) { 1651 $fh = $fhs[0]; 1652 $line = <$fh>; 1653 return($line) if $line; 1654 close($fh); 1655 shift(@fhs); 1656 } 1657 return(undef); 1658 } 1659 1660 # used in pass 1, use &next_line 1661 sub skip_until { 1662 local($tag) = @_; 1663 local($_); 1664 1665 while ($_ = &next_line) { 1666 return if /^\@end\s+$tag\s*$/; 1667 } 1668 die "* Failed to find '$tag' after: " . $lines[$#lines]; 1669 } 1670 1671 # 1672 # HTML stacking to have a better HTML output 1673 # 1674 1675 sub html_reset { 1676 @html_stack = ('html'); 1677 $html_element = 'body'; 1678 } 1679 1680 sub html_push { 1681 local($what) = @_; 1682 push(@html_stack, $html_element); 1683 $html_element = $what; 1684 } 1685 1686 sub html_push_if { 1687 local($what) = @_; 1688 push(@html_stack, $html_element) 1689 if ($html_element && $html_element ne 'P'); 1690 $html_element = $what; 1691 } 1692 1693 sub html_pop { 1694 $html_element = pop(@html_stack); 1695 } 1696 1697 sub html_pop_if { 1698 local($elt); 1699 1700 if (@_) { 1701 foreach $elt (@_) { 1702 if ($elt eq $html_element) { 1703 $html_element = pop(@html_stack) if @html_stack; 1704 last; 1705 } 1706 } 1707 } else { 1708 $html_element = pop(@html_stack) if @html_stack; 1709 } 1710 } 1711 1712 sub html_debug { 1713 local($what, $line) = @_; 1714 return("<!-- $line @html_stack, $html_element -->$what") 1715 if $debug & $DEBUG_HTML; 1716 return($what); 1717 } 1718 1719 # to debug the output... 1720 sub debug { 1721 local($what, $line) = @_; 1722 return("<!-- $line -->$what") 1723 if $debug & $DEBUG_HTML; 1724 return($what); 1725 } 1726 1727 sub normalise_node { 1728 $_[0] =~ s/\s+/ /g; 1729 $_[0] =~ s/ $//; 1730 $_[0] =~ s/^ //; 1731 } 1732 1733 sub menu_entry { 1734 local($entry, $node, $descr) = @_; 1735 local($href); 1736 1737 &normalise_node($node); 1738 $href = $node2href{$node}; 1739 if ($href) { 1740 $descr =~ s/^\s+//; 1741 $descr = ": $descr" if $descr; 1742 push(@lines2, "<LI>" . &anchor('', $href, $entry) . "$descr\n"); 1743 } else { 1744 warn "$ERROR Undefined node ($node): $_"; 1745 } 1746 } 1747 1748 sub do_ctrl { "^$_[0]" } 1749 1750 sub do_email { 1751 local($addr, $text) = split(/,\s*/, $_[0]); 1752 1753 $text = $addr unless $text; 1754 &anchor('', "mailto:$addr", $text); 1755 } 1756 1757 sub do_sc { "\U$_[0]\E" } 1758 1759 sub do_uref { 1760 local($url, $text) = split(/,\s*/, $_[0]); 1761 1762 $text = $url unless $text; 1763 &anchor('', $url, $text); 1764 } 1765 1766 sub do_url { &anchor('', $_[0], $_[0]) } 1767 1768 sub do_diaeresis { return "&$_[0]uml;"; } 1769 sub do_acuteaccent { return "&$_[0]acute;"; } 1770 sub do_graveaccent { return "&$_[0]grave;"; } 1771 sub do_tildeaccent { return "&$_[0]tilde;"; } 1772 sub do_cedilla { return "&$_[0]cedil;"; } 1773 sub do_circumflex { return "&$_[0]circ;"; } 1774 1775 sub apply_style { 1776 local($texi_style, $text) = @_; 1777 local($style); 1778 1779 $style = $style_map{$texi_style}; 1780 if (defined($style)) { # known style 1781 if ($style =~ /^\"/) { # add quotes 1782 $style = $'; 1783 $text = "\‘$text\’"; 1784 } 1785 if ($style =~ /^\&/) { # custom 1786 $style = $'; 1787 $text = &$style($text); 1788 } elsif ($style) { # good style 1789 $text = "<$style>$text</$style>"; 1790 } else { # no style 1791 } 1792 } else { # unknown style 1793 $text = undef; 1794 } 1795 return($text); 1796 } 1797 1798 # remove Texinfo styles 1799 sub remove_style { 1800 local($_) = @_; 1801 s/\@\w+{([^\{\}]+)}/$1/g; 1802 return($_); 1803 } 1804 1805 sub substitute_style { 1806 local($_) = @_; 1807 local($changed, $done, $style, $text); 1808 1809 $changed = 1; 1810 while ($changed) { 1811 $changed = 0; 1812 $done = ''; 1813 while (/\@(\w+|"|\~|,|\^){([^\{\}]+)}/) { 1814 $text = &apply_style($1, $2); 1815 if ($text) { 1816 $_ = "$`$text$'"; 1817 $changed = 1; 1818 } else { 1819 $done .= "$`\@$1"; 1820 $_ = "{$2}$'"; 1821 } 1822 } 1823 $_ = $done . $_; 1824 } 1825 return($_); 1826 } 1827 1828 sub anchor { 1829 local($name, $href, $text, $newline) = @_; 1830 local($result); 1831 1832 $result = "<A"; 1833 $result .= " NAME=\"$name\"" if $name; 1834 $result .= " HREF=\"$href\"" if $href; 1835 $result .= ">$text</A>"; 1836 $result .= "\n" if $newline; 1837 return($result); 1838 } 1839 1840 sub pretty_date { 1841 local(@MoY, $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst); 1842 1843 @MoY = ('January', 'Febuary', 'March', 'April', 'May', 'June', 1844 'July', 'August', 'September', 'October', 'November', 'December'); 1845 ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time); 1846 $year += ($year < 70) ? 2000 : 1900; 1847 return("$mday $MoY[$mon] $year"); 1848 } 1849 1850 sub doc_name { 1851 local($num) = @_; 1852 1853 return("${docu_name}_$num.html"); 1854 } 1855 1856 sub next_doc { 1857 $docu_doc = &doc_name(++$doc_num); 1858 } 1859 1860 sub print { 1861 local(*lines, $fh) = @_; 1862 local($_); 1863 1864 while (@lines) { 1865 $_ = shift(@lines); 1866 if (/^$PROTECTTAG/o) { 1867 $_ = $tag2pro{$_}; 1868 } else { 1869 &unprotect_texi; 1870 } 1871 print $fh $_; 1872 } 1873 } 1874 1875 sub print_ruler { 1876 print FILE "<P><HR><P>\n"; 1877 } 1878 1879 sub print_header { 1880 local($_); 1881 1882 # clean the title 1883 $_ = &remove_style($_[0]); 1884 &unprotect_texi; 1885 # print the header 1886 if ($doctype eq 'html2') { 1887 print FILE $html2_doctype; 1888 } elsif ($doctype) { 1889 print FILE $doctype; 1890 } 1891 print FILE <<EOT; 1892 <HTML> 1893 <HEAD> 1894 $header 1895 <META HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"> 1896 <TITLE>$_</TITLE> 1897 </HEAD> 1898 <BODY> 1899 EOT 1900 } 1901 1902 sub print_toplevel_header { 1903 local($_); 1904 1905 &print_header; # pass given arg... 1906 print FILE $full_title; 1907 if ($value{'_subtitle'}) { 1908 $value{'_subtitle'} =~ s/\n+$//; 1909 foreach (split(/\n/, $value{'_subtitle'})) { 1910 $_ = &substitute_style($_); 1911 &unprotect_texi; 1912 print FILE "<H2>$_</H2>\n"; 1913 } 1914 } 1915 if ($value{'_author'}) { 1916 $value{'_author'} =~ s/\n+$//; 1917 foreach (split(/\n/, $value{'_author'})) { 1918 $_ = &substitute_style($_); 1919 &unprotect_texi; 1920 s/[\w.-]+\@[\w.-]+/<A HREF="mailto:$&">$&<\/A>/g; 1921 print FILE "<ADDRESS>$_</ADDRESS>\n"; 1922 } 1923 } 1924 print FILE "<P>\n"; 1925 } 1926 1927 sub print_footer { 1928 print FILE <<EOT; 1929 </BODY> 1930 </HTML> 1931 EOT 1932 } 1933 1934 sub print_toplevel_footer { 1935 &print_ruler; 1936 print FILE <<EOT; 1937 This document was generated on $TODAY using the 1938 <A HREF=\"$HOMEPAGE\">texi2html</A> 1939 translator version 1.52b.</P> 1940 EOT 1941 &print_footer; 1942 } 1943 1944 sub protect_texi { 1945 # protect @ { } ` ' 1946 s/\@\@/$;0/go; 1947 s/\@\{/$;1/go; 1948 s/\@\}/$;2/go; 1949 s/\@\`/$;3/go; 1950 s/\@\'/$;4/go; 1951 } 1952 1953 sub protect_html { 1954 local($what) = @_; 1955 # protect & < > 1956 $what =~ s/\&/\&\#38;/g; 1957 $what =~ s/\</\&\#60;/g; 1958 $what =~ s/\>/\&\#62;/g; 1959 # but recognize some HTML things 1960 $what =~ s/\&\#60;\/A\&\#62;/<\/A>/g; # </A> 1961 $what =~ s/\&\#60;A ([^\&]+)\&\#62;/<A $1>/g; # <A [^&]+> 1962 $what =~ s/\&\#60;IMG ([^\&]+)\&\#62;/<IMG $1>/g; # <IMG [^&]+> 1963 return($what); 1964 } 1965 1966 sub unprotect_texi { 1967 s/$;0/\@/go; 1968 s/$;1/\{/go; 1969 s/$;2/\}/go; 1970 s/$;3/\`/go; 1971 s/$;4/\'/go; 1972 } 1973 1974 sub unprotect_html { 1975 local($what) = @_; 1976 $what =~ s/\&\#38;/\&/g; 1977 $what =~ s/\&\#60;/\</g; 1978 $what =~ s/\&\#62;/\>/g; 1979 return($what); 1980 } 1981 1982 sub byalpha { 1983 $key2alpha{$a} cmp $key2alpha{$b}; 1984 } 1985 1986 ############################################################################## 1987 1988 # These next few lines are legal in both Perl and nroff. 1989 1990 .00 ; # finish .ig 1991 1992 'di \" finish diversion--previous line must be blank 1993 .nr nl 0-1 \" fake up transition to first page again 1994 .nr % 0 \" start at page 1 1995 '; __END__ ############# From here on it's a standard manual page ############ 1996 .TH TEXI2HTML 1 "01/05/98" 1997 .AT 3 1998 .SH NAME 1999 texi2html \- a Texinfo to HTML converter 2000 .SH SYNOPSIS 2001 .B texi2html [options] file 2002 .PP 2003 .B texi2html -check [-verbose] files 2004 .SH DESCRIPTION 2005 .I Texi2html 2006 converts the given Texinfo file to a set of HTML files. It tries to handle 2007 most of the Texinfo commands. It creates hypertext links for cross-references, 2008 footnotes... 2009 .PP 2010 It also tries to add links from a reference to its corresponding entry in the 2011 bibliography (if any). It may also handle a glossary (see the 2012 .B \-glossary 2013 option). 2014 .PP 2015 .I Texi2html 2016 creates several files depending on the contents of the Texinfo file and on 2017 the chosen options (see FILES). 2018 .PP 2019 The HTML files created by 2020 .I texi2html 2021 are closer to TeX than to Info, that's why 2022 .I texi2html 2023 converts @ifhtml sections and not @ifinfo or @iftex ones by default. You can 2024 change this with the \-expandinfo or \-expandtex options. 2025 .SH OPTIONS 2026 .TP 12 2027 .B \-check 2028 Check the given file and give the list of all things that may be Texinfo commands. 2029 This may be used to check the output of 2030 .I texi2html 2031 to find the Texinfo commands that have been left in the HTML file. 2032 .TP 2033 .B \-expandinfo 2034 Expand @ifinfo sections, not @ifhtml ones. 2035 .TP 2036 .B \-expandtex 2037 Expand @iftex sections, not @ifhtml ones. 2038 .TP 2039 .B \-glossary 2040 Use the section named 'Glossary' to build a list of terms and put links in the HTML 2041 document from each term toward its definition. 2042 .TP 2043 .B \-invisible \fIname\fP 2044 Use \fIname\fP to create invisible destination anchors for index links 2045 (you can for instance use the invisible.xbm file shipped with this program). 2046 This is a workaround for a known bug of many WWW browsers, including netscape. 2047 .TP 2048 .B \-I \fIdir\fP 2049 Look also in \fIdir\fP to find included files. 2050 .TP 2051 .B \-menu 2052 Show the Texinfo menus; by default they are ignored. 2053 .TP 2054 .B \-monolithic 2055 Output only one file, including the table of contents and footnotes. 2056 .TP 2057 .B \-number 2058 Number the sections. 2059 .TP 2060 .B \-split_chapter 2061 Split the output into several HTML files (one per main section: 2062 chapter, appendix...). 2063 .TP 2064 .B \-split_node 2065 Split the output into several HTML files (one per node). 2066 .TP 2067 .B \-usage 2068 Print usage instructions, listing the current available command-line options. 2069 .TP 2070 .B \-verbose 2071 Give a verbose output. Can be used with the 2072 .B \-check 2073 option. 2074 .PP 2075 .SH FILES 2076 By default 2077 .I texi2html 2078 creates the following files (foo being the name of the Texinfo file): 2079 .TP 16 2080 .B foo_toc.html 2081 The table of contents. 2082 .TP 2083 .B foo.html 2084 The document's contents. 2085 .TP 2086 .B foo_foot.html 2087 The footnotes (if any). 2088 .PP 2089 When used with the 2090 .B \-split 2091 option, it creates several files (one per chapter or node), named 2092 .B foo_n.html 2093 (n being the indice of the chapter or node), instead of the single 2094 .B foo.html 2095 file. 2096 .PP 2097 When used with the 2098 .B \-monolithic 2099 option, it creates only one file: 2100 .B foo.html 2101 .SH VARIABLES 2102 .I texi2html 2103 predefines the following variables: \fBhtml\fP, \fBtexi2html\fP. 2104 .SH ADDITIONAL COMMANDS 2105 .I texi2html 2106 implements the following non-Texinfo commands (maybe they are in Texinfo now...): 2107 .TP 16 2108 .B @ifhtml 2109 This indicates the start of an HTML section, this section will passed through 2110 without any modification. 2111 .TP 2112 .B @end ifhtml 2113 This indicates the end of an HTML section. 2114 .SH VERSION 2115 This is \fItexi2html\fP version 1.52b, 01/05/98. 2116 .PP 2117 The latest version of \fItexi2html\fP can be found in WWW, cf. URL 2118 http://wwwinfo.cern.ch/dis/texi2html/ 2119 .SH AUTHOR 2120 The main author is Lionel Cons, CERN IT/DIS/OSE, Lionel.Cons (at] cern.ch. 2121 Many other people around the net contributed to this program. 2122 .SH COPYRIGHT 2123 This program is the intellectual property of the European 2124 Laboratory for Particle Physics (known as CERN). No guarantee whatsoever is 2125 provided by CERN. No liability whatsoever is accepted for any loss or damage 2126 of any kind resulting from any defect or inaccuracy in this information or 2127 code. 2128 .PP 2129 CERN, 1211 Geneva 23, Switzerland 2130 .SH "SEE ALSO" 2131 GNU Texinfo Documentation Format, 2132 HyperText Markup Language (HTML), 2133 World Wide Web (WWW). 2134 .SH BUGS 2135 This program does not understand all Texinfo commands (yet). 2136 .ex 2137