texi2html
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:58k
源码类别:

MySQL数据库

开发平台:

Visual C++

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