163eb84d1Schristos#!/usr/local/bin/perl 263eb84d1Schristos'di '; 363eb84d1Schristos'ig 00 '; 463eb84d1Schristos#+############################################################################## 563eb84d1Schristos# # 663eb84d1Schristos# File: texi2html # 763eb84d1Schristos# # 863eb84d1Schristos# Description: Program to transform most Texinfo documents to HTML # 963eb84d1Schristos# # 1063eb84d1Schristos#-############################################################################## 1163eb84d1Schristos 1263eb84d1Schristos# @(#)texi2html 1.52b 01/05/98 Written (mainly) by Lionel Cons, Lionel.Cons@cern.ch 1363eb84d1Schristos# 1.52a: Use acute accent instead of apostrophe. Add support for ISO-8859-1 1463eb84d1Schristos# characters with cedilla, circumflex etc. 1563eb84d1Schristos# 1.52b: Add option -expandtex. Expand @ifhtml by default, not @ifinfo. 1663eb84d1Schristos# Use Unicode quotation marks instead of grave and acute accents. 1763eb84d1Schristos# Emit charset=UTF-8 declaration. 1863eb84d1Schristos 1963eb84d1Schristos# The man page for this program is included at the end of this file and can be 2063eb84d1Schristos# viewed using the command 'nroff -man texi2html'. 2163eb84d1Schristos# Please read the copyright at the end of the man page. 2263eb84d1Schristos 2363eb84d1Schristos#+++############################################################################ 2463eb84d1Schristos# # 2563eb84d1Schristos# Constants # 2663eb84d1Schristos# # 2763eb84d1Schristos#---############################################################################ 2863eb84d1Schristos 2963eb84d1Schristos$DEBUG_TOC = 1; 3063eb84d1Schristos$DEBUG_INDEX = 2; 3163eb84d1Schristos$DEBUG_BIB = 4; 3263eb84d1Schristos$DEBUG_GLOSS = 8; 3363eb84d1Schristos$DEBUG_DEF = 16; 3463eb84d1Schristos$DEBUG_HTML = 32; 3563eb84d1Schristos$DEBUG_USER = 64; 3663eb84d1Schristos 3763eb84d1Schristos$BIBRE = '\[[\w\/-]+\]'; # RE for a bibliography reference 3863eb84d1Schristos$FILERE = '[\/\w.+-]+'; # RE for a file name 3963eb84d1Schristos$VARRE = '[^\s\{\}]+'; # RE for a variable name 4063eb84d1Schristos$NODERE = '[^@{}:\'`",]+'; # RE for a node name 4163eb84d1Schristos$NODESRE = '[^@{}:\'`"]+'; # RE for a list of node names 4263eb84d1Schristos$XREFRE = '[^@{}]+'; # RE for a xref (should use NODERE) 4363eb84d1Schristos 4463eb84d1Schristos$ERROR = "***"; # prefix for errors and warnings 4563eb84d1Schristos$THISPROG = "texi2html 1.52b"; # program name and version 4663eb84d1Schristos$HOMEPAGE = "http://wwwinfo.cern.ch/dis/texi2html/"; # program home page 4763eb84d1Schristos$TODAY = &pretty_date; # like "20 September 1993" 4863eb84d1Schristos$SPLITTAG = "<!-- SPLIT HERE -->\n"; # tag to know where to split 4963eb84d1Schristos$PROTECTTAG = "_ThisIsProtected_"; # tag to recognize protected sections 5063eb84d1Schristos$html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//EN">'; 5163eb84d1Schristos 5263eb84d1Schristos# 5363eb84d1Schristos# language dependent constants 5463eb84d1Schristos# 5563eb84d1Schristos#$LDC_SEE = 'see'; 5663eb84d1Schristos#$LDC_SECTION = 'section'; 5763eb84d1Schristos#$LDC_IN = 'in'; 5863eb84d1Schristos#$LDC_TOC = 'Table of Contents'; 5963eb84d1Schristos#$LDC_GOTO = 'Go to the'; 6063eb84d1Schristos#$LDC_FOOT = 'Footnotes'; 6163eb84d1Schristos# TODO: @def* shortcuts 6263eb84d1Schristos 6363eb84d1Schristos# 6463eb84d1Schristos# pre-defined indices 6563eb84d1Schristos# 6663eb84d1Schristos%predefined_index = ( 6763eb84d1Schristos 'cp', 'c', 6863eb84d1Schristos 'fn', 'f', 6963eb84d1Schristos 'vr', 'v', 7063eb84d1Schristos 'ky', 'k', 7163eb84d1Schristos 'pg', 'p', 7263eb84d1Schristos 'tp', 't', 7363eb84d1Schristos ); 7463eb84d1Schristos 7563eb84d1Schristos# 7663eb84d1Schristos# valid indices 7763eb84d1Schristos# 7863eb84d1Schristos%valid_index = ( 7963eb84d1Schristos 'c', 1, 8063eb84d1Schristos 'f', 1, 8163eb84d1Schristos 'v', 1, 8263eb84d1Schristos 'k', 1, 8363eb84d1Schristos 'p', 1, 8463eb84d1Schristos 't', 1, 8563eb84d1Schristos ); 8663eb84d1Schristos 8763eb84d1Schristos# 8863eb84d1Schristos# texinfo section names to level 8963eb84d1Schristos# 9063eb84d1Schristos%sec2level = ( 9163eb84d1Schristos 'top', 0, 9263eb84d1Schristos 'chapter', 1, 9363eb84d1Schristos 'unnumbered', 1, 9463eb84d1Schristos 'majorheading', 1, 9563eb84d1Schristos 'chapheading', 1, 9663eb84d1Schristos 'appendix', 1, 9763eb84d1Schristos 'section', 2, 9863eb84d1Schristos 'unnumberedsec', 2, 9963eb84d1Schristos 'heading', 2, 10063eb84d1Schristos 'appendixsec', 2, 10163eb84d1Schristos 'appendixsection', 2, 10263eb84d1Schristos 'subsection', 3, 10363eb84d1Schristos 'unnumberedsubsec', 3, 10463eb84d1Schristos 'subheading', 3, 10563eb84d1Schristos 'appendixsubsec', 3, 10663eb84d1Schristos 'subsubsection', 4, 10763eb84d1Schristos 'unnumberedsubsubsec', 4, 10863eb84d1Schristos 'subsubheading', 4, 10963eb84d1Schristos 'appendixsubsubsec', 4, 11063eb84d1Schristos ); 11163eb84d1Schristos 11263eb84d1Schristos# 11363eb84d1Schristos# accent map, TeX command to ISO name 11463eb84d1Schristos# 11563eb84d1Schristos%accent_map = ( 11663eb84d1Schristos '"', 'uml', 11763eb84d1Schristos '~', 'tilde', 11863eb84d1Schristos '^', 'circ', 11963eb84d1Schristos '`', 'grave', 12063eb84d1Schristos '\'', 'acute', 12163eb84d1Schristos ); 12263eb84d1Schristos 12363eb84d1Schristos# 12463eb84d1Schristos# texinfo "simple things" (@foo) to HTML ones 12563eb84d1Schristos# 12663eb84d1Schristos%simple_map = ( 12763eb84d1Schristos # cf. makeinfo.c 12863eb84d1Schristos "*", "<BR>", # HTML+ 12963eb84d1Schristos " ", " ", 13063eb84d1Schristos "\n", "\n", 13163eb84d1Schristos "|", "", 13263eb84d1Schristos # spacing commands 13363eb84d1Schristos ":", "", 13463eb84d1Schristos "!", "!", 13563eb84d1Schristos "?", "?", 13663eb84d1Schristos ".", ".", 13763eb84d1Schristos "-", "", 13863eb84d1Schristos ); 13963eb84d1Schristos 14063eb84d1Schristos# 14163eb84d1Schristos# texinfo "things" (@foo{}) to HTML ones 14263eb84d1Schristos# 14363eb84d1Schristos%things_map = ( 14463eb84d1Schristos 'TeX', 'TeX', 14563eb84d1Schristos 'br', '<P>', # paragraph break 14663eb84d1Schristos 'bullet', '*', 14763eb84d1Schristos 'copyright', '(C)', 14863eb84d1Schristos 'dots', '...', 14963eb84d1Schristos 'equiv', '==', 15063eb84d1Schristos 'error', 'error-->', 15163eb84d1Schristos 'expansion', '==>', 15263eb84d1Schristos 'minus', '-', 15363eb84d1Schristos 'point', '-!-', 15463eb84d1Schristos 'print', '-|', 15563eb84d1Schristos 'result', '=>', 15663eb84d1Schristos 'today', $TODAY, 15763eb84d1Schristos 'aa', 'å', 15863eb84d1Schristos 'AA', 'Å', 15963eb84d1Schristos 'ae', 'æ', 16063eb84d1Schristos 'AE', 'Æ', 16163eb84d1Schristos 'o', 'ø', 16263eb84d1Schristos 'O', 'Ø', 16363eb84d1Schristos 'ss', 'ß', 16463eb84d1Schristos 'exclamdown', '¡', 16563eb84d1Schristos 'questiondown', '¿', 16663eb84d1Schristos 'pounds', '£' 16763eb84d1Schristos ); 16863eb84d1Schristos 16963eb84d1Schristos# 17063eb84d1Schristos# texinfo styles (@foo{bar}) to HTML ones 17163eb84d1Schristos# 17263eb84d1Schristos%style_map = ( 17363eb84d1Schristos 'asis', '', 17463eb84d1Schristos 'b', 'B', 17563eb84d1Schristos 'cite', 'CITE', 17663eb84d1Schristos 'code', 'CODE', 17763eb84d1Schristos 'ctrl', '&do_ctrl', # special case 17863eb84d1Schristos 'dfn', 'EM', # DFN tag is illegal in the standard 17963eb84d1Schristos 'dmn', '', # useless 18063eb84d1Schristos 'email', '&do_email', # insert a clickable email address 18163eb84d1Schristos 'emph', 'EM', 18263eb84d1Schristos 'file', '"TT', # will put quotes, cf. &apply_style 18363eb84d1Schristos 'i', 'I', 18463eb84d1Schristos 'kbd', 'KBD', 18563eb84d1Schristos 'key', 'KBD', 18663eb84d1Schristos 'math', 'EM', 18763eb84d1Schristos 'r', '', # unsupported 18863eb84d1Schristos 'samp', '"SAMP', # will put quotes, cf. &apply_style 18963eb84d1Schristos 'sc', '&do_sc', # special case 19063eb84d1Schristos 'strong', 'STRONG', 19163eb84d1Schristos 't', 'TT', 19263eb84d1Schristos 'titlefont', '', # useless 19363eb84d1Schristos 'uref', '&do_uref', # insert a clickable URL 19463eb84d1Schristos 'url', '&do_url', # insert a clickable URL 19563eb84d1Schristos 'var', 'VAR', 19663eb84d1Schristos 'w', '', # unsupported 19763eb84d1Schristos '"', '&do_diaeresis', 19863eb84d1Schristos '\'', '&do_acuteaccent', # doesn't work?? 19963eb84d1Schristos '\`', '&do_graveaccent', # doesn't work?? 20063eb84d1Schristos '~', '&do_tildeaccent', 20163eb84d1Schristos ',', '&do_cedilla', 20263eb84d1Schristos '^', '&do_circumflex', 20363eb84d1Schristos ); 20463eb84d1Schristos 20563eb84d1Schristos# 20663eb84d1Schristos# texinfo format (@foo/@end foo) to HTML ones 20763eb84d1Schristos# 20863eb84d1Schristos%format_map = ( 20963eb84d1Schristos 'display', 'PRE', 21063eb84d1Schristos 'example', 'PRE', 21163eb84d1Schristos 'format', 'PRE', 21263eb84d1Schristos 'lisp', 'PRE', 21363eb84d1Schristos 'quotation', 'BLOCKQUOTE', 21463eb84d1Schristos 'smallexample', 'PRE', 21563eb84d1Schristos 'smalllisp', 'PRE', 21663eb84d1Schristos # lists 21763eb84d1Schristos 'itemize', 'UL', 21863eb84d1Schristos 'enumerate', 'OL', 21963eb84d1Schristos # poorly supported 22063eb84d1Schristos 'flushleft', 'PRE', 22163eb84d1Schristos 'flushright', 'PRE', 22263eb84d1Schristos ); 22363eb84d1Schristos 22463eb84d1Schristos# 22563eb84d1Schristos# texinfo definition shortcuts to real ones 22663eb84d1Schristos# 22763eb84d1Schristos%def_map = ( 22863eb84d1Schristos # basic commands 22963eb84d1Schristos 'deffn', 0, 23063eb84d1Schristos 'defvr', 0, 23163eb84d1Schristos 'deftypefn', 0, 23263eb84d1Schristos 'deftypevr', 0, 23363eb84d1Schristos 'defcv', 0, 23463eb84d1Schristos 'defop', 0, 23563eb84d1Schristos 'deftp', 0, 23663eb84d1Schristos # basic x commands 23763eb84d1Schristos 'deffnx', 0, 23863eb84d1Schristos 'defvrx', 0, 23963eb84d1Schristos 'deftypefnx', 0, 24063eb84d1Schristos 'deftypevrx', 0, 24163eb84d1Schristos 'defcvx', 0, 24263eb84d1Schristos 'defopx', 0, 24363eb84d1Schristos 'deftpx', 0, 24463eb84d1Schristos # shortcuts 24563eb84d1Schristos 'defun', 'deffn Function', 24663eb84d1Schristos 'defmac', 'deffn Macro', 24763eb84d1Schristos 'defspec', 'deffn {Special Form}', 24863eb84d1Schristos 'defvar', 'defvr Variable', 24963eb84d1Schristos 'defopt', 'defvr {User Option}', 25063eb84d1Schristos 'deftypefun', 'deftypefn Function', 25163eb84d1Schristos 'deftypevar', 'deftypevr Variable', 25263eb84d1Schristos 'defivar', 'defcv {Instance Variable}', 25363eb84d1Schristos 'defmethod', 'defop Method', 25463eb84d1Schristos # x shortcuts 25563eb84d1Schristos 'defunx', 'deffnx Function', 25663eb84d1Schristos 'defmacx', 'deffnx Macro', 25763eb84d1Schristos 'defspecx', 'deffnx {Special Form}', 25863eb84d1Schristos 'defvarx', 'defvrx Variable', 25963eb84d1Schristos 'defoptx', 'defvrx {User Option}', 26063eb84d1Schristos 'deftypefunx', 'deftypefnx Function', 26163eb84d1Schristos 'deftypevarx', 'deftypevrx Variable', 26263eb84d1Schristos 'defivarx', 'defcvx {Instance Variable}', 26363eb84d1Schristos 'defmethodx', 'defopx Method', 26463eb84d1Schristos ); 26563eb84d1Schristos 26663eb84d1Schristos# 26763eb84d1Schristos# things to skip 26863eb84d1Schristos# 26963eb84d1Schristos%to_skip = ( 27063eb84d1Schristos # comments 27163eb84d1Schristos 'c', 1, 27263eb84d1Schristos 'comment', 1, 27363eb84d1Schristos # useless 27463eb84d1Schristos 'contents', 1, 27563eb84d1Schristos 'shortcontents', 1, 27663eb84d1Schristos 'summarycontents', 1, 27763eb84d1Schristos 'footnotestyle', 1, 27863eb84d1Schristos 'end ifclear', 1, 27963eb84d1Schristos 'end ifset', 1, 28063eb84d1Schristos 'titlepage', 1, 28163eb84d1Schristos 'end titlepage', 1, 28263eb84d1Schristos # unsupported commands (formatting) 28363eb84d1Schristos 'afourpaper', 1, 28463eb84d1Schristos 'cropmarks', 1, 28563eb84d1Schristos 'finalout', 1, 28663eb84d1Schristos 'headings', 1, 28763eb84d1Schristos 'need', 1, 28863eb84d1Schristos 'page', 1, 28963eb84d1Schristos 'setchapternewpage', 1, 29063eb84d1Schristos 'everyheading', 1, 29163eb84d1Schristos 'everyfooting', 1, 29263eb84d1Schristos 'evenheading', 1, 29363eb84d1Schristos 'evenfooting', 1, 29463eb84d1Schristos 'oddheading', 1, 29563eb84d1Schristos 'oddfooting', 1, 29663eb84d1Schristos 'smallbook', 1, 29763eb84d1Schristos 'vskip', 1, 29863eb84d1Schristos 'filbreak', 1, 29963eb84d1Schristos 'paragraphindent', 1, 30063eb84d1Schristos # unsupported formats 30163eb84d1Schristos 'cartouche', 1, 30263eb84d1Schristos 'end cartouche', 1, 30363eb84d1Schristos 'group', 1, 30463eb84d1Schristos 'end group', 1, 30563eb84d1Schristos ); 30663eb84d1Schristos 30763eb84d1Schristos#+++############################################################################ 30863eb84d1Schristos# # 30963eb84d1Schristos# Argument parsing, initialisation # 31063eb84d1Schristos# # 31163eb84d1Schristos#---############################################################################ 31263eb84d1Schristos 31363eb84d1Schristos%value = (); # hold texinfo variables, see also -D 31463eb84d1Schristos 31563eb84d1Schristos$use_bibliography = 1; 31663eb84d1Schristos$use_acc = 0; 31763eb84d1Schristos$debug = 0; 31863eb84d1Schristos$doctype = ''; 31963eb84d1Schristos$check = 0; 32063eb84d1Schristos$expandinfo = 0; 32163eb84d1Schristos$expandtex = 0; 32263eb84d1Schristos$use_glossary = 0; 32363eb84d1Schristos$invisible_mark = ''; 32463eb84d1Schristos$use_iso = 0; 32563eb84d1Schristos@include_dirs = (); 32663eb84d1Schristos$show_menu = 0; 32763eb84d1Schristos$number_sections = 0; 32863eb84d1Schristos$split_node = 0; 32963eb84d1Schristos$split_chapter = 0; 33063eb84d1Schristos$monolithic = 0; 33163eb84d1Schristos$verbose = 0; 33263eb84d1Schristos$usage = <<EOT; 33363eb84d1SchristosThis is $THISPROG 33463eb84d1SchristosTo convert a Texinfo file to HMTL: $0 [options] file 33563eb84d1Schristos where options can be: 33663eb84d1Schristos -expandinfo : use \@ifinfo sections, not \@ifhtml 33763eb84d1Schristos -expandtex : use \@iftex sections, not \@ifhtml 33863eb84d1Schristos -glossary : handle a glossary 33963eb84d1Schristos -invisible name: use 'name' as an invisible anchor 34063eb84d1Schristos -Dname : define name like with \@set 34163eb84d1Schristos -I dir : search also for files in 'dir' 34263eb84d1Schristos -menu : handle menus 34363eb84d1Schristos -monolithic : output only one file including ToC 34463eb84d1Schristos -number : number sections 34563eb84d1Schristos -split_chapter : split on main sections 34663eb84d1Schristos -split_node : split on nodes 34763eb84d1Schristos -usage : print usage instructions 34863eb84d1Schristos -verbose : verbose output 34963eb84d1SchristosTo check converted files: $0 -check [-verbose] files 35063eb84d1SchristosEOT 35163eb84d1Schristos 35263eb84d1Schristoswhile (@ARGV && $ARGV[0] =~ /^-/) { 35363eb84d1Schristos $_ = shift(@ARGV); 35463eb84d1Schristos if (/^-acc$/) { $use_acc = 1; next; } 35563eb84d1Schristos if (/^-d(ebug)?(\d+)?$/) { $debug = $2 || shift(@ARGV); next; } 35663eb84d1Schristos if (/^-doctype$/) { $doctype = shift(@ARGV); next; } 35763eb84d1Schristos if (/^-c(heck)?$/) { $check = 1; next; } 35863eb84d1Schristos if (/^-expandi(nfo)?$/) { $expandinfo = 1; next; } 35963eb84d1Schristos if (/^-expandt(ex)?$/) { $expandtex = 1; next; } 36063eb84d1Schristos if (/^-g(lossary)?$/) { $use_glossary = 1; next; } 36163eb84d1Schristos if (/^-i(nvisible)?$/) { $invisible_mark = shift(@ARGV); next; } 36263eb84d1Schristos if (/^-iso$/) { $use_iso = 1; next; } 36363eb84d1Schristos if (/^-D(.+)?$/) { $value{$1 || shift(@ARGV)} = 1; next; } 36463eb84d1Schristos if (/^-I(.+)?$/) { push(@include_dirs, $1 || shift(@ARGV)); next; } 36563eb84d1Schristos if (/^-m(enu)?$/) { $show_menu = 1; next; } 36663eb84d1Schristos if (/^-mono(lithic)?$/) { $monolithic = 1; next; } 36763eb84d1Schristos if (/^-n(umber)?$/) { $number_sections = 1; next; } 36863eb84d1Schristos if (/^-s(plit)?_?(n(ode)?|c(hapter)?)?$/) { 36963eb84d1Schristos if ($2 =~ /^n/) { 37063eb84d1Schristos $split_node = 1; 37163eb84d1Schristos } else { 37263eb84d1Schristos $split_chapter = 1; 37363eb84d1Schristos } 37463eb84d1Schristos next; 37563eb84d1Schristos } 37663eb84d1Schristos if (/^-v(erbose)?$/) { $verbose = 1; next; } 37763eb84d1Schristos die $usage; 37863eb84d1Schristos} 37963eb84d1Schristosif ($check) { 38063eb84d1Schristos die $usage unless @ARGV > 0; 38163eb84d1Schristos ✓ 38263eb84d1Schristos exit; 38363eb84d1Schristos} 38463eb84d1Schristos 38563eb84d1Schristosif (($split_node || $split_chapter) && $monolithic) { 38663eb84d1Schristos warn "Can't use -monolithic with -split, -monolithic ignored.\n"; 38763eb84d1Schristos $monolithic = 0; 38863eb84d1Schristos} 38963eb84d1Schristosif ($expandinfo) { 39063eb84d1Schristos $to_skip{'ifinfo'}++; 39163eb84d1Schristos $to_skip{'end ifinfo'}++; 39263eb84d1Schristos $to_skip{'ifnottex'}++; 39363eb84d1Schristos $to_skip{'end ifnottex'}++; 39463eb84d1Schristos $to_skip{'ifnothtml'}++; 39563eb84d1Schristos $to_skip{'end ifnothtml'}++; 39663eb84d1Schristos} elsif ($expandtex) { 39763eb84d1Schristos $to_skip{'ifnotinfo'}++; 39863eb84d1Schristos $to_skip{'end ifnotinfo'}++; 39963eb84d1Schristos $to_skip{'iftex'}++; 40063eb84d1Schristos $to_skip{'end iftex'}++; 40163eb84d1Schristos $to_skip{'ifnothtml'}++; 40263eb84d1Schristos $to_skip{'end ifnothtml'}++; 40363eb84d1Schristos} else { 40463eb84d1Schristos $to_skip{'ifnotinfo'}++; 40563eb84d1Schristos $to_skip{'end ifnotinfo'}++; 40663eb84d1Schristos $to_skip{'ifnottex'}++; 40763eb84d1Schristos $to_skip{'end ifnottex'}++; 40863eb84d1Schristos $to_skip{'ifhtml'}++; 40963eb84d1Schristos $to_skip{'end ifhtml'}++; 41063eb84d1Schristos} 41163eb84d1Schristos$invisible_mark = '<IMG SRC="invisible.xbm">' if $invisible_mark eq 'xbm'; 41263eb84d1Schristosdie $usage unless @ARGV == 1; 41363eb84d1Schristos$docu = shift(@ARGV); 41463eb84d1Schristosif ($docu =~ /.*\//) { 41563eb84d1Schristos chop($docu_dir = $&); 41663eb84d1Schristos $docu_name = $'; 41763eb84d1Schristos} else { 41863eb84d1Schristos $docu_dir = '.'; 41963eb84d1Schristos $docu_name = $docu; 42063eb84d1Schristos} 42163eb84d1Schristosunshift(@include_dirs, $docu_dir); 42263eb84d1Schristos$docu_name =~ s/\.te?x(i|info)?$//; # basename of the document 42363eb84d1Schristos 42463eb84d1Schristos$docu_doc = "$docu_name.html"; # document's contents 42563eb84d1Schristosif ($monolithic) { 42663eb84d1Schristos $docu_toc = $docu_foot = $docu_doc; 42763eb84d1Schristos} else { 42863eb84d1Schristos $docu_toc = "${docu_name}_toc.html"; # document's table of contents 42963eb84d1Schristos $docu_foot = "${docu_name}_foot.html"; # document's footnotes 43063eb84d1Schristos} 43163eb84d1Schristos 43263eb84d1Schristos# 43363eb84d1Schristos# variables 43463eb84d1Schristos# 43563eb84d1Schristos$value{'html'} = 1; # predefine html (the output format) 43663eb84d1Schristos$value{'texi2html'} = '1.52b'; # predefine texi2html (the translator) 43763eb84d1Schristos# _foo: internal to track @foo 43863eb84d1Schristosforeach ('_author', '_title', '_subtitle', 43963eb84d1Schristos '_settitle', '_setfilename') { 44063eb84d1Schristos $value{$_} = ''; # prevent -w warnings 44163eb84d1Schristos} 44263eb84d1Schristos%node2sec = (); # node to section name 44363eb84d1Schristos%node2href = (); # node to HREF 44463eb84d1Schristos%bib2href = (); # bibliography reference to HREF 44563eb84d1Schristos%gloss2href = (); # glossary term to HREF 44663eb84d1Schristos@sections = (); # list of sections 44763eb84d1Schristos%tag2pro = (); # protected sections 44863eb84d1Schristos 44963eb84d1Schristos# 45063eb84d1Schristos# initial indexes 45163eb84d1Schristos# 45263eb84d1Schristos$bib_num = 0; 45363eb84d1Schristos$foot_num = 0; 45463eb84d1Schristos$gloss_num = 0; 45563eb84d1Schristos$idx_num = 0; 45663eb84d1Schristos$sec_num = 0; 45763eb84d1Schristos$doc_num = 0; 45863eb84d1Schristos$html_num = 0; 45963eb84d1Schristos 46063eb84d1Schristos# 46163eb84d1Schristos# can I use ISO8879 characters? (HTML+) 46263eb84d1Schristos# 46363eb84d1Schristosif ($use_iso) { 46463eb84d1Schristos $things_map{'bullet'} = "•"; 46563eb84d1Schristos $things_map{'copyright'} = "©"; 46663eb84d1Schristos $things_map{'dots'} = "…"; 46763eb84d1Schristos $things_map{'equiv'} = "≡"; 46863eb84d1Schristos $things_map{'expansion'} = "→"; 46963eb84d1Schristos $things_map{'point'} = "∗"; 47063eb84d1Schristos $things_map{'result'} = "⇒"; 47163eb84d1Schristos} 47263eb84d1Schristos 47363eb84d1Schristos# 47463eb84d1Schristos# read texi2html extensions (if any) 47563eb84d1Schristos# 47663eb84d1Schristos$extensions = 'texi2html.ext'; # extensions in working directory 47763eb84d1Schristosif (-f $extensions) { 47863eb84d1Schristos print "# reading extensions from $extensions\n" if $verbose; 47963eb84d1Schristos require($extensions); 48063eb84d1Schristos} 48163eb84d1Schristos($progdir = $0) =~ s/[^\/]+$//; 48263eb84d1Schristosif ($progdir && ($progdir ne './')) { 48363eb84d1Schristos $extensions = "${progdir}texi2html.ext"; # extensions in texi2html directory 48463eb84d1Schristos if (-f $extensions) { 48563eb84d1Schristos print "# reading extensions from $extensions\n" if $verbose; 48663eb84d1Schristos require($extensions); 48763eb84d1Schristos } 48863eb84d1Schristos} 48963eb84d1Schristos 49063eb84d1Schristosprint "# reading from $docu\n" if $verbose; 49163eb84d1Schristos 49263eb84d1Schristos#+++############################################################################ 49363eb84d1Schristos# # 49463eb84d1Schristos# Pass 1: read source, handle command, variable, simple substitution # 49563eb84d1Schristos# # 49663eb84d1Schristos#---############################################################################ 49763eb84d1Schristos 49863eb84d1Schristos@lines = (); # whole document 49963eb84d1Schristos@toc_lines = (); # table of contents 50063eb84d1Schristos$toplevel = 0; # top level seen in hierarchy 50163eb84d1Schristos$curlevel = 0; # current level in TOC 50263eb84d1Schristos$node = ''; # current node name 50363eb84d1Schristos$in_table = 0; # am I inside a table 50463eb84d1Schristos$table_type = ''; # type of table ('', 'f', 'v', 'multi') 50563eb84d1Schristos@tables = (); # nested table support 50663eb84d1Schristos$in_bibliography = 0; # am I inside a bibliography 50763eb84d1Schristos$in_glossary = 0; # am I inside a glossary 50863eb84d1Schristos$in_top = 0; # am I inside the top node 50963eb84d1Schristos$in_pre = 0; # am I inside a preformatted section 51063eb84d1Schristos$in_list = 0; # am I inside a list 51163eb84d1Schristos$in_html = 0; # am I inside an HTML section 51263eb84d1Schristos$first_line = 1; # is it the first line 51363eb84d1Schristos$dont_html = 0; # don't protect HTML on this line 51463eb84d1Schristos$split_num = 0; # split index 51563eb84d1Schristos$deferred_ref = ''; # deferred reference for indexes 51663eb84d1Schristos@html_stack = (); # HTML elements stack 51763eb84d1Schristos$html_element = ''; # current HTML element 51863eb84d1Schristos&html_reset; 51963eb84d1Schristos 52063eb84d1Schristos# build code for simple substitutions 52163eb84d1Schristos# the maps used (%simple_map and %things_map) MUST be aware of this 52263eb84d1Schristos# watch out for regexps, / and escaped characters! 52363eb84d1Schristos$subst_code = ''; 52463eb84d1Schristosforeach (keys(%simple_map)) { 52563eb84d1Schristos ($re = $_) =~ s/(\W)/\\$1/g; # protect regexp chars 52663eb84d1Schristos $subst_code .= "s/\\\@$re/$simple_map{$_}/g;\n"; 52763eb84d1Schristos} 52863eb84d1Schristosforeach (keys(%things_map)) { 52963eb84d1Schristos $subst_code .= "s/\\\@$_\\{\\}/$things_map{$_}/g;\n"; 53063eb84d1Schristos} 53163eb84d1Schristosif ($use_acc) { 53263eb84d1Schristos # accentuated characters 53363eb84d1Schristos foreach (keys(%accent_map)) { 53463eb84d1Schristos if ($_ eq "`") { 53563eb84d1Schristos $subst_code .= "s/$;3"; 53663eb84d1Schristos } elsif ($_ eq "'") { 53763eb84d1Schristos $subst_code .= "s/$;4"; 53863eb84d1Schristos } else { 53963eb84d1Schristos $subst_code .= "s/\\\@\\$_"; 54063eb84d1Schristos } 54163eb84d1Schristos $subst_code .= "([aeiou])/&\${1}$accent_map{$_};/gi;\n"; 54263eb84d1Schristos } 54363eb84d1Schristos} 54463eb84d1Schristoseval("sub simple_substitutions { $subst_code }"); 54563eb84d1Schristos 54663eb84d1Schristos&init_input; 54763eb84d1Schristoswhile ($_ = &next_line) { 54863eb84d1Schristos # 54963eb84d1Schristos # remove \input on the first lines only 55063eb84d1Schristos # 55163eb84d1Schristos if ($first_line) { 55263eb84d1Schristos next if /^\\input/; 55363eb84d1Schristos $first_line = 0; 55463eb84d1Schristos } 55563eb84d1Schristos # 55663eb84d1Schristos # parse texinfo tags 55763eb84d1Schristos # 55863eb84d1Schristos $tag = ''; 55963eb84d1Schristos $end_tag = ''; 56063eb84d1Schristos if (/^\@end\s+(\w+)\b/) { 56163eb84d1Schristos $end_tag = $1; 56263eb84d1Schristos } elsif (/^\@(\w+)\b/) { 56363eb84d1Schristos $tag = $1; 56463eb84d1Schristos } 56563eb84d1Schristos # 56663eb84d1Schristos # handle @ifhtml / @end ifhtml 56763eb84d1Schristos # 56863eb84d1Schristos if ($in_html) { 56963eb84d1Schristos if ($end_tag eq 'ifhtml') { 57063eb84d1Schristos $in_html = 0; 57163eb84d1Schristos } else { 57263eb84d1Schristos $tag2pro{$in_html} .= $_; 57363eb84d1Schristos } 57463eb84d1Schristos next; 57563eb84d1Schristos } elsif ($tag eq 'ifhtml') { 57663eb84d1Schristos $in_html = $PROTECTTAG . ++$html_num; 57763eb84d1Schristos push(@lines, $in_html); 57863eb84d1Schristos next; 57963eb84d1Schristos } 58063eb84d1Schristos # 58163eb84d1Schristos # try to skip the line 58263eb84d1Schristos # 58363eb84d1Schristos if ($end_tag) { 58463eb84d1Schristos next if $to_skip{"end $end_tag"}; 58563eb84d1Schristos } elsif ($tag) { 58663eb84d1Schristos next if $to_skip{$tag}; 58763eb84d1Schristos last if $tag eq 'bye'; 58863eb84d1Schristos } 58963eb84d1Schristos if ($in_top) { 59063eb84d1Schristos # parsing the top node 59163eb84d1Schristos if ($tag eq 'node' || $tag eq 'include' || $sec2level{$tag}) { 59263eb84d1Schristos # no more in top 59363eb84d1Schristos $in_top = 0; 59463eb84d1Schristos } else { 59563eb84d1Schristos # skip it 59663eb84d1Schristos next; 59763eb84d1Schristos } 59863eb84d1Schristos } 59963eb84d1Schristos # 60063eb84d1Schristos # try to remove inlined comments 60163eb84d1Schristos # syntax from tex-mode.el comment-start-skip 60263eb84d1Schristos # 60363eb84d1Schristos s/((^|[^\@])(\@\@)*)\@c(omment)? .*/$1/; 60463eb84d1Schristos # non-@ substitutions cf. texinfmt.el 60563eb84d1Schristos unless ($in_pre) { 60663eb84d1Schristos s/``/“/g; 60763eb84d1Schristos s/''/”/g; 60863eb84d1Schristos s/([\w ])---([\w ])/$1--$2/g; 60963eb84d1Schristos } 61063eb84d1Schristos # 61163eb84d1Schristos # analyze the tag 61263eb84d1Schristos # 61363eb84d1Schristos if ($tag) { 61463eb84d1Schristos # skip lines 61563eb84d1Schristos &skip_until($tag), next if $tag eq 'ignore'; 61663eb84d1Schristos if ($expandinfo) { 61763eb84d1Schristos &skip_until($tag), next if $tag eq 'ifnotinfo'; 61863eb84d1Schristos &skip_until($tag), next if $tag eq 'iftex'; 61963eb84d1Schristos &skip_until($tag), next if $tag eq 'ifhtml'; 62063eb84d1Schristos } elsif ($expandtex) { 62163eb84d1Schristos &skip_until($tag), next if $tag eq 'ifinfo'; 62263eb84d1Schristos &skip_until($tag), next if $tag eq 'ifnottex'; 62363eb84d1Schristos &skip_until($tag), next if $tag eq 'ifhtml'; 62463eb84d1Schristos } else { 62563eb84d1Schristos &skip_until($tag), next if $tag eq 'ifinfo'; 62663eb84d1Schristos &skip_until($tag), next if $tag eq 'iftex'; 62763eb84d1Schristos &skip_until($tag), next if $tag eq 'ifnothtml'; 62863eb84d1Schristos } 62963eb84d1Schristos &skip_until($tag), next if $tag eq 'tex'; 63063eb84d1Schristos # handle special tables 63163eb84d1Schristos if ($tag =~ /^(|f|v|multi)table$/) { 63263eb84d1Schristos $table_type = $1; 63363eb84d1Schristos $tag = 'table'; 63463eb84d1Schristos } 63563eb84d1Schristos # special cases 63663eb84d1Schristos if ($tag eq 'top' || ($tag eq 'node' && /^\@node\s+top\s*,/i)) { 63763eb84d1Schristos $in_top = 1; 63863eb84d1Schristos @lines = (); # ignore all lines before top (title page garbage) 63963eb84d1Schristos next; 64063eb84d1Schristos } elsif ($tag eq 'node') { 64163eb84d1Schristos $in_top = 0; 64263eb84d1Schristos warn "$ERROR Bad node line: $_" unless $_ =~ /^\@node\s$NODESRE$/o; 64363eb84d1Schristos $_ = &protect_html($_); # if node contains '&' for instance 64463eb84d1Schristos s/^\@node\s+//; 64563eb84d1Schristos ($node) = split(/,/); 64663eb84d1Schristos &normalise_node($node); 64763eb84d1Schristos if ($split_node) { 64863eb84d1Schristos &next_doc; 64963eb84d1Schristos push(@lines, $SPLITTAG) if $split_num++; 65063eb84d1Schristos push(@sections, $node); 65163eb84d1Schristos } 65263eb84d1Schristos next; 65363eb84d1Schristos } elsif ($tag eq 'include') { 65463eb84d1Schristos if (/^\@include\s+($FILERE)\s*$/o) { 65563eb84d1Schristos $file = $1; 65663eb84d1Schristos unless (-e $file) { 65763eb84d1Schristos foreach $dir (@include_dirs) { 65863eb84d1Schristos $file = "$dir/$1"; 65963eb84d1Schristos last if -e $file; 66063eb84d1Schristos } 66163eb84d1Schristos } 66263eb84d1Schristos if (-e $file) { 66363eb84d1Schristos &open($file); 66463eb84d1Schristos print "# including $file\n" if $verbose; 66563eb84d1Schristos } else { 66663eb84d1Schristos warn "$ERROR Can't find $file, skipping"; 66763eb84d1Schristos } 66863eb84d1Schristos } else { 66963eb84d1Schristos warn "$ERROR Bad include line: $_"; 67063eb84d1Schristos } 67163eb84d1Schristos next; 67263eb84d1Schristos } elsif ($tag eq 'ifclear') { 67363eb84d1Schristos if (/^\@ifclear\s+($VARRE)\s*$/o) { 67463eb84d1Schristos next unless defined($value{$1}); 67563eb84d1Schristos &skip_until($tag); 67663eb84d1Schristos } else { 67763eb84d1Schristos warn "$ERROR Bad ifclear line: $_"; 67863eb84d1Schristos } 67963eb84d1Schristos next; 68063eb84d1Schristos } elsif ($tag eq 'ifset') { 68163eb84d1Schristos if (/^\@ifset\s+($VARRE)\s*$/o) { 68263eb84d1Schristos next if defined($value{$1}); 68363eb84d1Schristos &skip_until($tag); 68463eb84d1Schristos } else { 68563eb84d1Schristos warn "$ERROR Bad ifset line: $_"; 68663eb84d1Schristos } 68763eb84d1Schristos next; 68863eb84d1Schristos } elsif ($tag eq 'menu') { 68963eb84d1Schristos unless ($show_menu) { 69063eb84d1Schristos &skip_until($tag); 69163eb84d1Schristos next; 69263eb84d1Schristos } 69363eb84d1Schristos &html_push_if($tag); 69463eb84d1Schristos push(@lines, &html_debug("\n", __LINE__)); 69563eb84d1Schristos } elsif ($format_map{$tag}) { 69663eb84d1Schristos $in_pre = 1 if $format_map{$tag} eq 'PRE'; 69763eb84d1Schristos &html_push_if($format_map{$tag}); 69863eb84d1Schristos push(@lines, &html_debug("\n", __LINE__)); 69963eb84d1Schristos $in_list++ if $format_map{$tag} eq 'UL' || $format_map{$tag} eq 'OL' ; 70063eb84d1Schristos push(@lines, &debug("<$format_map{$tag}>\n", __LINE__)); 70163eb84d1Schristos next; 70263eb84d1Schristos } elsif ($tag eq 'table') { 70363eb84d1Schristos if (/^\@(|f|v|multi)table\s+\@(\w+)/) { 70463eb84d1Schristos $in_table = $2; 70563eb84d1Schristos unshift(@tables, join($;, $table_type, $in_table)); 70663eb84d1Schristos if ($table_type eq "multi") { 70763eb84d1Schristos push(@lines, &debug("<TABLE BORDER>\n", __LINE__)); 70863eb84d1Schristos &html_push_if('TABLE'); 70963eb84d1Schristos } else { 71063eb84d1Schristos push(@lines, &debug("<DL COMPACT>\n", __LINE__)); 71163eb84d1Schristos &html_push_if('DL'); 71263eb84d1Schristos } 71363eb84d1Schristos push(@lines, &html_debug("\n", __LINE__)); 71463eb84d1Schristos } else { 71563eb84d1Schristos warn "$ERROR Bad table line: $_"; 71663eb84d1Schristos } 71763eb84d1Schristos next; 71863eb84d1Schristos } elsif ($tag eq 'synindex' || $tag eq 'syncodeindex') { 71963eb84d1Schristos if (/^\@$tag\s+(\w)\w\s+(\w)\w\s*$/) { 72063eb84d1Schristos eval("*${1}index = *${2}index"); 72163eb84d1Schristos } else { 72263eb84d1Schristos warn "$ERROR Bad syn*index line: $_"; 72363eb84d1Schristos } 72463eb84d1Schristos next; 72563eb84d1Schristos } elsif ($tag eq 'sp') { 72663eb84d1Schristos push(@lines, &debug("<P>\n", __LINE__)); 72763eb84d1Schristos next; 72863eb84d1Schristos } elsif ($tag eq 'setref') { 72963eb84d1Schristos &protect_html; # if setref contains '&' for instance 73063eb84d1Schristos if (/^\@$tag\s*{($NODERE)}\s*$/) { 73163eb84d1Schristos $setref = $1; 73263eb84d1Schristos $setref =~ s/\s+/ /g; # normalize 73363eb84d1Schristos $setref =~ s/ $//; 73463eb84d1Schristos $node2sec{$setref} = $name; 73563eb84d1Schristos $node2href{$setref} = "$docu_doc#$docid"; 73663eb84d1Schristos } else { 73763eb84d1Schristos warn "$ERROR Bad setref line: $_"; 73863eb84d1Schristos } 73963eb84d1Schristos next; 74063eb84d1Schristos } elsif ($tag eq 'defindex' || $tag eq 'defcodeindex') { 74163eb84d1Schristos if (/^\@$tag\s+(\w\w)\s*$/) { 74263eb84d1Schristos $valid_index{$1} = 1; 74363eb84d1Schristos } else { 74463eb84d1Schristos warn "$ERROR Bad defindex line: $_"; 74563eb84d1Schristos } 74663eb84d1Schristos next; 74763eb84d1Schristos } elsif (defined($def_map{$tag})) { 74863eb84d1Schristos if ($def_map{$tag}) { 74963eb84d1Schristos s/^\@$tag\s+//; 75063eb84d1Schristos $tag = $def_map{$tag}; 75163eb84d1Schristos $_ = "\@$tag $_"; 75263eb84d1Schristos $tag =~ s/\s.*//; 75363eb84d1Schristos } 75463eb84d1Schristos } elsif (defined($user_sub{$tag})) { 75563eb84d1Schristos s/^\@$tag\s+//; 75663eb84d1Schristos $sub = $user_sub{$tag}; 75763eb84d1Schristos print "# user $tag = $sub, arg: $_" if $debug & $DEBUG_USER; 75863eb84d1Schristos if (defined(&$sub)) { 75963eb84d1Schristos chop($_); 76063eb84d1Schristos &$sub($_); 76163eb84d1Schristos } else { 76263eb84d1Schristos warn "$ERROR Bad user sub for $tag: $sub\n"; 76363eb84d1Schristos } 76463eb84d1Schristos next; 76563eb84d1Schristos } 76663eb84d1Schristos if (defined($def_map{$tag})) { 76763eb84d1Schristos s/^\@$tag\s+//; 76863eb84d1Schristos if ($tag =~ /x$/) { 76963eb84d1Schristos # extra definition line 77063eb84d1Schristos $tag = $`; 77163eb84d1Schristos $is_extra = 1; 77263eb84d1Schristos } else { 77363eb84d1Schristos $is_extra = 0; 77463eb84d1Schristos } 77563eb84d1Schristos while (/\{([^\{\}]*)\}/) { 77663eb84d1Schristos # this is a {} construct 77763eb84d1Schristos ($before, $contents, $after) = ($`, $1, $'); 77863eb84d1Schristos # protect spaces 77963eb84d1Schristos $contents =~ s/\s+/$;9/g; 78063eb84d1Schristos # restore $_ protecting {} 78163eb84d1Schristos $_ = "$before$;7$contents$;8$after"; 78263eb84d1Schristos } 78363eb84d1Schristos @args = split(/\s+/, &protect_html($_)); 78463eb84d1Schristos foreach (@args) { 78563eb84d1Schristos s/$;9/ /g; # unprotect spaces 78663eb84d1Schristos s/$;7/\{/g; # ... { 78763eb84d1Schristos s/$;8/\}/g; # ... } 78863eb84d1Schristos } 78963eb84d1Schristos $type = shift(@args); 79063eb84d1Schristos $type =~ s/^\{(.*)\}$/$1/; 79163eb84d1Schristos print "# def ($tag): {$type} ", join(', ', @args), "\n" 79263eb84d1Schristos if $debug & $DEBUG_DEF; 79363eb84d1Schristos $type .= ':'; # it's nicer like this 79463eb84d1Schristos $name = shift(@args); 79563eb84d1Schristos $name =~ s/^\{(.*)\}$/$1/; 79663eb84d1Schristos if ($is_extra) { 79763eb84d1Schristos $_ = &debug("<DT>", __LINE__); 79863eb84d1Schristos } else { 79963eb84d1Schristos $_ = &debug("<DL>\n<DT>", __LINE__); 80063eb84d1Schristos } 80163eb84d1Schristos if ($tag eq 'deffn' || $tag eq 'defvr' || $tag eq 'deftp') { 80263eb84d1Schristos $_ .= "<U>$type</U> <B>$name</B>"; 80363eb84d1Schristos $_ .= " <I>@args</I>" if @args; 80463eb84d1Schristos } elsif ($tag eq 'deftypefn' || $tag eq 'deftypevr' 80563eb84d1Schristos || $tag eq 'defcv' || $tag eq 'defop') { 80663eb84d1Schristos $ftype = $name; 80763eb84d1Schristos $name = shift(@args); 80863eb84d1Schristos $name =~ s/^\{(.*)\}$/$1/; 80963eb84d1Schristos $_ .= "<U>$type</U> $ftype <B>$name</B>"; 81063eb84d1Schristos $_ .= " <I>@args</I>" if @args; 81163eb84d1Schristos } else { 81263eb84d1Schristos warn "$ERROR Unknown definition type: $tag\n"; 81363eb84d1Schristos $_ .= "<U>$type</U> <B>$name</B>"; 81463eb84d1Schristos $_ .= " <I>@args</I>" if @args; 81563eb84d1Schristos } 81663eb84d1Schristos $_ .= &debug("\n<DD>", __LINE__); 81763eb84d1Schristos $name = &unprotect_html($name); 81863eb84d1Schristos if ($tag eq 'deffn' || $tag eq 'deftypefn') { 81963eb84d1Schristos unshift(@input_spool, "\@findex $name\n"); 82063eb84d1Schristos } elsif ($tag eq 'defop') { 82163eb84d1Schristos unshift(@input_spool, "\@findex $name on $ftype\n"); 82263eb84d1Schristos } elsif ($tag eq 'defvr' || $tag eq 'deftypevr' || $tag eq 'defcv') { 82363eb84d1Schristos unshift(@input_spool, "\@vindex $name\n"); 82463eb84d1Schristos } else { 82563eb84d1Schristos unshift(@input_spool, "\@tindex $name\n"); 82663eb84d1Schristos } 82763eb84d1Schristos $dont_html = 1; 82863eb84d1Schristos } 82963eb84d1Schristos } elsif ($end_tag) { 83063eb84d1Schristos if ($format_map{$end_tag}) { 83163eb84d1Schristos $in_pre = 0 if $format_map{$end_tag} eq 'PRE'; 83263eb84d1Schristos $in_list-- if $format_map{$end_tag} eq 'UL' || $format_map{$end_tag} eq 'OL' ; 83363eb84d1Schristos &html_pop_if('LI', 'P'); 83463eb84d1Schristos &html_pop_if(); 83563eb84d1Schristos push(@lines, &debug("</$format_map{$end_tag}>\n", __LINE__)); 83663eb84d1Schristos push(@lines, &html_debug("\n", __LINE__)); 83763eb84d1Schristos } elsif ($end_tag =~ /^(|f|v|multi)table$/) { 83863eb84d1Schristos unless (@tables) { 83963eb84d1Schristos warn "$ERROR \@end $end_tag without \@*table\n"; 84063eb84d1Schristos next; 84163eb84d1Schristos } 84263eb84d1Schristos ($table_type, $in_table) = split($;, shift(@tables)); 84363eb84d1Schristos unless ($1 eq $table_type) { 84463eb84d1Schristos warn "$ERROR \@end $end_tag without matching \@$end_tag\n"; 84563eb84d1Schristos next; 84663eb84d1Schristos } 84763eb84d1Schristos if ($table_type eq "multi") { 84863eb84d1Schristos push(@lines, "</TR></TABLE>\n"); 84963eb84d1Schristos &html_pop_if('TR'); 85063eb84d1Schristos } else { 85163eb84d1Schristos push(@lines, "</DL>\n"); 85263eb84d1Schristos &html_pop_if('DD'); 85363eb84d1Schristos } 85463eb84d1Schristos &html_pop_if(); 85563eb84d1Schristos if (@tables) { 85663eb84d1Schristos ($table_type, $in_table) = split($;, $tables[0]); 85763eb84d1Schristos } else { 85863eb84d1Schristos $in_table = 0; 85963eb84d1Schristos } 86063eb84d1Schristos } elsif (defined($def_map{$end_tag})) { 86163eb84d1Schristos push(@lines, &debug("</DL>\n", __LINE__)); 86263eb84d1Schristos } elsif ($end_tag eq 'menu') { 86363eb84d1Schristos &html_pop_if(); 86463eb84d1Schristos push(@lines, $_); # must keep it for pass 2 86563eb84d1Schristos } 86663eb84d1Schristos next; 86763eb84d1Schristos } 86863eb84d1Schristos # 86963eb84d1Schristos # misc things 87063eb84d1Schristos # 87163eb84d1Schristos # protect texi and HTML things 87263eb84d1Schristos &protect_texi; 87363eb84d1Schristos $_ = &protect_html($_) unless $dont_html; 87463eb84d1Schristos $dont_html = 0; 87563eb84d1Schristos # substitution (unsupported things) 87663eb84d1Schristos s/^\@center\s+//g; 87763eb84d1Schristos s/^\@exdent\s+//g; 87863eb84d1Schristos s/\@noindent\s+//g; 87963eb84d1Schristos s/\@refill\s+//g; 88063eb84d1Schristos # other substitutions 88163eb84d1Schristos &simple_substitutions; 88263eb84d1Schristos s/\@value{($VARRE)}/$value{$1}/eg; 88363eb84d1Schristos s/\@footnote\{/\@footnote$docu_doc\{/g; # mark footnotes, cf. pass 4 88463eb84d1Schristos # 88563eb84d1Schristos # analyze the tag again 88663eb84d1Schristos # 88763eb84d1Schristos if ($tag) { 88863eb84d1Schristos if (defined($sec2level{$tag}) && $sec2level{$tag} > 0) { 88963eb84d1Schristos if (/^\@$tag\s+(.+)$/) { 89063eb84d1Schristos $name = $1; 89163eb84d1Schristos $name =~ s/\s+$//; 89263eb84d1Schristos $level = $sec2level{$tag}; 89363eb84d1Schristos $name = &update_sec_num($tag, $level) . " $name" 89463eb84d1Schristos if $number_sections && $tag !~ /^unnumbered/; 89563eb84d1Schristos if ($tag =~ /heading$/) { 89663eb84d1Schristos push(@lines, &html_debug("\n", __LINE__)); 89763eb84d1Schristos if ($html_element ne 'body') { 89863eb84d1Schristos # We are in a nice pickle here. We are trying to get a H? heading 89963eb84d1Schristos # even though we are not in the body level. So, we convert it to a 90063eb84d1Schristos # nice, bold, line by itself. 90163eb84d1Schristos $_ = &debug("\n\n<P><STRONG>$name</STRONG></P>\n\n", __LINE__); 90263eb84d1Schristos } else { 90363eb84d1Schristos $_ = &debug("<H$level>$name</H$level>\n", __LINE__); 90463eb84d1Schristos &html_push_if('body'); 90563eb84d1Schristos } 90663eb84d1Schristos print "# heading, section $name, level $level\n" 90763eb84d1Schristos if $debug & $DEBUG_TOC; 90863eb84d1Schristos } else { 90963eb84d1Schristos if ($split_chapter) { 91063eb84d1Schristos unless ($toplevel) { 91163eb84d1Schristos # first time we see a "section" 91263eb84d1Schristos unless ($level == 1) { 91363eb84d1Schristos warn "$ERROR The first section found is not of level 1: $_"; 91463eb84d1Schristos warn "$ERROR I'll split on sections of level $level...\n"; 91563eb84d1Schristos } 91663eb84d1Schristos $toplevel = $level; 91763eb84d1Schristos } 91863eb84d1Schristos if ($level == $toplevel) { 91963eb84d1Schristos &next_doc; 92063eb84d1Schristos push(@lines, $SPLITTAG) if $split_num++; 92163eb84d1Schristos push(@sections, $name); 92263eb84d1Schristos } 92363eb84d1Schristos } 92463eb84d1Schristos $sec_num++; 92563eb84d1Schristos $docid = "SEC$sec_num"; 92663eb84d1Schristos $tocid = "TOC$sec_num"; 92763eb84d1Schristos # check biblio and glossary 92863eb84d1Schristos $in_bibliography = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*bibliography$/i); 92963eb84d1Schristos $in_glossary = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*glossary$/i); 93063eb84d1Schristos # check node 93163eb84d1Schristos if ($node) { 93263eb84d1Schristos if ($node2sec{$node}) { 93363eb84d1Schristos warn "$ERROR Duplicate node found: $node\n"; 93463eb84d1Schristos } else { 93563eb84d1Schristos $node2sec{$node} = $name; 93663eb84d1Schristos $node2href{$node} = "$docu_doc#$docid"; 93763eb84d1Schristos print "# node $node, section $name, level $level\n" 93863eb84d1Schristos if $debug & $DEBUG_TOC; 93963eb84d1Schristos } 94063eb84d1Schristos $node = ''; 94163eb84d1Schristos } else { 94263eb84d1Schristos print "# no node, section $name, level $level\n" 94363eb84d1Schristos if $debug & $DEBUG_TOC; 94463eb84d1Schristos } 94563eb84d1Schristos # update TOC 94663eb84d1Schristos while ($level > $curlevel) { 94763eb84d1Schristos $curlevel++; 94863eb84d1Schristos push(@toc_lines, "<UL>\n"); 94963eb84d1Schristos } 95063eb84d1Schristos while ($level < $curlevel) { 95163eb84d1Schristos $curlevel--; 95263eb84d1Schristos push(@toc_lines, "</UL>\n"); 95363eb84d1Schristos } 95463eb84d1Schristos $_ = "<LI>" . &anchor($tocid, "$docu_doc#$docid", $name, 1); 95563eb84d1Schristos push(@toc_lines, &substitute_style($_)); 95663eb84d1Schristos # update DOC 95763eb84d1Schristos push(@lines, &html_debug("\n", __LINE__)); 95863eb84d1Schristos &html_reset; 95963eb84d1Schristos $_ = "<H$level>".&anchor($docid, "$docu_toc#$tocid", $name)."</H$level>\n"; 96063eb84d1Schristos $_ = &debug($_, __LINE__); 96163eb84d1Schristos push(@lines, &html_debug("\n", __LINE__)); 96263eb84d1Schristos } 96363eb84d1Schristos # update DOC 96463eb84d1Schristos foreach $line (split(/\n+/, $_)) { 96563eb84d1Schristos push(@lines, "$line\n"); 96663eb84d1Schristos } 96763eb84d1Schristos next; 96863eb84d1Schristos } else { 96963eb84d1Schristos warn "$ERROR Bad section line: $_"; 97063eb84d1Schristos } 97163eb84d1Schristos } else { 97263eb84d1Schristos # track variables 97363eb84d1Schristos $value{$1} = $2, next if /^\@set\s+($VARRE)\s+(.*)$/o; 97463eb84d1Schristos delete $value{$1}, next if /^\@clear\s+($VARRE)\s*$/o; 97563eb84d1Schristos # store things 97663eb84d1Schristos $value{'_setfilename'} = $1, next if /^\@setfilename\s+(.*)$/; 97763eb84d1Schristos $value{'_settitle'} = $1, next if /^\@settitle\s+(.*)$/; 97863eb84d1Schristos $value{'_author'} .= "$1\n", next if /^\@author\s+(.*)$/; 97963eb84d1Schristos $value{'_subtitle'} .= "$1\n", next if /^\@subtitle\s+(.*)$/; 98063eb84d1Schristos $value{'_title'} .= "$1\n", next if /^\@title\s+(.*)$/; 98163eb84d1Schristos # index 98263eb84d1Schristos if (/^\@(..?)index\s+/) { 98363eb84d1Schristos unless ($valid_index{$1}) { 98463eb84d1Schristos warn "$ERROR Undefined index command: $_"; 98563eb84d1Schristos next; 98663eb84d1Schristos } 98763eb84d1Schristos $id = 'IDX' . ++$idx_num; 98863eb84d1Schristos $index = $1 . 'index'; 98963eb84d1Schristos $what = &substitute_style($'); 99063eb84d1Schristos $what =~ s/\s+$//; 99163eb84d1Schristos print "# found $index for '$what' id $id\n" 99263eb84d1Schristos if $debug & $DEBUG_INDEX; 99363eb84d1Schristos eval(<<EOC); 99463eb84d1Schristos if (defined(\$$index\{\$what\})) { 99563eb84d1Schristos \$$index\{\$what\} .= "$;$docu_doc#$id"; 99663eb84d1Schristos } else { 99763eb84d1Schristos \$$index\{\$what\} = "$docu_doc#$id"; 99863eb84d1Schristos } 99963eb84d1SchristosEOC 100063eb84d1Schristos # 100163eb84d1Schristos # dirty hack to see if I can put an invisible anchor... 100263eb84d1Schristos # 100363eb84d1Schristos if ($html_element eq 'P' || 100463eb84d1Schristos $html_element eq 'LI' || 100563eb84d1Schristos $html_element eq 'DT' || 100663eb84d1Schristos $html_element eq 'DD' || 100763eb84d1Schristos $html_element eq 'ADDRESS' || 100863eb84d1Schristos $html_element eq 'B' || 100963eb84d1Schristos $html_element eq 'BLOCKQUOTE' || 101063eb84d1Schristos $html_element eq 'PRE' || 101163eb84d1Schristos $html_element eq 'SAMP') { 101263eb84d1Schristos push(@lines, &anchor($id, '', $invisible_mark, !$in_pre)); 101363eb84d1Schristos } elsif ($html_element eq 'body') { 101463eb84d1Schristos push(@lines, &debug("<P>\n", __LINE__)); 101563eb84d1Schristos push(@lines, &anchor($id, '', $invisible_mark, !$in_pre)); 101663eb84d1Schristos &html_push('P'); 101763eb84d1Schristos } elsif ($html_element eq 'DL' || 101863eb84d1Schristos $html_element eq 'UL' || 101963eb84d1Schristos $html_element eq 'OL' ) { 102063eb84d1Schristos $deferred_ref .= &anchor($id, '', $invisible_mark, !$in_pre) . " "; 102163eb84d1Schristos } 102263eb84d1Schristos next; 102363eb84d1Schristos } 102463eb84d1Schristos # list item 102563eb84d1Schristos if (/^\@itemx?\s+/) { 102663eb84d1Schristos $what = $'; 102763eb84d1Schristos $what =~ s/\s+$//; 102863eb84d1Schristos if ($in_bibliography && $use_bibliography) { 102963eb84d1Schristos if ($what =~ /^$BIBRE$/o) { 103063eb84d1Schristos $id = 'BIB' . ++$bib_num; 103163eb84d1Schristos $bib2href{$what} = "$docu_doc#$id"; 103263eb84d1Schristos print "# found bibliography for '$what' id $id\n" 103363eb84d1Schristos if $debug & $DEBUG_BIB; 103463eb84d1Schristos $what = &anchor($id, '', $what); 103563eb84d1Schristos } 103663eb84d1Schristos } elsif ($in_glossary && $use_glossary) { 103763eb84d1Schristos $id = 'GLOSS' . ++$gloss_num; 103863eb84d1Schristos $entry = $what; 103963eb84d1Schristos $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/; 104063eb84d1Schristos $gloss2href{$entry} = "$docu_doc#$id"; 104163eb84d1Schristos print "# found glossary for '$entry' id $id\n" 104263eb84d1Schristos if $debug & $DEBUG_GLOSS; 104363eb84d1Schristos $what = &anchor($id, '', $what); 104463eb84d1Schristos } 104563eb84d1Schristos &html_pop_if('P'); 104663eb84d1Schristos if ($html_element eq 'DL' || $html_element eq 'DD') { 104763eb84d1Schristos if ($things_map{$in_table} && !$what) { 104863eb84d1Schristos # special case to allow @table @bullet for instance 104963eb84d1Schristos push(@lines, &debug("<DT>$things_map{$in_table}\n", __LINE__)); 105063eb84d1Schristos } else { 105163eb84d1Schristos push(@lines, &debug("<DT>\@$in_table\{$what\}\n", __LINE__)); 105263eb84d1Schristos } 105363eb84d1Schristos push(@lines, "<DD>"); 105463eb84d1Schristos &html_push('DD') unless $html_element eq 'DD'; 105563eb84d1Schristos if ($table_type) { # add also an index 105663eb84d1Schristos unshift(@input_spool, "\@${table_type}index $what\n"); 105763eb84d1Schristos } 105863eb84d1Schristos } elsif ($html_element eq 'TABLE') { 105963eb84d1Schristos push(@lines, &debug("<TR><TD>$what</TD>\n", __LINE__)); 106063eb84d1Schristos &html_push('TR'); 106163eb84d1Schristos } elsif ($html_element eq 'TR') { 106263eb84d1Schristos push(@lines, &debug("</TR>\n", __LINE__)); 106363eb84d1Schristos push(@lines, &debug("<TR><TD>$what</TD>\n", __LINE__)); 106463eb84d1Schristos } else { 106563eb84d1Schristos push(@lines, &debug("<LI>$what\n", __LINE__)); 106663eb84d1Schristos &html_push('LI') unless $html_element eq 'LI'; 106763eb84d1Schristos } 106863eb84d1Schristos push(@lines, &html_debug("\n", __LINE__)); 106963eb84d1Schristos if ($deferred_ref) { 107063eb84d1Schristos push(@lines, &debug("$deferred_ref\n", __LINE__)); 107163eb84d1Schristos $deferred_ref = ''; 107263eb84d1Schristos } 107363eb84d1Schristos next; 107463eb84d1Schristos } elsif (/^\@tab\s+(.*)$/) { 107563eb84d1Schristos push(@lines, "<TD>$1</TD>\n"); 107663eb84d1Schristos next; 107763eb84d1Schristos } 107863eb84d1Schristos } 107963eb84d1Schristos } 108063eb84d1Schristos # paragraph separator 108163eb84d1Schristos if ($_ eq "\n") { 108263eb84d1Schristos next if $#lines >= 0 && $lines[$#lines] eq "\n"; 108363eb84d1Schristos if ($html_element eq 'P') { 108463eb84d1Schristos push(@lines, "\n"); 108563eb84d1Schristos $_ = &debug("</P>\n", __LINE__); 108663eb84d1Schristos &html_pop; 108763eb84d1Schristos } 108863eb84d1Schristos } elsif ($html_element eq 'body' || $html_element eq 'BLOCKQUOTE') { 108963eb84d1Schristos push(@lines, "<P>\n"); 109063eb84d1Schristos &html_push('P'); 109163eb84d1Schristos $_ = &debug($_, __LINE__); 109263eb84d1Schristos } 109363eb84d1Schristos # otherwise 109463eb84d1Schristos push(@lines, $_); 109563eb84d1Schristos} 109663eb84d1Schristos 109763eb84d1Schristos# finish TOC 109863eb84d1Schristos$level = 0; 109963eb84d1Schristoswhile ($level < $curlevel) { 110063eb84d1Schristos $curlevel--; 110163eb84d1Schristos push(@toc_lines, "</UL>\n"); 110263eb84d1Schristos} 110363eb84d1Schristos 110463eb84d1Schristosprint "# end of pass 1\n" if $verbose; 110563eb84d1Schristos 110663eb84d1Schristos#+++############################################################################ 110763eb84d1Schristos# # 110863eb84d1Schristos# Pass 2/3: handle style, menu, index, cross-reference # 110963eb84d1Schristos# # 111063eb84d1Schristos#---############################################################################ 111163eb84d1Schristos 111263eb84d1Schristos@lines2 = (); # whole document (2nd pass) 111363eb84d1Schristos@lines3 = (); # whole document (3rd pass) 111463eb84d1Schristos$in_menu = 0; # am I inside a menu 111563eb84d1Schristos 111663eb84d1Schristoswhile (@lines) { 111763eb84d1Schristos $_ = shift(@lines); 111863eb84d1Schristos # 111963eb84d1Schristos # special case (protected sections) 112063eb84d1Schristos # 112163eb84d1Schristos if (/^$PROTECTTAG/o) { 112263eb84d1Schristos push(@lines2, $_); 112363eb84d1Schristos next; 112463eb84d1Schristos } 112563eb84d1Schristos # 112663eb84d1Schristos # menu 112763eb84d1Schristos # 112863eb84d1Schristos $in_menu = 1, push(@lines2, &debug("<UL>\n", __LINE__)), next if /^\@menu\b/; 112963eb84d1Schristos $in_menu = 0, push(@lines2, &debug("</UL>\n", __LINE__)), next if /^\@end\s+menu\b/; 113063eb84d1Schristos if ($in_menu) { 113163eb84d1Schristos if (/^\*\s+($NODERE)::/o) { 113263eb84d1Schristos $descr = $'; 113363eb84d1Schristos chop($descr); 113463eb84d1Schristos &menu_entry($1, $1, $descr); 113563eb84d1Schristos } elsif (/^\*\s+(.+):\s+([^\t,\.\n]+)[\t,\.\n]/) { 113663eb84d1Schristos $descr = $'; 113763eb84d1Schristos chop($descr); 113863eb84d1Schristos &menu_entry($1, $2, $descr); 113963eb84d1Schristos } elsif (/^\*/) { 114063eb84d1Schristos warn "$ERROR Bad menu line: $_"; 114163eb84d1Schristos } else { # description continued? 114263eb84d1Schristos push(@lines2, $_); 114363eb84d1Schristos } 114463eb84d1Schristos next; 114563eb84d1Schristos } 114663eb84d1Schristos # 114763eb84d1Schristos # printindex 114863eb84d1Schristos # 114963eb84d1Schristos if (/^\@printindex\s+(\w\w)\b/) { 115063eb84d1Schristos local($index, *ary, @keys, $key, $letter, $last_letter, @refs); 115163eb84d1Schristos if ($predefined_index{$1}) { 115263eb84d1Schristos $index = $predefined_index{$1} . 'index'; 115363eb84d1Schristos } else { 115463eb84d1Schristos $index = $1 . 'index'; 115563eb84d1Schristos } 115663eb84d1Schristos eval("*ary = *$index"); 115763eb84d1Schristos @keys = keys(%ary); 115863eb84d1Schristos foreach $key (@keys) { 115963eb84d1Schristos $_ = $key; 116063eb84d1Schristos 1 while s/<(\w+)>\`(.*)\´<\/\1>/$2/; # remove HTML tags with quotes 116163eb84d1Schristos 1 while s/<(\w+)>(.*)<\/\1>/$2/; # remove HTML tags 116263eb84d1Schristos $_ = &unprotect_html($_); 116363eb84d1Schristos &unprotect_texi; 116463eb84d1Schristos tr/A-Z/a-z/; # lowercase 116563eb84d1Schristos $key2alpha{$key} = $_; 116663eb84d1Schristos print "# index $key sorted as $_\n" 116763eb84d1Schristos if $key ne $_ && $debug & $DEBUG_INDEX; 116863eb84d1Schristos } 116963eb84d1Schristos push(@lines2, "Jump to:\n"); 117063eb84d1Schristos $last_letter = undef; 117163eb84d1Schristos foreach $key (sort byalpha @keys) { 117263eb84d1Schristos $letter = substr($key2alpha{$key}, 0, 1); 117363eb84d1Schristos $letter = substr($key2alpha{$key}, 0, 2) if $letter eq $;; 117463eb84d1Schristos if (!defined($last_letter) || $letter ne $last_letter) { 117563eb84d1Schristos push(@lines2, "-\n") if defined($last_letter); 117663eb84d1Schristos push(@lines2, "<A HREF=\"#$index\_$letter\">" . &protect_html($letter) . "</A>\n"); 117763eb84d1Schristos $last_letter = $letter; 117863eb84d1Schristos } 117963eb84d1Schristos } 118063eb84d1Schristos push(@lines2, "<P>\n"); 118163eb84d1Schristos $last_letter = undef; 118263eb84d1Schristos foreach $key (sort byalpha @keys) { 118363eb84d1Schristos $letter = substr($key2alpha{$key}, 0, 1); 118463eb84d1Schristos $letter = substr($key2alpha{$key}, 0, 2) if $letter eq $;; 118563eb84d1Schristos if (!defined($last_letter) || $letter ne $last_letter) { 118663eb84d1Schristos push(@lines2, "</DIR>\n") if defined($last_letter); 118763eb84d1Schristos push(@lines2, "<H2><A NAME=\"$index\_$letter\">" . &protect_html($letter) . "</A></H2>\n"); 118863eb84d1Schristos push(@lines2, "<DIR>\n"); 118963eb84d1Schristos $last_letter = $letter; 119063eb84d1Schristos } 119163eb84d1Schristos @refs = (); 119263eb84d1Schristos foreach (split(/$;/, $ary{$key})) { 119363eb84d1Schristos push(@refs, &anchor('', $_, $key, 0)); 119463eb84d1Schristos } 119563eb84d1Schristos push(@lines2, "<LI>" . join(", ", @refs) . "\n"); 119663eb84d1Schristos } 119763eb84d1Schristos push(@lines2, "</DIR>\n") if defined($last_letter); 119863eb84d1Schristos next; 119963eb84d1Schristos } 120063eb84d1Schristos # 120163eb84d1Schristos # simple style substitutions 120263eb84d1Schristos # 120363eb84d1Schristos $_ = &substitute_style($_); 120463eb84d1Schristos # 120563eb84d1Schristos # xref 120663eb84d1Schristos # 120763eb84d1Schristos while (/\@(x|px|info|)ref{($XREFRE)(}?)/o) { 120863eb84d1Schristos # note: Texinfo may accept other characters 120963eb84d1Schristos ($type, $nodes, $full) = ($1, $2, $3); 121063eb84d1Schristos ($before, $after) = ($`, $'); 121163eb84d1Schristos if (! $full && $after) { 121263eb84d1Schristos warn "$ERROR Bad xref (no ending } on line): $_"; 121363eb84d1Schristos $_ = "$before$;0${type}ref\{$nodes$after"; 121463eb84d1Schristos next; # while xref 121563eb84d1Schristos } 121663eb84d1Schristos if ($type eq 'x') { 121763eb84d1Schristos $type = 'See '; 121863eb84d1Schristos } elsif ($type eq 'px') { 121963eb84d1Schristos $type = 'see '; 122063eb84d1Schristos } elsif ($type eq 'info') { 122163eb84d1Schristos $type = 'See Info'; 122263eb84d1Schristos } else { 122363eb84d1Schristos $type = ''; 122463eb84d1Schristos } 122563eb84d1Schristos unless ($full) { 122663eb84d1Schristos $next = shift(@lines); 122763eb84d1Schristos $next = &substitute_style($next); 122863eb84d1Schristos chop($nodes); # remove final newline 122963eb84d1Schristos if ($next =~ /\}/) { # split on 2 lines 123063eb84d1Schristos $nodes .= " $`"; 123163eb84d1Schristos $after = $'; 123263eb84d1Schristos } else { 123363eb84d1Schristos $nodes .= " $next"; 123463eb84d1Schristos $next = shift(@lines); 123563eb84d1Schristos $next = &substitute_style($next); 123663eb84d1Schristos chop($nodes); 123763eb84d1Schristos if ($next =~ /\}/) { # split on 3 lines 123863eb84d1Schristos $nodes .= " $`"; 123963eb84d1Schristos $after = $'; 124063eb84d1Schristos } else { 124163eb84d1Schristos warn "$ERROR Bad xref (no ending }): $_"; 124263eb84d1Schristos $_ = "$before$;0xref\{$nodes$after"; 124363eb84d1Schristos unshift(@lines, $next); 124463eb84d1Schristos next; # while xref 124563eb84d1Schristos } 124663eb84d1Schristos } 124763eb84d1Schristos } 124863eb84d1Schristos $nodes =~ s/\s+/ /g; # remove useless spaces 124963eb84d1Schristos @args = split(/\s*,\s*/, $nodes); 125063eb84d1Schristos $node = $args[0]; # the node is always the first arg 125163eb84d1Schristos &normalise_node($node); 125263eb84d1Schristos $sec = $node2sec{$node}; 125363eb84d1Schristos if (@args == 5) { # reference to another manual 125463eb84d1Schristos $sec = $args[2] || $node; 125563eb84d1Schristos $man = $args[4] || $args[3]; 125663eb84d1Schristos $_ = "${before}${type}section ‘$sec’ in \@cite{$man}$after"; 125763eb84d1Schristos } elsif ($type =~ /Info/) { # inforef 125863eb84d1Schristos warn "$ERROR Wrong number of arguments: $_" unless @args == 3; 125963eb84d1Schristos ($nn, $_, $in) = @args; 126063eb84d1Schristos $_ = "${before}${type} file ‘$in’, node ‘$nn’$after"; 126163eb84d1Schristos } elsif ($sec) { 126263eb84d1Schristos $href = $node2href{$node}; 126363eb84d1Schristos $_ = "${before}${type}section " . &anchor('', $href, $sec) . $after; 126463eb84d1Schristos } else { 126563eb84d1Schristos warn "$ERROR Undefined node ($node): $_"; 126663eb84d1Schristos $_ = "$before$;0xref{$nodes}$after"; 126763eb84d1Schristos } 126863eb84d1Schristos } 126963eb84d1Schristos # 127063eb84d1Schristos # try to guess bibliography references or glossary terms 127163eb84d1Schristos # 127263eb84d1Schristos unless (/^<H\d><A NAME=\"SEC\d/) { 127363eb84d1Schristos if ($use_bibliography) { 127463eb84d1Schristos $done = ''; 127563eb84d1Schristos while (/$BIBRE/o) { 127663eb84d1Schristos ($pre, $what, $post) = ($`, $&, $'); 127763eb84d1Schristos $href = $bib2href{$what}; 127863eb84d1Schristos if (defined($href) && $post !~ /^[^<]*<\/A>/) { 127963eb84d1Schristos $done .= $pre . &anchor('', $href, $what); 128063eb84d1Schristos } else { 128163eb84d1Schristos $done .= "$pre$what"; 128263eb84d1Schristos } 128363eb84d1Schristos $_ = $post; 128463eb84d1Schristos } 128563eb84d1Schristos $_ = $done . $_; 128663eb84d1Schristos } 128763eb84d1Schristos if ($use_glossary) { 128863eb84d1Schristos $done = ''; 128963eb84d1Schristos while (/\b\w+\b/) { 129063eb84d1Schristos ($pre, $what, $post) = ($`, $&, $'); 129163eb84d1Schristos $entry = $what; 129263eb84d1Schristos $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/; 129363eb84d1Schristos $href = $gloss2href{$entry}; 129463eb84d1Schristos if (defined($href) && $post !~ /^[^<]*<\/A>/) { 129563eb84d1Schristos $done .= $pre . &anchor('', $href, $what); 129663eb84d1Schristos } else { 129763eb84d1Schristos $done .= "$pre$what"; 129863eb84d1Schristos } 129963eb84d1Schristos $_ = $post; 130063eb84d1Schristos } 130163eb84d1Schristos $_ = $done . $_; 130263eb84d1Schristos } 130363eb84d1Schristos } 130463eb84d1Schristos # otherwise 130563eb84d1Schristos push(@lines2, $_); 130663eb84d1Schristos} 130763eb84d1Schristosprint "# end of pass 2\n" if $verbose; 130863eb84d1Schristos 130963eb84d1Schristos# 131063eb84d1Schristos# split style substitutions 131163eb84d1Schristos# 131263eb84d1Schristoswhile (@lines2) { 131363eb84d1Schristos $_ = shift(@lines2); 131463eb84d1Schristos # 131563eb84d1Schristos # special case (protected sections) 131663eb84d1Schristos # 131763eb84d1Schristos if (/^$PROTECTTAG/o) { 131863eb84d1Schristos push(@lines3, $_); 131963eb84d1Schristos next; 132063eb84d1Schristos } 132163eb84d1Schristos # 132263eb84d1Schristos # split style substitutions 132363eb84d1Schristos # 132463eb84d1Schristos $old = ''; 132563eb84d1Schristos while ($old ne $_) { 132663eb84d1Schristos $old = $_; 132763eb84d1Schristos if (/\@(\w+|"|\~|,|\^)\{/) { 132863eb84d1Schristos ($before, $style, $after) = ($`, $1, $'); 132963eb84d1Schristos if (defined($style_map{$style})) { 133063eb84d1Schristos $_ = $after; 133163eb84d1Schristos $text = ''; 133263eb84d1Schristos $after = ''; 133363eb84d1Schristos $failed = 1; 133463eb84d1Schristos while (@lines2) { 133563eb84d1Schristos if (/\}/) { 133663eb84d1Schristos $text .= $`; 133763eb84d1Schristos $after = $'; 133863eb84d1Schristos $failed = 0; 133963eb84d1Schristos last; 134063eb84d1Schristos } else { 134163eb84d1Schristos $text .= $_; 134263eb84d1Schristos $_ = shift(@lines2); 134363eb84d1Schristos } 134463eb84d1Schristos } 134563eb84d1Schristos if ($failed) { 134663eb84d1Schristos die "* Bad syntax (\@$style) after: $before\n"; 134763eb84d1Schristos } else { 134863eb84d1Schristos $text = &apply_style($style, $text); 134963eb84d1Schristos $_ = "$before$text$after"; 135063eb84d1Schristos } 135163eb84d1Schristos } 135263eb84d1Schristos } 135363eb84d1Schristos } 135463eb84d1Schristos # otherwise 135563eb84d1Schristos push(@lines3, $_); 135663eb84d1Schristos} 135763eb84d1Schristosprint "# end of pass 3\n" if $verbose; 135863eb84d1Schristos 135963eb84d1Schristos#+++############################################################################ 136063eb84d1Schristos# # 136163eb84d1Schristos# Pass 4: foot notes, final cleanup # 136263eb84d1Schristos# # 136363eb84d1Schristos#---############################################################################ 136463eb84d1Schristos 136563eb84d1Schristos@foot_lines = (); # footnotes 136663eb84d1Schristos@doc_lines = (); # final document 136763eb84d1Schristos$end_of_para = 0; # true if last line is <P> 136863eb84d1Schristos 136963eb84d1Schristoswhile (@lines3) { 137063eb84d1Schristos $_ = shift(@lines3); 137163eb84d1Schristos # 137263eb84d1Schristos # special case (protected sections) 137363eb84d1Schristos # 137463eb84d1Schristos if (/^$PROTECTTAG/o) { 137563eb84d1Schristos push(@doc_lines, $_); 137663eb84d1Schristos $end_of_para = 0; 137763eb84d1Schristos next; 137863eb84d1Schristos } 137963eb84d1Schristos # 138063eb84d1Schristos # footnotes 138163eb84d1Schristos # 138263eb84d1Schristos while (/\@footnote([^\{\s]+)\{/) { 138363eb84d1Schristos ($before, $d, $after) = ($`, $1, $'); 138463eb84d1Schristos $_ = $after; 138563eb84d1Schristos $text = ''; 138663eb84d1Schristos $after = ''; 138763eb84d1Schristos $failed = 1; 138863eb84d1Schristos while (@lines3) { 138963eb84d1Schristos if (/\}/) { 139063eb84d1Schristos $text .= $`; 139163eb84d1Schristos $after = $'; 139263eb84d1Schristos $failed = 0; 139363eb84d1Schristos last; 139463eb84d1Schristos } else { 139563eb84d1Schristos $text .= $_; 139663eb84d1Schristos $_ = shift(@lines3); 139763eb84d1Schristos } 139863eb84d1Schristos } 139963eb84d1Schristos if ($failed) { 140063eb84d1Schristos die "* Bad syntax (\@footnote) after: $before\n"; 140163eb84d1Schristos } else { 140263eb84d1Schristos $foot_num++; 140363eb84d1Schristos $docid = "DOCF$foot_num"; 140463eb84d1Schristos $footid = "FOOT$foot_num"; 140563eb84d1Schristos $foot = "($foot_num)"; 140663eb84d1Schristos push(@foot_lines, "<H3>" . &anchor($footid, "$d#$docid", $foot) . "</H3>\n"); 140763eb84d1Schristos $text = "<P>$text" unless $text =~ /^\s*<P>/; 140863eb84d1Schristos push(@foot_lines, "$text\n"); 140963eb84d1Schristos $_ = $before . &anchor($docid, "$docu_foot#$footid", $foot) . $after; 141063eb84d1Schristos } 141163eb84d1Schristos } 141263eb84d1Schristos # 141363eb84d1Schristos # remove unnecessary <P> 141463eb84d1Schristos # 141563eb84d1Schristos if (/^\s*<P>\s*$/) { 141663eb84d1Schristos next if $end_of_para++; 141763eb84d1Schristos } else { 141863eb84d1Schristos $end_of_para = 0; 141963eb84d1Schristos } 142063eb84d1Schristos # otherwise 142163eb84d1Schristos push(@doc_lines, $_); 142263eb84d1Schristos} 142363eb84d1Schristosprint "# end of pass 4\n" if $verbose; 142463eb84d1Schristos 142563eb84d1Schristos#+++############################################################################ 142663eb84d1Schristos# # 142763eb84d1Schristos# Pass 5: print things # 142863eb84d1Schristos# # 142963eb84d1Schristos#---############################################################################ 143063eb84d1Schristos 143163eb84d1Schristos$header = <<EOT; 143263eb84d1Schristos<!-- This HTML file has been created by $THISPROG 143363eb84d1Schristos from $docu on $TODAY --> 143463eb84d1SchristosEOT 143563eb84d1Schristos 143663eb84d1Schristos$full_title = $value{'_title'} || $value{'_settitle'} || "Untitled Document"; 143763eb84d1Schristos$title = $value{'_settitle'} || $full_title; 143863eb84d1Schristos$_ = &substitute_style($full_title); 143963eb84d1Schristos&unprotect_texi; 144063eb84d1Schristoss/\n$//; # rmv last \n (if any) 144163eb84d1Schristos$full_title = "<H1>" . join("</H1>\n<H1>", split(/\n/, $_)) . "</H1>\n"; 144263eb84d1Schristos 144363eb84d1Schristos# 144463eb84d1Schristos# print ToC 144563eb84d1Schristos# 144663eb84d1Schristosif (!$monolithic && @toc_lines) { 144763eb84d1Schristos if (open(FILE, "> $docu_toc")) { 144863eb84d1Schristos print "# creating $docu_toc...\n" if $verbose; 144963eb84d1Schristos &print_toplevel_header("$title - Table of Contents"); 145063eb84d1Schristos &print_ruler; 145163eb84d1Schristos &print(*toc_lines, FILE); 145263eb84d1Schristos &print_toplevel_footer; 145363eb84d1Schristos close(FILE); 145463eb84d1Schristos } else { 145563eb84d1Schristos warn "$ERROR Can't write to $docu_toc: $!\n"; 145663eb84d1Schristos } 145763eb84d1Schristos} 145863eb84d1Schristos 145963eb84d1Schristos# 146063eb84d1Schristos# print footnotes 146163eb84d1Schristos# 146263eb84d1Schristosif (!$monolithic && @foot_lines) { 146363eb84d1Schristos if (open(FILE, "> $docu_foot")) { 146463eb84d1Schristos print "# creating $docu_foot...\n" if $verbose; 146563eb84d1Schristos &print_toplevel_header("$title - Footnotes"); 146663eb84d1Schristos &print_ruler; 146763eb84d1Schristos &print(*foot_lines, FILE); 146863eb84d1Schristos &print_toplevel_footer; 146963eb84d1Schristos close(FILE); 147063eb84d1Schristos } else { 147163eb84d1Schristos warn "$ERROR Can't write to $docu_foot: $!\n"; 147263eb84d1Schristos } 147363eb84d1Schristos} 147463eb84d1Schristos 147563eb84d1Schristos# 147663eb84d1Schristos# print document 147763eb84d1Schristos# 147863eb84d1Schristosif ($split_chapter || $split_node) { # split 147963eb84d1Schristos $doc_num = 0; 148063eb84d1Schristos $last_num = scalar(@sections); 148163eb84d1Schristos $first_doc = &doc_name(1); 148263eb84d1Schristos $last_doc = &doc_name($last_num); 148363eb84d1Schristos while (@sections) { 148463eb84d1Schristos $section = shift(@sections); 148563eb84d1Schristos &next_doc; 148663eb84d1Schristos if (open(FILE, "> $docu_doc")) { 148763eb84d1Schristos print "# creating $docu_doc...\n" if $verbose; 148863eb84d1Schristos &print_header("$title - $section"); 148963eb84d1Schristos $prev_doc = ($doc_num == 1 ? undef : &doc_name($doc_num - 1)); 149063eb84d1Schristos $next_doc = ($doc_num == $last_num ? undef : &doc_name($doc_num + 1)); 149163eb84d1Schristos $navigation = "Go to the "; 149263eb84d1Schristos $navigation .= ($prev_doc ? &anchor('', $first_doc, "first") : "first"); 149363eb84d1Schristos $navigation .= ", "; 149463eb84d1Schristos $navigation .= ($prev_doc ? &anchor('', $prev_doc, "previous") : "previous"); 149563eb84d1Schristos $navigation .= ", "; 149663eb84d1Schristos $navigation .= ($next_doc ? &anchor('', $next_doc, "next") : "next"); 149763eb84d1Schristos $navigation .= ", "; 149863eb84d1Schristos $navigation .= ($next_doc ? &anchor('', $last_doc, "last") : "last"); 149963eb84d1Schristos $navigation .= " section, " . &anchor('', $docu_toc, "table of contents") . ".\n"; 150063eb84d1Schristos print FILE $navigation; 150163eb84d1Schristos &print_ruler; 150263eb84d1Schristos # find corresponding lines 150363eb84d1Schristos @tmp_lines = (); 150463eb84d1Schristos while (@doc_lines) { 150563eb84d1Schristos $_ = shift(@doc_lines); 150663eb84d1Schristos last if ($_ eq $SPLITTAG); 150763eb84d1Schristos push(@tmp_lines, $_); 150863eb84d1Schristos } 150963eb84d1Schristos &print(*tmp_lines, FILE); 151063eb84d1Schristos &print_ruler; 151163eb84d1Schristos print FILE $navigation; 151263eb84d1Schristos &print_footer; 151363eb84d1Schristos close(FILE); 151463eb84d1Schristos } else { 151563eb84d1Schristos warn "$ERROR Can't write to $docu_doc: $!\n"; 151663eb84d1Schristos } 151763eb84d1Schristos } 151863eb84d1Schristos} else { # not split 151963eb84d1Schristos if (open(FILE, "> $docu_doc")) { 152063eb84d1Schristos print "# creating $docu_doc...\n" if $verbose; 152163eb84d1Schristos if ($monolithic || !@toc_lines) { 152263eb84d1Schristos &print_toplevel_header($title); 152363eb84d1Schristos } else { 152463eb84d1Schristos &print_header($title); 152563eb84d1Schristos print FILE $full_title; 152663eb84d1Schristos } 152763eb84d1Schristos if ($monolithic && @toc_lines) { 152863eb84d1Schristos &print_ruler; 152963eb84d1Schristos print FILE "<H1>Table of Contents</H1>\n"; 153063eb84d1Schristos &print(*toc_lines, FILE); 153163eb84d1Schristos } 153263eb84d1Schristos &print_ruler; 153363eb84d1Schristos &print(*doc_lines, FILE); 153463eb84d1Schristos if ($monolithic && @foot_lines) { 153563eb84d1Schristos &print_ruler; 153663eb84d1Schristos print FILE "<H1>Footnotes</H1>\n"; 153763eb84d1Schristos &print(*foot_lines, FILE); 153863eb84d1Schristos } 153963eb84d1Schristos if ($monolithic || !@toc_lines) { 154063eb84d1Schristos &print_toplevel_footer; 154163eb84d1Schristos } else { 154263eb84d1Schristos &print_footer; 154363eb84d1Schristos } 154463eb84d1Schristos close(FILE); 154563eb84d1Schristos } else { 154663eb84d1Schristos warn "$ERROR Can't write to $docu_doc: $!\n"; 154763eb84d1Schristos } 154863eb84d1Schristos} 154963eb84d1Schristos 155063eb84d1Schristosprint "# that's all folks\n" if $verbose; 155163eb84d1Schristos 155263eb84d1Schristos#+++############################################################################ 155363eb84d1Schristos# # 155463eb84d1Schristos# Low level functions # 155563eb84d1Schristos# # 155663eb84d1Schristos#---############################################################################ 155763eb84d1Schristos 155863eb84d1Schristossub update_sec_num { 155963eb84d1Schristos local($name, $level) = @_; 156063eb84d1Schristos 156163eb84d1Schristos $level--; # here we start at 0 156263eb84d1Schristos if ($name =~ /^appendix/) { 156363eb84d1Schristos # appendix style 1564*99c2fe91Schristos if (@appendix_sec_num) { 156563eb84d1Schristos &incr_sec_num($level, @appendix_sec_num); 156663eb84d1Schristos } else { 156763eb84d1Schristos @appendix_sec_num = ('A', 0, 0, 0); 156863eb84d1Schristos } 156963eb84d1Schristos return(join('.', @appendix_sec_num[0..$level])); 157063eb84d1Schristos } else { 157163eb84d1Schristos # normal style 1572*99c2fe91Schristos if (@normal_sec_num) { 157363eb84d1Schristos &incr_sec_num($level, @normal_sec_num); 157463eb84d1Schristos } else { 157563eb84d1Schristos @normal_sec_num = (1, 0, 0, 0); 157663eb84d1Schristos } 157763eb84d1Schristos return(join('.', @normal_sec_num[0..$level])); 157863eb84d1Schristos } 157963eb84d1Schristos} 158063eb84d1Schristos 158163eb84d1Schristossub incr_sec_num { 158263eb84d1Schristos local($level, $l); 158363eb84d1Schristos $level = shift(@_); 158463eb84d1Schristos $_[$level]++; 158563eb84d1Schristos foreach $l ($level+1 .. 3) { 158663eb84d1Schristos $_[$l] = 0; 158763eb84d1Schristos } 158863eb84d1Schristos} 158963eb84d1Schristos 159063eb84d1Schristossub check { 159163eb84d1Schristos local($_, %seen, %context, $before, $match, $after); 159263eb84d1Schristos 159363eb84d1Schristos while (<>) { 159463eb84d1Schristos if (/\@(\*|\.|\:|\@|\{|\})/) { 159563eb84d1Schristos $seen{$&}++; 159663eb84d1Schristos $context{$&} .= "> $_" if $verbose; 159763eb84d1Schristos $_ = "$`XX$'"; 159863eb84d1Schristos redo; 159963eb84d1Schristos } 160063eb84d1Schristos if (/\@(\w+)/) { 160163eb84d1Schristos ($before, $match, $after) = ($`, $&, $'); 160263eb84d1Schristos if ($before =~ /\b[\w-]+$/ && $after =~ /^[\w-.]*\b/) { # e-mail address 160363eb84d1Schristos $seen{'e-mail address'}++; 160463eb84d1Schristos $context{'e-mail address'} .= "> $_" if $verbose; 160563eb84d1Schristos } else { 160663eb84d1Schristos $seen{$match}++; 160763eb84d1Schristos $context{$match} .= "> $_" if $verbose; 160863eb84d1Schristos } 160963eb84d1Schristos $match =~ s/^\@/X/; 161063eb84d1Schristos $_ = "$before$match$after"; 161163eb84d1Schristos redo; 161263eb84d1Schristos } 161363eb84d1Schristos } 161463eb84d1Schristos 161563eb84d1Schristos foreach (sort(keys(%seen))) { 161663eb84d1Schristos if ($verbose) { 161763eb84d1Schristos print "$_\n"; 161863eb84d1Schristos print $context{$_}; 161963eb84d1Schristos } else { 162063eb84d1Schristos print "$_ ($seen{$_})\n"; 162163eb84d1Schristos } 162263eb84d1Schristos } 162363eb84d1Schristos} 162463eb84d1Schristos 162563eb84d1Schristossub open { 162663eb84d1Schristos local($name) = @_; 162763eb84d1Schristos 162863eb84d1Schristos ++$fh_name; 162963eb84d1Schristos if (open($fh_name, $name)) { 163063eb84d1Schristos unshift(@fhs, $fh_name); 163163eb84d1Schristos } else { 163263eb84d1Schristos warn "$ERROR Can't read file $name: $!\n"; 163363eb84d1Schristos } 163463eb84d1Schristos} 163563eb84d1Schristos 163663eb84d1Schristossub init_input { 163763eb84d1Schristos @fhs = (); # hold the file handles to read 163863eb84d1Schristos @input_spool = (); # spooled lines to read 163963eb84d1Schristos $fh_name = 'FH000'; 164063eb84d1Schristos &open($docu); 164163eb84d1Schristos} 164263eb84d1Schristos 164363eb84d1Schristossub next_line { 164463eb84d1Schristos local($fh, $line); 164563eb84d1Schristos 164663eb84d1Schristos if (@input_spool) { 164763eb84d1Schristos $line = shift(@input_spool); 164863eb84d1Schristos return($line); 164963eb84d1Schristos } 165063eb84d1Schristos while (@fhs) { 165163eb84d1Schristos $fh = $fhs[0]; 165263eb84d1Schristos $line = <$fh>; 165363eb84d1Schristos return($line) if $line; 165463eb84d1Schristos close($fh); 165563eb84d1Schristos shift(@fhs); 165663eb84d1Schristos } 165763eb84d1Schristos return(undef); 165863eb84d1Schristos} 165963eb84d1Schristos 166063eb84d1Schristos# used in pass 1, use &next_line 166163eb84d1Schristossub skip_until { 166263eb84d1Schristos local($tag) = @_; 166363eb84d1Schristos local($_); 166463eb84d1Schristos 166563eb84d1Schristos while ($_ = &next_line) { 166663eb84d1Schristos return if /^\@end\s+$tag\s*$/; 166763eb84d1Schristos } 166863eb84d1Schristos die "* Failed to find '$tag' after: " . $lines[$#lines]; 166963eb84d1Schristos} 167063eb84d1Schristos 167163eb84d1Schristos# 167263eb84d1Schristos# HTML stacking to have a better HTML output 167363eb84d1Schristos# 167463eb84d1Schristos 167563eb84d1Schristossub html_reset { 167663eb84d1Schristos @html_stack = ('html'); 167763eb84d1Schristos $html_element = 'body'; 167863eb84d1Schristos} 167963eb84d1Schristos 168063eb84d1Schristossub html_push { 168163eb84d1Schristos local($what) = @_; 168263eb84d1Schristos push(@html_stack, $html_element); 168363eb84d1Schristos $html_element = $what; 168463eb84d1Schristos} 168563eb84d1Schristos 168663eb84d1Schristossub html_push_if { 168763eb84d1Schristos local($what) = @_; 168863eb84d1Schristos push(@html_stack, $html_element) 168963eb84d1Schristos if ($html_element && $html_element ne 'P'); 169063eb84d1Schristos $html_element = $what; 169163eb84d1Schristos} 169263eb84d1Schristos 169363eb84d1Schristossub html_pop { 169463eb84d1Schristos $html_element = pop(@html_stack); 169563eb84d1Schristos} 169663eb84d1Schristos 169763eb84d1Schristossub html_pop_if { 169863eb84d1Schristos local($elt); 169963eb84d1Schristos 170063eb84d1Schristos if (@_) { 170163eb84d1Schristos foreach $elt (@_) { 170263eb84d1Schristos if ($elt eq $html_element) { 170363eb84d1Schristos $html_element = pop(@html_stack) if @html_stack; 170463eb84d1Schristos last; 170563eb84d1Schristos } 170663eb84d1Schristos } 170763eb84d1Schristos } else { 170863eb84d1Schristos $html_element = pop(@html_stack) if @html_stack; 170963eb84d1Schristos } 171063eb84d1Schristos} 171163eb84d1Schristos 171263eb84d1Schristossub html_debug { 171363eb84d1Schristos local($what, $line) = @_; 171463eb84d1Schristos return("<!-- $line @html_stack, $html_element -->$what") 171563eb84d1Schristos if $debug & $DEBUG_HTML; 171663eb84d1Schristos return($what); 171763eb84d1Schristos} 171863eb84d1Schristos 171963eb84d1Schristos# to debug the output... 172063eb84d1Schristossub debug { 172163eb84d1Schristos local($what, $line) = @_; 172263eb84d1Schristos return("<!-- $line -->$what") 172363eb84d1Schristos if $debug & $DEBUG_HTML; 172463eb84d1Schristos return($what); 172563eb84d1Schristos} 172663eb84d1Schristos 172763eb84d1Schristossub normalise_node { 172863eb84d1Schristos $_[0] =~ s/\s+/ /g; 172963eb84d1Schristos $_[0] =~ s/ $//; 173063eb84d1Schristos $_[0] =~ s/^ //; 173163eb84d1Schristos} 173263eb84d1Schristos 173363eb84d1Schristossub menu_entry { 173463eb84d1Schristos local($entry, $node, $descr) = @_; 173563eb84d1Schristos local($href); 173663eb84d1Schristos 173763eb84d1Schristos &normalise_node($node); 173863eb84d1Schristos $href = $node2href{$node}; 173963eb84d1Schristos if ($href) { 174063eb84d1Schristos $descr =~ s/^\s+//; 174163eb84d1Schristos $descr = ": $descr" if $descr; 174263eb84d1Schristos push(@lines2, "<LI>" . &anchor('', $href, $entry) . "$descr\n"); 174363eb84d1Schristos } else { 174463eb84d1Schristos warn "$ERROR Undefined node ($node): $_"; 174563eb84d1Schristos } 174663eb84d1Schristos} 174763eb84d1Schristos 174863eb84d1Schristossub do_ctrl { "^$_[0]" } 174963eb84d1Schristos 175063eb84d1Schristossub do_email { 175163eb84d1Schristos local($addr, $text) = split(/,\s*/, $_[0]); 175263eb84d1Schristos 175363eb84d1Schristos $text = $addr unless $text; 175463eb84d1Schristos &anchor('', "mailto:$addr", $text); 175563eb84d1Schristos} 175663eb84d1Schristos 175763eb84d1Schristossub do_sc { "\U$_[0]\E" } 175863eb84d1Schristos 175963eb84d1Schristossub do_uref { 176063eb84d1Schristos local($url, $text) = split(/,\s*/, $_[0]); 176163eb84d1Schristos 176263eb84d1Schristos $text = $url unless $text; 176363eb84d1Schristos &anchor('', $url, $text); 176463eb84d1Schristos} 176563eb84d1Schristos 176663eb84d1Schristossub do_url { &anchor('', $_[0], $_[0]) } 176763eb84d1Schristos 176863eb84d1Schristossub do_diaeresis { return "&$_[0]uml;"; } 176963eb84d1Schristossub do_acuteaccent { return "&$_[0]acute;"; } 177063eb84d1Schristossub do_graveaccent { return "&$_[0]grave;"; } 177163eb84d1Schristossub do_tildeaccent { return "&$_[0]tilde;"; } 177263eb84d1Schristossub do_cedilla { return "&$_[0]cedil;"; } 177363eb84d1Schristossub do_circumflex { return "&$_[0]circ;"; } 177463eb84d1Schristos 177563eb84d1Schristossub apply_style { 177663eb84d1Schristos local($texi_style, $text) = @_; 177763eb84d1Schristos local($style); 177863eb84d1Schristos 177963eb84d1Schristos $style = $style_map{$texi_style}; 178063eb84d1Schristos if (defined($style)) { # known style 178163eb84d1Schristos if ($style =~ /^\"/) { # add quotes 178263eb84d1Schristos $style = $'; 178363eb84d1Schristos $text = "\‘$text\’"; 178463eb84d1Schristos } 178563eb84d1Schristos if ($style =~ /^\&/) { # custom 178663eb84d1Schristos $style = $'; 178763eb84d1Schristos $text = &$style($text); 178863eb84d1Schristos } elsif ($style) { # good style 178963eb84d1Schristos $text = "<$style>$text</$style>"; 179063eb84d1Schristos } else { # no style 179163eb84d1Schristos } 179263eb84d1Schristos } else { # unknown style 179363eb84d1Schristos $text = undef; 179463eb84d1Schristos } 179563eb84d1Schristos return($text); 179663eb84d1Schristos} 179763eb84d1Schristos 179863eb84d1Schristos# remove Texinfo styles 179963eb84d1Schristossub remove_style { 180063eb84d1Schristos local($_) = @_; 180163eb84d1Schristos s/\@\w+{([^\{\}]+)}/$1/g; 180263eb84d1Schristos return($_); 180363eb84d1Schristos} 180463eb84d1Schristos 180563eb84d1Schristossub substitute_style { 180663eb84d1Schristos local($_) = @_; 180763eb84d1Schristos local($changed, $done, $style, $text); 180863eb84d1Schristos 180963eb84d1Schristos $changed = 1; 181063eb84d1Schristos while ($changed) { 181163eb84d1Schristos $changed = 0; 181263eb84d1Schristos $done = ''; 181363eb84d1Schristos while (/\@(\w+|"|\~|,|\^){([^\{\}]+)}/) { 181463eb84d1Schristos $text = &apply_style($1, $2); 181563eb84d1Schristos if ($text) { 181663eb84d1Schristos $_ = "$`$text$'"; 181763eb84d1Schristos $changed = 1; 181863eb84d1Schristos } else { 181963eb84d1Schristos $done .= "$`\@$1"; 182063eb84d1Schristos $_ = "{$2}$'"; 182163eb84d1Schristos } 182263eb84d1Schristos } 182363eb84d1Schristos $_ = $done . $_; 182463eb84d1Schristos } 182563eb84d1Schristos return($_); 182663eb84d1Schristos} 182763eb84d1Schristos 182863eb84d1Schristossub anchor { 182963eb84d1Schristos local($name, $href, $text, $newline) = @_; 183063eb84d1Schristos local($result); 183163eb84d1Schristos 183263eb84d1Schristos $result = "<A"; 183363eb84d1Schristos $result .= " NAME=\"$name\"" if $name; 183463eb84d1Schristos $result .= " HREF=\"$href\"" if $href; 183563eb84d1Schristos $result .= ">$text</A>"; 183663eb84d1Schristos $result .= "\n" if $newline; 183763eb84d1Schristos return($result); 183863eb84d1Schristos} 183963eb84d1Schristos 184063eb84d1Schristossub pretty_date { 184163eb84d1Schristos local(@MoY, $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst); 184263eb84d1Schristos 184363eb84d1Schristos @MoY = ('January', 'Febuary', 'March', 'April', 'May', 'June', 184463eb84d1Schristos 'July', 'August', 'September', 'October', 'November', 'December'); 184563eb84d1Schristos ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time); 184663eb84d1Schristos $year += ($year < 70) ? 2000 : 1900; 184763eb84d1Schristos return("$mday $MoY[$mon] $year"); 184863eb84d1Schristos} 184963eb84d1Schristos 185063eb84d1Schristossub doc_name { 185163eb84d1Schristos local($num) = @_; 185263eb84d1Schristos 185363eb84d1Schristos return("${docu_name}_$num.html"); 185463eb84d1Schristos} 185563eb84d1Schristos 185663eb84d1Schristossub next_doc { 185763eb84d1Schristos $docu_doc = &doc_name(++$doc_num); 185863eb84d1Schristos} 185963eb84d1Schristos 186063eb84d1Schristossub print { 186163eb84d1Schristos local(*lines, $fh) = @_; 186263eb84d1Schristos local($_); 186363eb84d1Schristos 186463eb84d1Schristos while (@lines) { 186563eb84d1Schristos $_ = shift(@lines); 186663eb84d1Schristos if (/^$PROTECTTAG/o) { 186763eb84d1Schristos $_ = $tag2pro{$_}; 186863eb84d1Schristos } else { 186963eb84d1Schristos &unprotect_texi; 187063eb84d1Schristos } 187163eb84d1Schristos print $fh $_; 187263eb84d1Schristos } 187363eb84d1Schristos} 187463eb84d1Schristos 187563eb84d1Schristossub print_ruler { 187663eb84d1Schristos print FILE "<P><HR><P>\n"; 187763eb84d1Schristos} 187863eb84d1Schristos 187963eb84d1Schristossub print_header { 188063eb84d1Schristos local($_); 188163eb84d1Schristos 188263eb84d1Schristos # clean the title 188363eb84d1Schristos $_ = &remove_style($_[0]); 188463eb84d1Schristos &unprotect_texi; 188563eb84d1Schristos # print the header 188663eb84d1Schristos if ($doctype eq 'html2') { 188763eb84d1Schristos print FILE $html2_doctype; 188863eb84d1Schristos } elsif ($doctype) { 188963eb84d1Schristos print FILE $doctype; 189063eb84d1Schristos } 189163eb84d1Schristos print FILE <<EOT; 189263eb84d1Schristos<HTML> 189363eb84d1Schristos<HEAD> 189463eb84d1Schristos$header 189563eb84d1Schristos<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"> 189663eb84d1Schristos<TITLE>$_</TITLE> 189763eb84d1Schristos</HEAD> 189863eb84d1Schristos<BODY> 189963eb84d1SchristosEOT 190063eb84d1Schristos} 190163eb84d1Schristos 190263eb84d1Schristossub print_toplevel_header { 190363eb84d1Schristos local($_); 190463eb84d1Schristos 190563eb84d1Schristos &print_header; # pass given arg... 190663eb84d1Schristos print FILE $full_title; 190763eb84d1Schristos if ($value{'_subtitle'}) { 190863eb84d1Schristos $value{'_subtitle'} =~ s/\n+$//; 190963eb84d1Schristos foreach (split(/\n/, $value{'_subtitle'})) { 191063eb84d1Schristos $_ = &substitute_style($_); 191163eb84d1Schristos &unprotect_texi; 191263eb84d1Schristos print FILE "<H2>$_</H2>\n"; 191363eb84d1Schristos } 191463eb84d1Schristos } 191563eb84d1Schristos if ($value{'_author'}) { 191663eb84d1Schristos $value{'_author'} =~ s/\n+$//; 191763eb84d1Schristos foreach (split(/\n/, $value{'_author'})) { 191863eb84d1Schristos $_ = &substitute_style($_); 191963eb84d1Schristos &unprotect_texi; 192063eb84d1Schristos s/[\w.-]+\@[\w.-]+/<A HREF="mailto:$&">$&<\/A>/g; 192163eb84d1Schristos print FILE "<ADDRESS>$_</ADDRESS>\n"; 192263eb84d1Schristos } 192363eb84d1Schristos } 192463eb84d1Schristos print FILE "<P>\n"; 192563eb84d1Schristos} 192663eb84d1Schristos 192763eb84d1Schristossub print_footer { 192863eb84d1Schristos print FILE <<EOT; 192963eb84d1Schristos</BODY> 193063eb84d1Schristos</HTML> 193163eb84d1SchristosEOT 193263eb84d1Schristos} 193363eb84d1Schristos 193463eb84d1Schristossub print_toplevel_footer { 193563eb84d1Schristos &print_ruler; 193663eb84d1Schristos print FILE <<EOT; 193763eb84d1SchristosThis document was generated on $TODAY using the 193863eb84d1Schristos<A HREF=\"$HOMEPAGE\">texi2html</A> 193963eb84d1Schristostranslator version 1.52b.</P> 194063eb84d1SchristosEOT 194163eb84d1Schristos &print_footer; 194263eb84d1Schristos} 194363eb84d1Schristos 194463eb84d1Schristossub protect_texi { 194563eb84d1Schristos # protect @ { } ` ' 194663eb84d1Schristos s/\@\@/$;0/go; 194763eb84d1Schristos s/\@\{/$;1/go; 194863eb84d1Schristos s/\@\}/$;2/go; 194963eb84d1Schristos s/\@\`/$;3/go; 195063eb84d1Schristos s/\@\'/$;4/go; 195163eb84d1Schristos} 195263eb84d1Schristos 195363eb84d1Schristossub protect_html { 195463eb84d1Schristos local($what) = @_; 195563eb84d1Schristos # protect & < > 195663eb84d1Schristos $what =~ s/\&/\&\#38;/g; 195763eb84d1Schristos $what =~ s/\</\&\#60;/g; 195863eb84d1Schristos $what =~ s/\>/\&\#62;/g; 195963eb84d1Schristos # but recognize some HTML things 196063eb84d1Schristos $what =~ s/\&\#60;\/A\&\#62;/<\/A>/g; # </A> 196163eb84d1Schristos $what =~ s/\&\#60;A ([^\&]+)\&\#62;/<A $1>/g; # <A [^&]+> 196263eb84d1Schristos $what =~ s/\&\#60;IMG ([^\&]+)\&\#62;/<IMG $1>/g; # <IMG [^&]+> 196363eb84d1Schristos return($what); 196463eb84d1Schristos} 196563eb84d1Schristos 196663eb84d1Schristossub unprotect_texi { 196763eb84d1Schristos s/$;0/\@/go; 196863eb84d1Schristos s/$;1/\{/go; 196963eb84d1Schristos s/$;2/\}/go; 197063eb84d1Schristos s/$;3/\`/go; 197163eb84d1Schristos s/$;4/\'/go; 197263eb84d1Schristos} 197363eb84d1Schristos 197463eb84d1Schristossub unprotect_html { 197563eb84d1Schristos local($what) = @_; 197663eb84d1Schristos $what =~ s/\&\#38;/\&/g; 197763eb84d1Schristos $what =~ s/\&\#60;/\</g; 197863eb84d1Schristos $what =~ s/\&\#62;/\>/g; 197963eb84d1Schristos return($what); 198063eb84d1Schristos} 198163eb84d1Schristos 198263eb84d1Schristossub byalpha { 198363eb84d1Schristos $key2alpha{$a} cmp $key2alpha{$b}; 198463eb84d1Schristos} 198563eb84d1Schristos 198663eb84d1Schristos############################################################################## 198763eb84d1Schristos 198863eb84d1Schristos # These next few lines are legal in both Perl and nroff. 198963eb84d1Schristos 199063eb84d1Schristos.00 ; # finish .ig 199163eb84d1Schristos 199263eb84d1Schristos'di \" finish diversion--previous line must be blank 199363eb84d1Schristos.nr nl 0-1 \" fake up transition to first page again 199463eb84d1Schristos.nr % 0 \" start at page 1 199563eb84d1Schristos'; __END__ ############# From here on it's a standard manual page ############ 199663eb84d1Schristos.TH TEXI2HTML 1 "01/05/98" 199763eb84d1Schristos.AT 3 199863eb84d1Schristos.SH NAME 199963eb84d1Schristostexi2html \- a Texinfo to HTML converter 200063eb84d1Schristos.SH SYNOPSIS 200163eb84d1Schristos.B texi2html [options] file 200263eb84d1Schristos.PP 200363eb84d1Schristos.B texi2html -check [-verbose] files 200463eb84d1Schristos.SH DESCRIPTION 200563eb84d1Schristos.I Texi2html 200663eb84d1Schristosconverts the given Texinfo file to a set of HTML files. It tries to handle 200763eb84d1Schristosmost of the Texinfo commands. It creates hypertext links for cross-references, 200863eb84d1Schristosfootnotes... 200963eb84d1Schristos.PP 201063eb84d1SchristosIt also tries to add links from a reference to its corresponding entry in the 201163eb84d1Schristosbibliography (if any). It may also handle a glossary (see the 201263eb84d1Schristos.B \-glossary 201363eb84d1Schristosoption). 201463eb84d1Schristos.PP 201563eb84d1Schristos.I Texi2html 201663eb84d1Schristoscreates several files depending on the contents of the Texinfo file and on 201763eb84d1Schristosthe chosen options (see FILES). 201863eb84d1Schristos.PP 201963eb84d1SchristosThe HTML files created by 202063eb84d1Schristos.I texi2html 202163eb84d1Schristosare closer to TeX than to Info, that's why 202263eb84d1Schristos.I texi2html 202363eb84d1Schristosconverts @ifhtml sections and not @ifinfo or @iftex ones by default. You can 202463eb84d1Schristoschange this with the \-expandinfo or \-expandtex options. 202563eb84d1Schristos.SH OPTIONS 202663eb84d1Schristos.TP 12 202763eb84d1Schristos.B \-check 202863eb84d1SchristosCheck the given file and give the list of all things that may be Texinfo commands. 202963eb84d1SchristosThis may be used to check the output of 203063eb84d1Schristos.I texi2html 203163eb84d1Schristosto find the Texinfo commands that have been left in the HTML file. 203263eb84d1Schristos.TP 203363eb84d1Schristos.B \-expandinfo 203463eb84d1SchristosExpand @ifinfo sections, not @ifhtml ones. 203563eb84d1Schristos.TP 203663eb84d1Schristos.B \-expandtex 203763eb84d1SchristosExpand @iftex sections, not @ifhtml ones. 203863eb84d1Schristos.TP 203963eb84d1Schristos.B \-glossary 204063eb84d1SchristosUse the section named 'Glossary' to build a list of terms and put links in the HTML 204163eb84d1Schristosdocument from each term toward its definition. 204263eb84d1Schristos.TP 204363eb84d1Schristos.B \-invisible \fIname\fP 204463eb84d1SchristosUse \fIname\fP to create invisible destination anchors for index links 204563eb84d1Schristos(you can for instance use the invisible.xbm file shipped with this program). 204663eb84d1SchristosThis is a workaround for a known bug of many WWW browsers, including netscape. 204763eb84d1Schristos.TP 204863eb84d1Schristos.B \-I \fIdir\fP 204963eb84d1SchristosLook also in \fIdir\fP to find included files. 205063eb84d1Schristos.TP 205163eb84d1Schristos.B \-menu 205263eb84d1SchristosShow the Texinfo menus; by default they are ignored. 205363eb84d1Schristos.TP 205463eb84d1Schristos.B \-monolithic 205563eb84d1SchristosOutput only one file, including the table of contents and footnotes. 205663eb84d1Schristos.TP 205763eb84d1Schristos.B \-number 205863eb84d1SchristosNumber the sections. 205963eb84d1Schristos.TP 206063eb84d1Schristos.B \-split_chapter 206163eb84d1SchristosSplit the output into several HTML files (one per main section: 206263eb84d1Schristoschapter, appendix...). 206363eb84d1Schristos.TP 206463eb84d1Schristos.B \-split_node 206563eb84d1SchristosSplit the output into several HTML files (one per node). 206663eb84d1Schristos.TP 206763eb84d1Schristos.B \-usage 206863eb84d1SchristosPrint usage instructions, listing the current available command-line options. 206963eb84d1Schristos.TP 207063eb84d1Schristos.B \-verbose 207163eb84d1SchristosGive a verbose output. Can be used with the 207263eb84d1Schristos.B \-check 207363eb84d1Schristosoption. 207463eb84d1Schristos.PP 207563eb84d1Schristos.SH FILES 207663eb84d1SchristosBy default 207763eb84d1Schristos.I texi2html 207863eb84d1Schristoscreates the following files (foo being the name of the Texinfo file): 207963eb84d1Schristos.TP 16 208063eb84d1Schristos.B foo_toc.html 208163eb84d1SchristosThe table of contents. 208263eb84d1Schristos.TP 208363eb84d1Schristos.B foo.html 208463eb84d1SchristosThe document's contents. 208563eb84d1Schristos.TP 208663eb84d1Schristos.B foo_foot.html 208763eb84d1SchristosThe footnotes (if any). 208863eb84d1Schristos.PP 208963eb84d1SchristosWhen used with the 209063eb84d1Schristos.B \-split 209163eb84d1Schristosoption, it creates several files (one per chapter or node), named 209263eb84d1Schristos.B foo_n.html 209363eb84d1Schristos(n being the indice of the chapter or node), instead of the single 209463eb84d1Schristos.B foo.html 209563eb84d1Schristosfile. 209663eb84d1Schristos.PP 209763eb84d1SchristosWhen used with the 209863eb84d1Schristos.B \-monolithic 209963eb84d1Schristosoption, it creates only one file: 210063eb84d1Schristos.B foo.html 210163eb84d1Schristos.SH VARIABLES 210263eb84d1Schristos.I texi2html 210363eb84d1Schristospredefines the following variables: \fBhtml\fP, \fBtexi2html\fP. 210463eb84d1Schristos.SH ADDITIONAL COMMANDS 210563eb84d1Schristos.I texi2html 210663eb84d1Schristosimplements the following non-Texinfo commands (maybe they are in Texinfo now...): 210763eb84d1Schristos.TP 16 210863eb84d1Schristos.B @ifhtml 210963eb84d1SchristosThis indicates the start of an HTML section, this section will passed through 211063eb84d1Schristoswithout any modification. 211163eb84d1Schristos.TP 211263eb84d1Schristos.B @end ifhtml 211363eb84d1SchristosThis indicates the end of an HTML section. 211463eb84d1Schristos.SH VERSION 211563eb84d1SchristosThis is \fItexi2html\fP version 1.52b, 01/05/98. 211663eb84d1Schristos.PP 211763eb84d1SchristosThe latest version of \fItexi2html\fP can be found in WWW, cf. URL 211863eb84d1Schristoshttp://wwwinfo.cern.ch/dis/texi2html/ 211963eb84d1Schristos.SH AUTHOR 212063eb84d1SchristosThe main author is Lionel Cons, CERN IT/DIS/OSE, Lionel.Cons@cern.ch. 212163eb84d1SchristosMany other people around the net contributed to this program. 212263eb84d1Schristos.SH COPYRIGHT 212363eb84d1SchristosThis program is the intellectual property of the European 212463eb84d1SchristosLaboratory for Particle Physics (known as CERN). No guarantee whatsoever is 212563eb84d1Schristosprovided by CERN. No liability whatsoever is accepted for any loss or damage 212663eb84d1Schristosof any kind resulting from any defect or inaccuracy in this information or 212763eb84d1Schristoscode. 212863eb84d1Schristos.PP 212963eb84d1SchristosCERN, 1211 Geneva 23, Switzerland 213063eb84d1Schristos.SH "SEE ALSO" 213163eb84d1SchristosGNU Texinfo Documentation Format, 213263eb84d1SchristosHyperText Markup Language (HTML), 213363eb84d1SchristosWorld Wide Web (WWW). 213463eb84d1Schristos.SH BUGS 213563eb84d1SchristosThis program does not understand all Texinfo commands (yet). 213663eb84d1Schristos.ex 2137