[BACK]Return to texi2html CVS log [TXT][DIR] Up to [local] / OpenXM / src / asir-doc

Annotation of OpenXM/src/asir-doc/texi2html, Revision 1.2

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>