1946379e7Schristos#!/usr/local/bin/perl 2946379e7Schristos'di '; 3946379e7Schristos'ig 00 '; 4946379e7Schristos#+############################################################################## 5946379e7Schristos# # 6946379e7Schristos# File: texi2html # 7946379e7Schristos# # 8946379e7Schristos# Description: Program to transform most Texinfo documents to HTML # 9946379e7Schristos# # 10946379e7Schristos#-############################################################################## 11946379e7Schristos 12946379e7Schristos# @(#)texi2html 1.52b 01/05/98 Written (mainly) by Lionel Cons, Lionel.Cons@cern.ch 13946379e7Schristos# 1.52a: Use acute accent instead of apostrophe. Add support for ISO-8859-1 14946379e7Schristos# characters with cedilla, circumflex etc. 15946379e7Schristos# 1.52b: Add option -expandtex. Expand @ifhtml by default, not @ifinfo. 16946379e7Schristos# Use Unicode quotation marks instead of grave and acute accents. 17946379e7Schristos# Emit charset=UTF-8 declaration. 18946379e7Schristos 19946379e7Schristos# The man page for this program is included at the end of this file and can be 20946379e7Schristos# viewed using the command 'nroff -man texi2html'. 21946379e7Schristos# Please read the copyright at the end of the man page. 22946379e7Schristos 23946379e7Schristos#+++############################################################################ 24946379e7Schristos# # 25946379e7Schristos# Constants # 26946379e7Schristos# # 27946379e7Schristos#---############################################################################ 28946379e7Schristos 29946379e7Schristos$DEBUG_TOC = 1; 30946379e7Schristos$DEBUG_INDEX = 2; 31946379e7Schristos$DEBUG_BIB = 4; 32946379e7Schristos$DEBUG_GLOSS = 8; 33946379e7Schristos$DEBUG_DEF = 16; 34946379e7Schristos$DEBUG_HTML = 32; 35946379e7Schristos$DEBUG_USER = 64; 36946379e7Schristos 37946379e7Schristos$BIBRE = '\[[\w\/-]+\]'; # RE for a bibliography reference 38946379e7Schristos$FILERE = '[\/\w.+-]+'; # RE for a file name 39946379e7Schristos$VARRE = '[^\s\{\}]+'; # RE for a variable name 40946379e7Schristos$NODERE = '[^@{}:\'`",]+'; # RE for a node name 41946379e7Schristos$NODESRE = '[^@{}:\'`"]+'; # RE for a list of node names 42946379e7Schristos$XREFRE = '[^@{}]+'; # RE for a xref (should use NODERE) 43946379e7Schristos 44946379e7Schristos$ERROR = "***"; # prefix for errors and warnings 45946379e7Schristos$THISPROG = "texi2html 1.52b"; # program name and version 46946379e7Schristos$HOMEPAGE = "http://wwwinfo.cern.ch/dis/texi2html/"; # program home page 47946379e7Schristos$TODAY = &pretty_date; # like "20 September 1993" 48946379e7Schristos$SPLITTAG = "<!-- SPLIT HERE -->\n"; # tag to know where to split 49946379e7Schristos$PROTECTTAG = "_ThisIsProtected_"; # tag to recognize protected sections 50946379e7Schristos$html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//EN">'; 51946379e7Schristos 52946379e7Schristos# 53946379e7Schristos# language dependent constants 54946379e7Schristos# 55946379e7Schristos#$LDC_SEE = 'see'; 56946379e7Schristos#$LDC_SECTION = 'section'; 57946379e7Schristos#$LDC_IN = 'in'; 58946379e7Schristos#$LDC_TOC = 'Table of Contents'; 59946379e7Schristos#$LDC_GOTO = 'Go to the'; 60946379e7Schristos#$LDC_FOOT = 'Footnotes'; 61946379e7Schristos# TODO: @def* shortcuts 62946379e7Schristos 63946379e7Schristos# 64946379e7Schristos# pre-defined indices 65946379e7Schristos# 66946379e7Schristos%predefined_index = ( 67946379e7Schristos 'cp', 'c', 68946379e7Schristos 'fn', 'f', 69946379e7Schristos 'vr', 'v', 70946379e7Schristos 'ky', 'k', 71946379e7Schristos 'pg', 'p', 72946379e7Schristos 'tp', 't', 73946379e7Schristos ); 74946379e7Schristos 75946379e7Schristos# 76946379e7Schristos# valid indices 77946379e7Schristos# 78946379e7Schristos%valid_index = ( 79946379e7Schristos 'c', 1, 80946379e7Schristos 'f', 1, 81946379e7Schristos 'v', 1, 82946379e7Schristos 'k', 1, 83946379e7Schristos 'p', 1, 84946379e7Schristos 't', 1, 85946379e7Schristos ); 86946379e7Schristos 87946379e7Schristos# 88946379e7Schristos# texinfo section names to level 89946379e7Schristos# 90946379e7Schristos%sec2level = ( 91946379e7Schristos 'top', 0, 92946379e7Schristos 'chapter', 1, 93946379e7Schristos 'unnumbered', 1, 94946379e7Schristos 'majorheading', 1, 95946379e7Schristos 'chapheading', 1, 96946379e7Schristos 'appendix', 1, 97946379e7Schristos 'section', 2, 98946379e7Schristos 'unnumberedsec', 2, 99946379e7Schristos 'heading', 2, 100946379e7Schristos 'appendixsec', 2, 101946379e7Schristos 'appendixsection', 2, 102946379e7Schristos 'subsection', 3, 103946379e7Schristos 'unnumberedsubsec', 3, 104946379e7Schristos 'subheading', 3, 105946379e7Schristos 'appendixsubsec', 3, 106946379e7Schristos 'subsubsection', 4, 107946379e7Schristos 'unnumberedsubsubsec', 4, 108946379e7Schristos 'subsubheading', 4, 109946379e7Schristos 'appendixsubsubsec', 4, 110946379e7Schristos ); 111946379e7Schristos 112946379e7Schristos# 113946379e7Schristos# accent map, TeX command to ISO name 114946379e7Schristos# 115946379e7Schristos%accent_map = ( 116946379e7Schristos '"', 'uml', 117946379e7Schristos '~', 'tilde', 118946379e7Schristos '^', 'circ', 119946379e7Schristos '`', 'grave', 120946379e7Schristos '\'', 'acute', 121946379e7Schristos ); 122946379e7Schristos 123946379e7Schristos# 124946379e7Schristos# texinfo "simple things" (@foo) to HTML ones 125946379e7Schristos# 126946379e7Schristos%simple_map = ( 127946379e7Schristos # cf. makeinfo.c 128946379e7Schristos "*", "<BR>", # HTML+ 129946379e7Schristos " ", " ", 130946379e7Schristos "\n", "\n", 131946379e7Schristos "|", "", 132946379e7Schristos # spacing commands 133946379e7Schristos ":", "", 134946379e7Schristos "!", "!", 135946379e7Schristos "?", "?", 136946379e7Schristos ".", ".", 137946379e7Schristos "-", "", 138946379e7Schristos ); 139946379e7Schristos 140946379e7Schristos# 141946379e7Schristos# texinfo "things" (@foo{}) to HTML ones 142946379e7Schristos# 143946379e7Schristos%things_map = ( 144946379e7Schristos 'TeX', 'TeX', 145946379e7Schristos 'br', '<P>', # paragraph break 146946379e7Schristos 'bullet', '*', 147946379e7Schristos 'copyright', '(C)', 148946379e7Schristos 'dots', '...', 149946379e7Schristos 'equiv', '==', 150946379e7Schristos 'error', 'error-->', 151946379e7Schristos 'expansion', '==>', 152946379e7Schristos 'minus', '-', 153946379e7Schristos 'point', '-!-', 154946379e7Schristos 'print', '-|', 155946379e7Schristos 'result', '=>', 156946379e7Schristos 'today', $TODAY, 157946379e7Schristos 'aa', 'å', 158946379e7Schristos 'AA', 'Å', 159946379e7Schristos 'ae', 'æ', 160946379e7Schristos 'AE', 'Æ', 161946379e7Schristos 'o', 'ø', 162946379e7Schristos 'O', 'Ø', 163946379e7Schristos 'ss', 'ß', 164946379e7Schristos 'exclamdown', '¡', 165946379e7Schristos 'questiondown', '¿', 166946379e7Schristos 'pounds', '£' 167946379e7Schristos ); 168946379e7Schristos 169946379e7Schristos# 170946379e7Schristos# texinfo styles (@foo{bar}) to HTML ones 171946379e7Schristos# 172946379e7Schristos%style_map = ( 173946379e7Schristos 'asis', '', 174946379e7Schristos 'b', 'B', 175946379e7Schristos 'cite', 'CITE', 176946379e7Schristos 'code', 'CODE', 177946379e7Schristos 'ctrl', '&do_ctrl', # special case 178946379e7Schristos 'dfn', 'EM', # DFN tag is illegal in the standard 179946379e7Schristos 'dmn', '', # useless 180946379e7Schristos 'email', '&do_email', # insert a clickable email address 181946379e7Schristos 'emph', 'EM', 182946379e7Schristos 'file', '"TT', # will put quotes, cf. &apply_style 183946379e7Schristos 'i', 'I', 184946379e7Schristos 'kbd', 'KBD', 185946379e7Schristos 'key', 'KBD', 186946379e7Schristos 'math', 'EM', 187946379e7Schristos 'r', '', # unsupported 188946379e7Schristos 'samp', '"SAMP', # will put quotes, cf. &apply_style 189946379e7Schristos 'sc', '&do_sc', # special case 190946379e7Schristos 'strong', 'STRONG', 191946379e7Schristos 't', 'TT', 192946379e7Schristos 'titlefont', '', # useless 193946379e7Schristos 'uref', '&do_uref', # insert a clickable URL 194946379e7Schristos 'url', '&do_url', # insert a clickable URL 195946379e7Schristos 'var', 'VAR', 196946379e7Schristos 'w', '', # unsupported 197946379e7Schristos '"', '&do_diaeresis', 198946379e7Schristos '\'', '&do_acuteaccent', # doesn't work?? 199946379e7Schristos '\`', '&do_graveaccent', # doesn't work?? 200946379e7Schristos '~', '&do_tildeaccent', 201946379e7Schristos ',', '&do_cedilla', 202946379e7Schristos '^', '&do_circumflex', 203946379e7Schristos ); 204946379e7Schristos 205946379e7Schristos# 206946379e7Schristos# texinfo format (@foo/@end foo) to HTML ones 207946379e7Schristos# 208946379e7Schristos%format_map = ( 209946379e7Schristos 'display', 'PRE', 210946379e7Schristos 'example', 'PRE', 211946379e7Schristos 'format', 'PRE', 212946379e7Schristos 'lisp', 'PRE', 213946379e7Schristos 'quotation', 'BLOCKQUOTE', 214946379e7Schristos 'smallexample', 'PRE', 215946379e7Schristos 'smalllisp', 'PRE', 216946379e7Schristos # lists 217946379e7Schristos 'itemize', 'UL', 218946379e7Schristos 'enumerate', 'OL', 219946379e7Schristos # poorly supported 220946379e7Schristos 'flushleft', 'PRE', 221946379e7Schristos 'flushright', 'PRE', 222946379e7Schristos ); 223946379e7Schristos 224946379e7Schristos# 225946379e7Schristos# texinfo definition shortcuts to real ones 226946379e7Schristos# 227946379e7Schristos%def_map = ( 228946379e7Schristos # basic commands 229946379e7Schristos 'deffn', 0, 230946379e7Schristos 'defvr', 0, 231946379e7Schristos 'deftypefn', 0, 232946379e7Schristos 'deftypevr', 0, 233946379e7Schristos 'defcv', 0, 234946379e7Schristos 'defop', 0, 235946379e7Schristos 'deftp', 0, 236946379e7Schristos # basic x commands 237946379e7Schristos 'deffnx', 0, 238946379e7Schristos 'defvrx', 0, 239946379e7Schristos 'deftypefnx', 0, 240946379e7Schristos 'deftypevrx', 0, 241946379e7Schristos 'defcvx', 0, 242946379e7Schristos 'defopx', 0, 243946379e7Schristos 'deftpx', 0, 244946379e7Schristos # shortcuts 245946379e7Schristos 'defun', 'deffn Function', 246946379e7Schristos 'defmac', 'deffn Macro', 247946379e7Schristos 'defspec', 'deffn {Special Form}', 248946379e7Schristos 'defvar', 'defvr Variable', 249946379e7Schristos 'defopt', 'defvr {User Option}', 250946379e7Schristos 'deftypefun', 'deftypefn Function', 251946379e7Schristos 'deftypevar', 'deftypevr Variable', 252946379e7Schristos 'defivar', 'defcv {Instance Variable}', 253946379e7Schristos 'defmethod', 'defop Method', 254946379e7Schristos # x shortcuts 255946379e7Schristos 'defunx', 'deffnx Function', 256946379e7Schristos 'defmacx', 'deffnx Macro', 257946379e7Schristos 'defspecx', 'deffnx {Special Form}', 258946379e7Schristos 'defvarx', 'defvrx Variable', 259946379e7Schristos 'defoptx', 'defvrx {User Option}', 260946379e7Schristos 'deftypefunx', 'deftypefnx Function', 261946379e7Schristos 'deftypevarx', 'deftypevrx Variable', 262946379e7Schristos 'defivarx', 'defcvx {Instance Variable}', 263946379e7Schristos 'defmethodx', 'defopx Method', 264946379e7Schristos ); 265946379e7Schristos 266946379e7Schristos# 267946379e7Schristos# things to skip 268946379e7Schristos# 269946379e7Schristos%to_skip = ( 270946379e7Schristos # comments 271946379e7Schristos 'c', 1, 272946379e7Schristos 'comment', 1, 273946379e7Schristos # useless 274946379e7Schristos 'contents', 1, 275946379e7Schristos 'shortcontents', 1, 276946379e7Schristos 'summarycontents', 1, 277946379e7Schristos 'footnotestyle', 1, 278946379e7Schristos 'end ifclear', 1, 279946379e7Schristos 'end ifset', 1, 280946379e7Schristos 'titlepage', 1, 281946379e7Schristos 'end titlepage', 1, 282946379e7Schristos # unsupported commands (formatting) 283946379e7Schristos 'afourpaper', 1, 284946379e7Schristos 'cropmarks', 1, 285946379e7Schristos 'finalout', 1, 286946379e7Schristos 'headings', 1, 287946379e7Schristos 'need', 1, 288946379e7Schristos 'page', 1, 289946379e7Schristos 'setchapternewpage', 1, 290946379e7Schristos 'everyheading', 1, 291946379e7Schristos 'everyfooting', 1, 292946379e7Schristos 'evenheading', 1, 293946379e7Schristos 'evenfooting', 1, 294946379e7Schristos 'oddheading', 1, 295946379e7Schristos 'oddfooting', 1, 296946379e7Schristos 'smallbook', 1, 297946379e7Schristos 'vskip', 1, 298946379e7Schristos 'filbreak', 1, 299946379e7Schristos 'paragraphindent', 1, 300946379e7Schristos # unsupported formats 301946379e7Schristos 'cartouche', 1, 302946379e7Schristos 'end cartouche', 1, 303946379e7Schristos 'group', 1, 304946379e7Schristos 'end group', 1, 305946379e7Schristos ); 306946379e7Schristos 307946379e7Schristos#+++############################################################################ 308946379e7Schristos# # 309946379e7Schristos# Argument parsing, initialisation # 310946379e7Schristos# # 311946379e7Schristos#---############################################################################ 312946379e7Schristos 313946379e7Schristos%value = (); # hold texinfo variables, see also -D 314946379e7Schristos 315946379e7Schristos$use_bibliography = 1; 316946379e7Schristos$use_acc = 0; 317946379e7Schristos$debug = 0; 318946379e7Schristos$doctype = ''; 319946379e7Schristos$check = 0; 320946379e7Schristos$expandinfo = 0; 321946379e7Schristos$expandtex = 0; 322946379e7Schristos$use_glossary = 0; 323946379e7Schristos$invisible_mark = ''; 324946379e7Schristos$use_iso = 0; 325946379e7Schristos@include_dirs = (); 326946379e7Schristos$show_menu = 0; 327946379e7Schristos$number_sections = 0; 328946379e7Schristos$split_node = 0; 329946379e7Schristos$split_chapter = 0; 330946379e7Schristos$monolithic = 0; 331946379e7Schristos$verbose = 0; 332946379e7Schristos$usage = <<EOT; 333946379e7SchristosThis is $THISPROG 334946379e7SchristosTo convert a Texinfo file to HMTL: $0 [options] file 335946379e7Schristos where options can be: 336946379e7Schristos -expandinfo : use \@ifinfo sections, not \@ifhtml 337946379e7Schristos -expandtex : use \@iftex sections, not \@ifhtml 338946379e7Schristos -glossary : handle a glossary 339946379e7Schristos -invisible name: use 'name' as an invisible anchor 340946379e7Schristos -Dname : define name like with \@set 341946379e7Schristos -I dir : search also for files in 'dir' 342946379e7Schristos -menu : handle menus 343946379e7Schristos -monolithic : output only one file including ToC 344946379e7Schristos -number : number sections 345946379e7Schristos -split_chapter : split on main sections 346946379e7Schristos -split_node : split on nodes 347946379e7Schristos -usage : print usage instructions 348946379e7Schristos -verbose : verbose output 349946379e7SchristosTo check converted files: $0 -check [-verbose] files 350946379e7SchristosEOT 351946379e7Schristos 352946379e7Schristoswhile (@ARGV && $ARGV[0] =~ /^-/) { 353946379e7Schristos $_ = shift(@ARGV); 354946379e7Schristos if (/^-acc$/) { $use_acc = 1; next; } 355946379e7Schristos if (/^-d(ebug)?(\d+)?$/) { $debug = $2 || shift(@ARGV); next; } 356946379e7Schristos if (/^-doctype$/) { $doctype = shift(@ARGV); next; } 357946379e7Schristos if (/^-c(heck)?$/) { $check = 1; next; } 358946379e7Schristos if (/^-expandi(nfo)?$/) { $expandinfo = 1; next; } 359946379e7Schristos if (/^-expandt(ex)?$/) { $expandtex = 1; next; } 360946379e7Schristos if (/^-g(lossary)?$/) { $use_glossary = 1; next; } 361946379e7Schristos if (/^-i(nvisible)?$/) { $invisible_mark = shift(@ARGV); next; } 362946379e7Schristos if (/^-iso$/) { $use_iso = 1; next; } 363946379e7Schristos if (/^-D(.+)?$/) { $value{$1 || shift(@ARGV)} = 1; next; } 364946379e7Schristos if (/^-I(.+)?$/) { push(@include_dirs, $1 || shift(@ARGV)); next; } 365946379e7Schristos if (/^-m(enu)?$/) { $show_menu = 1; next; } 366946379e7Schristos if (/^-mono(lithic)?$/) { $monolithic = 1; next; } 367946379e7Schristos if (/^-n(umber)?$/) { $number_sections = 1; next; } 368946379e7Schristos if (/^-s(plit)?_?(n(ode)?|c(hapter)?)?$/) { 369946379e7Schristos if ($2 =~ /^n/) { 370946379e7Schristos $split_node = 1; 371946379e7Schristos } else { 372946379e7Schristos $split_chapter = 1; 373946379e7Schristos } 374946379e7Schristos next; 375946379e7Schristos } 376946379e7Schristos if (/^-v(erbose)?$/) { $verbose = 1; next; } 377946379e7Schristos die $usage; 378946379e7Schristos} 379946379e7Schristosif ($check) { 380946379e7Schristos die $usage unless @ARGV > 0; 381946379e7Schristos ✓ 382946379e7Schristos exit; 383946379e7Schristos} 384946379e7Schristos 385946379e7Schristosif (($split_node || $split_chapter) && $monolithic) { 386946379e7Schristos warn "Can't use -monolithic with -split, -monolithic ignored.\n"; 387946379e7Schristos $monolithic = 0; 388946379e7Schristos} 389946379e7Schristosif ($expandinfo) { 390946379e7Schristos $to_skip{'ifinfo'}++; 391946379e7Schristos $to_skip{'end ifinfo'}++; 392946379e7Schristos $to_skip{'ifnottex'}++; 393946379e7Schristos $to_skip{'end ifnottex'}++; 394946379e7Schristos $to_skip{'ifnothtml'}++; 395946379e7Schristos $to_skip{'end ifnothtml'}++; 396946379e7Schristos} elsif ($expandtex) { 397946379e7Schristos $to_skip{'ifnotinfo'}++; 398946379e7Schristos $to_skip{'end ifnotinfo'}++; 399946379e7Schristos $to_skip{'iftex'}++; 400946379e7Schristos $to_skip{'end iftex'}++; 401946379e7Schristos $to_skip{'ifnothtml'}++; 402946379e7Schristos $to_skip{'end ifnothtml'}++; 403946379e7Schristos} else { 404946379e7Schristos $to_skip{'ifnotinfo'}++; 405946379e7Schristos $to_skip{'end ifnotinfo'}++; 406946379e7Schristos $to_skip{'ifnottex'}++; 407946379e7Schristos $to_skip{'end ifnottex'}++; 408946379e7Schristos $to_skip{'ifhtml'}++; 409946379e7Schristos $to_skip{'end ifhtml'}++; 410946379e7Schristos} 411946379e7Schristos$invisible_mark = '<IMG SRC="invisible.xbm">' if $invisible_mark eq 'xbm'; 412946379e7Schristosdie $usage unless @ARGV == 1; 413946379e7Schristos$docu = shift(@ARGV); 414946379e7Schristosif ($docu =~ /.*\//) { 415946379e7Schristos chop($docu_dir = $&); 416946379e7Schristos $docu_name = $'; 417946379e7Schristos} else { 418946379e7Schristos $docu_dir = '.'; 419946379e7Schristos $docu_name = $docu; 420946379e7Schristos} 421946379e7Schristosunshift(@include_dirs, $docu_dir); 422946379e7Schristos$docu_name =~ s/\.te?x(i|info)?$//; # basename of the document 423946379e7Schristos 424946379e7Schristos$docu_doc = "$docu_name.html"; # document's contents 425946379e7Schristosif ($monolithic) { 426946379e7Schristos $docu_toc = $docu_foot = $docu_doc; 427946379e7Schristos} else { 428946379e7Schristos $docu_toc = "${docu_name}_toc.html"; # document's table of contents 429946379e7Schristos $docu_foot = "${docu_name}_foot.html"; # document's footnotes 430946379e7Schristos} 431946379e7Schristos 432946379e7Schristos# 433946379e7Schristos# variables 434946379e7Schristos# 435946379e7Schristos$value{'html'} = 1; # predefine html (the output format) 436946379e7Schristos$value{'texi2html'} = '1.52b'; # predefine texi2html (the translator) 437946379e7Schristos# _foo: internal to track @foo 438946379e7Schristosforeach ('_author', '_title', '_subtitle', 439946379e7Schristos '_settitle', '_setfilename') { 440946379e7Schristos $value{$_} = ''; # prevent -w warnings 441946379e7Schristos} 442946379e7Schristos%node2sec = (); # node to section name 443946379e7Schristos%node2href = (); # node to HREF 444946379e7Schristos%bib2href = (); # bibliography reference to HREF 445946379e7Schristos%gloss2href = (); # glossary term to HREF 446946379e7Schristos@sections = (); # list of sections 447946379e7Schristos%tag2pro = (); # protected sections 448946379e7Schristos 449946379e7Schristos# 450946379e7Schristos# initial indexes 451946379e7Schristos# 452946379e7Schristos$bib_num = 0; 453946379e7Schristos$foot_num = 0; 454946379e7Schristos$gloss_num = 0; 455946379e7Schristos$idx_num = 0; 456946379e7Schristos$sec_num = 0; 457946379e7Schristos$doc_num = 0; 458946379e7Schristos$html_num = 0; 459946379e7Schristos 460946379e7Schristos# 461946379e7Schristos# can I use ISO8879 characters? (HTML+) 462946379e7Schristos# 463946379e7Schristosif ($use_iso) { 464946379e7Schristos $things_map{'bullet'} = "•"; 465946379e7Schristos $things_map{'copyright'} = "©"; 466946379e7Schristos $things_map{'dots'} = "…"; 467946379e7Schristos $things_map{'equiv'} = "≡"; 468946379e7Schristos $things_map{'expansion'} = "→"; 469946379e7Schristos $things_map{'point'} = "∗"; 470946379e7Schristos $things_map{'result'} = "⇒"; 471946379e7Schristos} 472946379e7Schristos 473946379e7Schristos# 474946379e7Schristos# read texi2html extensions (if any) 475946379e7Schristos# 476946379e7Schristos$extensions = 'texi2html.ext'; # extensions in working directory 477946379e7Schristosif (-f $extensions) { 478946379e7Schristos print "# reading extensions from $extensions\n" if $verbose; 479946379e7Schristos require($extensions); 480946379e7Schristos} 481946379e7Schristos($progdir = $0) =~ s/[^\/]+$//; 482946379e7Schristosif ($progdir && ($progdir ne './')) { 483946379e7Schristos $extensions = "${progdir}texi2html.ext"; # extensions in texi2html directory 484946379e7Schristos if (-f $extensions) { 485946379e7Schristos print "# reading extensions from $extensions\n" if $verbose; 486946379e7Schristos require($extensions); 487946379e7Schristos } 488946379e7Schristos} 489946379e7Schristos 490946379e7Schristosprint "# reading from $docu\n" if $verbose; 491946379e7Schristos 492946379e7Schristos#+++############################################################################ 493946379e7Schristos# # 494946379e7Schristos# Pass 1: read source, handle command, variable, simple substitution # 495946379e7Schristos# # 496946379e7Schristos#---############################################################################ 497946379e7Schristos 498946379e7Schristos@lines = (); # whole document 499946379e7Schristos@toc_lines = (); # table of contents 500946379e7Schristos$toplevel = 0; # top level seen in hierarchy 501946379e7Schristos$curlevel = 0; # current level in TOC 502946379e7Schristos$node = ''; # current node name 503946379e7Schristos$in_table = 0; # am I inside a table 504946379e7Schristos$table_type = ''; # type of table ('', 'f', 'v', 'multi') 505946379e7Schristos@tables = (); # nested table support 506946379e7Schristos$in_bibliography = 0; # am I inside a bibliography 507946379e7Schristos$in_glossary = 0; # am I inside a glossary 508946379e7Schristos$in_top = 0; # am I inside the top node 509946379e7Schristos$in_pre = 0; # am I inside a preformatted section 510946379e7Schristos$in_list = 0; # am I inside a list 511946379e7Schristos$in_html = 0; # am I inside an HTML section 512946379e7Schristos$first_line = 1; # is it the first line 513946379e7Schristos$dont_html = 0; # don't protect HTML on this line 514946379e7Schristos$split_num = 0; # split index 515946379e7Schristos$deferred_ref = ''; # deferred reference for indexes 516946379e7Schristos@html_stack = (); # HTML elements stack 517946379e7Schristos$html_element = ''; # current HTML element 518946379e7Schristos&html_reset; 519946379e7Schristos 520946379e7Schristos# build code for simple substitutions 521946379e7Schristos# the maps used (%simple_map and %things_map) MUST be aware of this 522946379e7Schristos# watch out for regexps, / and escaped characters! 523946379e7Schristos$subst_code = ''; 524946379e7Schristosforeach (keys(%simple_map)) { 525946379e7Schristos ($re = $_) =~ s/(\W)/\\$1/g; # protect regexp chars 526946379e7Schristos $subst_code .= "s/\\\@$re/$simple_map{$_}/g;\n"; 527946379e7Schristos} 528946379e7Schristosforeach (keys(%things_map)) { 529946379e7Schristos $subst_code .= "s/\\\@$_\\{\\}/$things_map{$_}/g;\n"; 530946379e7Schristos} 531946379e7Schristosif ($use_acc) { 532946379e7Schristos # accentuated characters 533946379e7Schristos foreach (keys(%accent_map)) { 534946379e7Schristos if ($_ eq "`") { 535946379e7Schristos $subst_code .= "s/$;3"; 536946379e7Schristos } elsif ($_ eq "'") { 537946379e7Schristos $subst_code .= "s/$;4"; 538946379e7Schristos } else { 539946379e7Schristos $subst_code .= "s/\\\@\\$_"; 540946379e7Schristos } 541946379e7Schristos $subst_code .= "([aeiou])/&\${1}$accent_map{$_};/gi;\n"; 542946379e7Schristos } 543946379e7Schristos} 544946379e7Schristoseval("sub simple_substitutions { $subst_code }"); 545946379e7Schristos 546946379e7Schristos&init_input; 547946379e7Schristoswhile ($_ = &next_line) { 548946379e7Schristos # 549946379e7Schristos # remove \input on the first lines only 550946379e7Schristos # 551946379e7Schristos if ($first_line) { 552946379e7Schristos next if /^\\input/; 553946379e7Schristos $first_line = 0; 554946379e7Schristos } 555946379e7Schristos # 556946379e7Schristos # parse texinfo tags 557946379e7Schristos # 558946379e7Schristos $tag = ''; 559946379e7Schristos $end_tag = ''; 560946379e7Schristos if (/^\@end\s+(\w+)\b/) { 561946379e7Schristos $end_tag = $1; 562946379e7Schristos } elsif (/^\@(\w+)\b/) { 563946379e7Schristos $tag = $1; 564946379e7Schristos } 565946379e7Schristos # 566946379e7Schristos # handle @ifhtml / @end ifhtml 567946379e7Schristos # 568946379e7Schristos if ($in_html) { 569946379e7Schristos if ($end_tag eq 'ifhtml') { 570946379e7Schristos $in_html = 0; 571946379e7Schristos } else { 572946379e7Schristos $tag2pro{$in_html} .= $_; 573946379e7Schristos } 574946379e7Schristos next; 575946379e7Schristos } elsif ($tag eq 'ifhtml') { 576946379e7Schristos $in_html = $PROTECTTAG . ++$html_num; 577946379e7Schristos push(@lines, $in_html); 578946379e7Schristos next; 579946379e7Schristos } 580946379e7Schristos # 581946379e7Schristos # try to skip the line 582946379e7Schristos # 583946379e7Schristos if ($end_tag) { 584946379e7Schristos next if $to_skip{"end $end_tag"}; 585946379e7Schristos } elsif ($tag) { 586946379e7Schristos next if $to_skip{$tag}; 587946379e7Schristos last if $tag eq 'bye'; 588946379e7Schristos } 589946379e7Schristos if ($in_top) { 590946379e7Schristos # parsing the top node 591946379e7Schristos if ($tag eq 'node' || $tag eq 'include' || $sec2level{$tag}) { 592946379e7Schristos # no more in top 593946379e7Schristos $in_top = 0; 594946379e7Schristos } else { 595946379e7Schristos # skip it 596946379e7Schristos next; 597946379e7Schristos } 598946379e7Schristos } 599946379e7Schristos # 600946379e7Schristos # try to remove inlined comments 601946379e7Schristos # syntax from tex-mode.el comment-start-skip 602946379e7Schristos # 603946379e7Schristos s/((^|[^\@])(\@\@)*)\@c(omment)? .*/$1/; 604946379e7Schristos # non-@ substitutions cf. texinfmt.el 605946379e7Schristos unless ($in_pre) { 606946379e7Schristos s/``/“/g; 607946379e7Schristos s/''/”/g; 608946379e7Schristos s/([\w ])---([\w ])/$1--$2/g; 609946379e7Schristos } 610946379e7Schristos # 611946379e7Schristos # analyze the tag 612946379e7Schristos # 613946379e7Schristos if ($tag) { 614946379e7Schristos # skip lines 615946379e7Schristos &skip_until($tag), next if $tag eq 'ignore'; 616946379e7Schristos if ($expandinfo) { 617946379e7Schristos &skip_until($tag), next if $tag eq 'ifnotinfo'; 618946379e7Schristos &skip_until($tag), next if $tag eq 'iftex'; 619946379e7Schristos &skip_until($tag), next if $tag eq 'ifhtml'; 620946379e7Schristos } elsif ($expandtex) { 621946379e7Schristos &skip_until($tag), next if $tag eq 'ifinfo'; 622946379e7Schristos &skip_until($tag), next if $tag eq 'ifnottex'; 623946379e7Schristos &skip_until($tag), next if $tag eq 'ifhtml'; 624946379e7Schristos } else { 625946379e7Schristos &skip_until($tag), next if $tag eq 'ifinfo'; 626946379e7Schristos &skip_until($tag), next if $tag eq 'iftex'; 627946379e7Schristos &skip_until($tag), next if $tag eq 'ifnothtml'; 628946379e7Schristos } 629946379e7Schristos &skip_until($tag), next if $tag eq 'tex'; 630946379e7Schristos # handle special tables 631946379e7Schristos if ($tag =~ /^(|f|v|multi)table$/) { 632946379e7Schristos $table_type = $1; 633946379e7Schristos $tag = 'table'; 634946379e7Schristos } 635946379e7Schristos # special cases 636946379e7Schristos if ($tag eq 'top' || ($tag eq 'node' && /^\@node\s+top\s*,/i)) { 637946379e7Schristos $in_top = 1; 638946379e7Schristos @lines = (); # ignore all lines before top (title page garbage) 639946379e7Schristos next; 640946379e7Schristos } elsif ($tag eq 'node') { 641946379e7Schristos $in_top = 0; 642946379e7Schristos warn "$ERROR Bad node line: $_" unless $_ =~ /^\@node\s$NODESRE$/o; 643946379e7Schristos $_ = &protect_html($_); # if node contains '&' for instance 644946379e7Schristos s/^\@node\s+//; 645946379e7Schristos ($node) = split(/,/); 646946379e7Schristos &normalise_node($node); 647946379e7Schristos if ($split_node) { 648946379e7Schristos &next_doc; 649946379e7Schristos push(@lines, $SPLITTAG) if $split_num++; 650946379e7Schristos push(@sections, $node); 651946379e7Schristos } 652946379e7Schristos next; 653946379e7Schristos } elsif ($tag eq 'include') { 654946379e7Schristos if (/^\@include\s+($FILERE)\s*$/o) { 655946379e7Schristos $file = $1; 656946379e7Schristos unless (-e $file) { 657946379e7Schristos foreach $dir (@include_dirs) { 658946379e7Schristos $file = "$dir/$1"; 659946379e7Schristos last if -e $file; 660946379e7Schristos } 661946379e7Schristos } 662946379e7Schristos if (-e $file) { 663946379e7Schristos &open($file); 664946379e7Schristos print "# including $file\n" if $verbose; 665946379e7Schristos } else { 666946379e7Schristos warn "$ERROR Can't find $file, skipping"; 667946379e7Schristos } 668946379e7Schristos } else { 669946379e7Schristos warn "$ERROR Bad include line: $_"; 670946379e7Schristos } 671946379e7Schristos next; 672946379e7Schristos } elsif ($tag eq 'ifclear') { 673946379e7Schristos if (/^\@ifclear\s+($VARRE)\s*$/o) { 674946379e7Schristos next unless defined($value{$1}); 675946379e7Schristos &skip_until($tag); 676946379e7Schristos } else { 677946379e7Schristos warn "$ERROR Bad ifclear line: $_"; 678946379e7Schristos } 679946379e7Schristos next; 680946379e7Schristos } elsif ($tag eq 'ifset') { 681946379e7Schristos if (/^\@ifset\s+($VARRE)\s*$/o) { 682946379e7Schristos next if defined($value{$1}); 683946379e7Schristos &skip_until($tag); 684946379e7Schristos } else { 685946379e7Schristos warn "$ERROR Bad ifset line: $_"; 686946379e7Schristos } 687946379e7Schristos next; 688946379e7Schristos } elsif ($tag eq 'menu') { 689946379e7Schristos unless ($show_menu) { 690946379e7Schristos &skip_until($tag); 691946379e7Schristos next; 692946379e7Schristos } 693946379e7Schristos &html_push_if($tag); 694946379e7Schristos push(@lines, &html_debug("\n", __LINE__)); 695946379e7Schristos } elsif ($format_map{$tag}) { 696946379e7Schristos $in_pre = 1 if $format_map{$tag} eq 'PRE'; 697946379e7Schristos &html_push_if($format_map{$tag}); 698946379e7Schristos push(@lines, &html_debug("\n", __LINE__)); 699946379e7Schristos $in_list++ if $format_map{$tag} eq 'UL' || $format_map{$tag} eq 'OL' ; 700946379e7Schristos push(@lines, &debug("<$format_map{$tag}>\n", __LINE__)); 701946379e7Schristos next; 702946379e7Schristos } elsif ($tag eq 'table') { 703946379e7Schristos if (/^\@(|f|v|multi)table\s+\@(\w+)/) { 704946379e7Schristos $in_table = $2; 705946379e7Schristos unshift(@tables, join($;, $table_type, $in_table)); 706946379e7Schristos if ($table_type eq "multi") { 707946379e7Schristos push(@lines, &debug("<TABLE BORDER>\n", __LINE__)); 708946379e7Schristos &html_push_if('TABLE'); 709946379e7Schristos } else { 710946379e7Schristos push(@lines, &debug("<DL COMPACT>\n", __LINE__)); 711946379e7Schristos &html_push_if('DL'); 712946379e7Schristos } 713946379e7Schristos push(@lines, &html_debug("\n", __LINE__)); 714946379e7Schristos } else { 715946379e7Schristos warn "$ERROR Bad table line: $_"; 716946379e7Schristos } 717946379e7Schristos next; 718946379e7Schristos } elsif ($tag eq 'synindex' || $tag eq 'syncodeindex') { 719946379e7Schristos if (/^\@$tag\s+(\w)\w\s+(\w)\w\s*$/) { 720946379e7Schristos eval("*${1}index = *${2}index"); 721946379e7Schristos } else { 722946379e7Schristos warn "$ERROR Bad syn*index line: $_"; 723946379e7Schristos } 724946379e7Schristos next; 725946379e7Schristos } elsif ($tag eq 'sp') { 726946379e7Schristos push(@lines, &debug("<P>\n", __LINE__)); 727946379e7Schristos next; 728946379e7Schristos } elsif ($tag eq 'setref') { 729946379e7Schristos &protect_html; # if setref contains '&' for instance 730946379e7Schristos if (/^\@$tag\s*{($NODERE)}\s*$/) { 731946379e7Schristos $setref = $1; 732946379e7Schristos $setref =~ s/\s+/ /g; # normalize 733946379e7Schristos $setref =~ s/ $//; 734946379e7Schristos $node2sec{$setref} = $name; 735946379e7Schristos $node2href{$setref} = "$docu_doc#$docid"; 736946379e7Schristos } else { 737946379e7Schristos warn "$ERROR Bad setref line: $_"; 738946379e7Schristos } 739946379e7Schristos next; 740946379e7Schristos } elsif ($tag eq 'defindex' || $tag eq 'defcodeindex') { 741946379e7Schristos if (/^\@$tag\s+(\w\w)\s*$/) { 742946379e7Schristos $valid_index{$1} = 1; 743946379e7Schristos } else { 744946379e7Schristos warn "$ERROR Bad defindex line: $_"; 745946379e7Schristos } 746946379e7Schristos next; 747946379e7Schristos } elsif (defined($def_map{$tag})) { 748946379e7Schristos if ($def_map{$tag}) { 749946379e7Schristos s/^\@$tag\s+//; 750946379e7Schristos $tag = $def_map{$tag}; 751946379e7Schristos $_ = "\@$tag $_"; 752946379e7Schristos $tag =~ s/\s.*//; 753946379e7Schristos } 754946379e7Schristos } elsif (defined($user_sub{$tag})) { 755946379e7Schristos s/^\@$tag\s+//; 756946379e7Schristos $sub = $user_sub{$tag}; 757946379e7Schristos print "# user $tag = $sub, arg: $_" if $debug & $DEBUG_USER; 758946379e7Schristos if (defined(&$sub)) { 759946379e7Schristos chop($_); 760946379e7Schristos &$sub($_); 761946379e7Schristos } else { 762946379e7Schristos warn "$ERROR Bad user sub for $tag: $sub\n"; 763946379e7Schristos } 764946379e7Schristos next; 765946379e7Schristos } 766946379e7Schristos if (defined($def_map{$tag})) { 767946379e7Schristos s/^\@$tag\s+//; 768946379e7Schristos if ($tag =~ /x$/) { 769946379e7Schristos # extra definition line 770946379e7Schristos $tag = $`; 771946379e7Schristos $is_extra = 1; 772946379e7Schristos } else { 773946379e7Schristos $is_extra = 0; 774946379e7Schristos } 775946379e7Schristos while (/\{([^\{\}]*)\}/) { 776946379e7Schristos # this is a {} construct 777946379e7Schristos ($before, $contents, $after) = ($`, $1, $'); 778946379e7Schristos # protect spaces 779946379e7Schristos $contents =~ s/\s+/$;9/g; 780946379e7Schristos # restore $_ protecting {} 781946379e7Schristos $_ = "$before$;7$contents$;8$after"; 782946379e7Schristos } 783946379e7Schristos @args = split(/\s+/, &protect_html($_)); 784946379e7Schristos foreach (@args) { 785946379e7Schristos s/$;9/ /g; # unprotect spaces 786946379e7Schristos s/$;7/\{/g; # ... { 787946379e7Schristos s/$;8/\}/g; # ... } 788946379e7Schristos } 789946379e7Schristos $type = shift(@args); 790946379e7Schristos $type =~ s/^\{(.*)\}$/$1/; 791946379e7Schristos print "# def ($tag): {$type} ", join(', ', @args), "\n" 792946379e7Schristos if $debug & $DEBUG_DEF; 793946379e7Schristos $type .= ':'; # it's nicer like this 794946379e7Schristos $name = shift(@args); 795946379e7Schristos $name =~ s/^\{(.*)\}$/$1/; 796946379e7Schristos if ($is_extra) { 797946379e7Schristos $_ = &debug("<DT>", __LINE__); 798946379e7Schristos } else { 799946379e7Schristos $_ = &debug("<DL>\n<DT>", __LINE__); 800946379e7Schristos } 801946379e7Schristos if ($tag eq 'deffn' || $tag eq 'defvr' || $tag eq 'deftp') { 802946379e7Schristos $_ .= "<U>$type</U> <B>$name</B>"; 803946379e7Schristos $_ .= " <I>@args</I>" if @args; 804946379e7Schristos } elsif ($tag eq 'deftypefn' || $tag eq 'deftypevr' 805946379e7Schristos || $tag eq 'defcv' || $tag eq 'defop') { 806946379e7Schristos $ftype = $name; 807946379e7Schristos $name = shift(@args); 808946379e7Schristos $name =~ s/^\{(.*)\}$/$1/; 809946379e7Schristos $_ .= "<U>$type</U> $ftype <B>$name</B>"; 810946379e7Schristos $_ .= " <I>@args</I>" if @args; 811946379e7Schristos } else { 812946379e7Schristos warn "$ERROR Unknown definition type: $tag\n"; 813946379e7Schristos $_ .= "<U>$type</U> <B>$name</B>"; 814946379e7Schristos $_ .= " <I>@args</I>" if @args; 815946379e7Schristos } 816946379e7Schristos $_ .= &debug("\n<DD>", __LINE__); 817946379e7Schristos $name = &unprotect_html($name); 818946379e7Schristos if ($tag eq 'deffn' || $tag eq 'deftypefn') { 819946379e7Schristos unshift(@input_spool, "\@findex $name\n"); 820946379e7Schristos } elsif ($tag eq 'defop') { 821946379e7Schristos unshift(@input_spool, "\@findex $name on $ftype\n"); 822946379e7Schristos } elsif ($tag eq 'defvr' || $tag eq 'deftypevr' || $tag eq 'defcv') { 823946379e7Schristos unshift(@input_spool, "\@vindex $name\n"); 824946379e7Schristos } else { 825946379e7Schristos unshift(@input_spool, "\@tindex $name\n"); 826946379e7Schristos } 827946379e7Schristos $dont_html = 1; 828946379e7Schristos } 829946379e7Schristos } elsif ($end_tag) { 830946379e7Schristos if ($format_map{$end_tag}) { 831946379e7Schristos $in_pre = 0 if $format_map{$end_tag} eq 'PRE'; 832946379e7Schristos $in_list-- if $format_map{$end_tag} eq 'UL' || $format_map{$end_tag} eq 'OL' ; 833946379e7Schristos &html_pop_if('LI', 'P'); 834946379e7Schristos &html_pop_if(); 835946379e7Schristos push(@lines, &debug("</$format_map{$end_tag}>\n", __LINE__)); 836946379e7Schristos push(@lines, &html_debug("\n", __LINE__)); 837946379e7Schristos } elsif ($end_tag =~ /^(|f|v|multi)table$/) { 838946379e7Schristos unless (@tables) { 839946379e7Schristos warn "$ERROR \@end $end_tag without \@*table\n"; 840946379e7Schristos next; 841946379e7Schristos } 842946379e7Schristos ($table_type, $in_table) = split($;, shift(@tables)); 843946379e7Schristos unless ($1 eq $table_type) { 844946379e7Schristos warn "$ERROR \@end $end_tag without matching \@$end_tag\n"; 845946379e7Schristos next; 846946379e7Schristos } 847946379e7Schristos if ($table_type eq "multi") { 848946379e7Schristos push(@lines, "</TR></TABLE>\n"); 849946379e7Schristos &html_pop_if('TR'); 850946379e7Schristos } else { 851946379e7Schristos push(@lines, "</DL>\n"); 852946379e7Schristos &html_pop_if('DD'); 853946379e7Schristos } 854946379e7Schristos &html_pop_if(); 855946379e7Schristos if (@tables) { 856946379e7Schristos ($table_type, $in_table) = split($;, $tables[0]); 857946379e7Schristos } else { 858946379e7Schristos $in_table = 0; 859946379e7Schristos } 860946379e7Schristos } elsif (defined($def_map{$end_tag})) { 861946379e7Schristos push(@lines, &debug("</DL>\n", __LINE__)); 862946379e7Schristos } elsif ($end_tag eq 'menu') { 863946379e7Schristos &html_pop_if(); 864946379e7Schristos push(@lines, $_); # must keep it for pass 2 865946379e7Schristos } 866946379e7Schristos next; 867946379e7Schristos } 868946379e7Schristos # 869946379e7Schristos # misc things 870946379e7Schristos # 871946379e7Schristos # protect texi and HTML things 872946379e7Schristos &protect_texi; 873946379e7Schristos $_ = &protect_html($_) unless $dont_html; 874946379e7Schristos $dont_html = 0; 875946379e7Schristos # substitution (unsupported things) 876946379e7Schristos s/^\@center\s+//g; 877946379e7Schristos s/^\@exdent\s+//g; 878946379e7Schristos s/\@noindent\s+//g; 879946379e7Schristos s/\@refill\s+//g; 880946379e7Schristos # other substitutions 881946379e7Schristos &simple_substitutions; 882946379e7Schristos s/\@value{($VARRE)}/$value{$1}/eg; 883946379e7Schristos s/\@footnote\{/\@footnote$docu_doc\{/g; # mark footnotes, cf. pass 4 884946379e7Schristos # 885946379e7Schristos # analyze the tag again 886946379e7Schristos # 887946379e7Schristos if ($tag) { 888946379e7Schristos if (defined($sec2level{$tag}) && $sec2level{$tag} > 0) { 889946379e7Schristos if (/^\@$tag\s+(.+)$/) { 890946379e7Schristos $name = $1; 891946379e7Schristos $name =~ s/\s+$//; 892946379e7Schristos $level = $sec2level{$tag}; 893946379e7Schristos $name = &update_sec_num($tag, $level) . " $name" 894946379e7Schristos if $number_sections && $tag !~ /^unnumbered/; 895946379e7Schristos if ($tag =~ /heading$/) { 896946379e7Schristos push(@lines, &html_debug("\n", __LINE__)); 897946379e7Schristos if ($html_element ne 'body') { 898946379e7Schristos # We are in a nice pickle here. We are trying to get a H? heading 899946379e7Schristos # even though we are not in the body level. So, we convert it to a 900946379e7Schristos # nice, bold, line by itself. 901946379e7Schristos $_ = &debug("\n\n<P><STRONG>$name</STRONG></P>\n\n", __LINE__); 902946379e7Schristos } else { 903946379e7Schristos $_ = &debug("<H$level>$name</H$level>\n", __LINE__); 904946379e7Schristos &html_push_if('body'); 905946379e7Schristos } 906946379e7Schristos print "# heading, section $name, level $level\n" 907946379e7Schristos if $debug & $DEBUG_TOC; 908946379e7Schristos } else { 909946379e7Schristos if ($split_chapter) { 910946379e7Schristos unless ($toplevel) { 911946379e7Schristos # first time we see a "section" 912946379e7Schristos unless ($level == 1) { 913946379e7Schristos warn "$ERROR The first section found is not of level 1: $_"; 914946379e7Schristos warn "$ERROR I'll split on sections of level $level...\n"; 915946379e7Schristos } 916946379e7Schristos $toplevel = $level; 917946379e7Schristos } 918946379e7Schristos if ($level == $toplevel) { 919946379e7Schristos &next_doc; 920946379e7Schristos push(@lines, $SPLITTAG) if $split_num++; 921946379e7Schristos push(@sections, $name); 922946379e7Schristos } 923946379e7Schristos } 924946379e7Schristos $sec_num++; 925946379e7Schristos $docid = "SEC$sec_num"; 926946379e7Schristos $tocid = "TOC$sec_num"; 927946379e7Schristos # check biblio and glossary 928946379e7Schristos $in_bibliography = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*bibliography$/i); 929946379e7Schristos $in_glossary = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*glossary$/i); 930946379e7Schristos # check node 931946379e7Schristos if ($node) { 932946379e7Schristos if ($node2sec{$node}) { 933946379e7Schristos warn "$ERROR Duplicate node found: $node\n"; 934946379e7Schristos } else { 935946379e7Schristos $node2sec{$node} = $name; 936946379e7Schristos $node2href{$node} = "$docu_doc#$docid"; 937946379e7Schristos print "# node $node, section $name, level $level\n" 938946379e7Schristos if $debug & $DEBUG_TOC; 939946379e7Schristos } 940946379e7Schristos $node = ''; 941946379e7Schristos } else { 942946379e7Schristos print "# no node, section $name, level $level\n" 943946379e7Schristos if $debug & $DEBUG_TOC; 944946379e7Schristos } 945946379e7Schristos # update TOC 946946379e7Schristos while ($level > $curlevel) { 947946379e7Schristos $curlevel++; 948946379e7Schristos push(@toc_lines, "<UL>\n"); 949946379e7Schristos } 950946379e7Schristos while ($level < $curlevel) { 951946379e7Schristos $curlevel--; 952946379e7Schristos push(@toc_lines, "</UL>\n"); 953946379e7Schristos } 954946379e7Schristos $_ = "<LI>" . &anchor($tocid, "$docu_doc#$docid", $name, 1); 955946379e7Schristos push(@toc_lines, &substitute_style($_)); 956946379e7Schristos # update DOC 957946379e7Schristos push(@lines, &html_debug("\n", __LINE__)); 958946379e7Schristos &html_reset; 959946379e7Schristos $_ = "<H$level>".&anchor($docid, "$docu_toc#$tocid", $name)."</H$level>\n"; 960946379e7Schristos $_ = &debug($_, __LINE__); 961946379e7Schristos push(@lines, &html_debug("\n", __LINE__)); 962946379e7Schristos } 963946379e7Schristos # update DOC 964946379e7Schristos foreach $line (split(/\n+/, $_)) { 965946379e7Schristos push(@lines, "$line\n"); 966946379e7Schristos } 967946379e7Schristos next; 968946379e7Schristos } else { 969946379e7Schristos warn "$ERROR Bad section line: $_"; 970946379e7Schristos } 971946379e7Schristos } else { 972946379e7Schristos # track variables 973946379e7Schristos $value{$1} = $2, next if /^\@set\s+($VARRE)\s+(.*)$/o; 974946379e7Schristos delete $value{$1}, next if /^\@clear\s+($VARRE)\s*$/o; 975946379e7Schristos # store things 976946379e7Schristos $value{'_setfilename'} = $1, next if /^\@setfilename\s+(.*)$/; 977946379e7Schristos $value{'_settitle'} = $1, next if /^\@settitle\s+(.*)$/; 978946379e7Schristos $value{'_author'} .= "$1\n", next if /^\@author\s+(.*)$/; 979946379e7Schristos $value{'_subtitle'} .= "$1\n", next if /^\@subtitle\s+(.*)$/; 980946379e7Schristos $value{'_title'} .= "$1\n", next if /^\@title\s+(.*)$/; 981946379e7Schristos # index 982946379e7Schristos if (/^\@(..?)index\s+/) { 983946379e7Schristos unless ($valid_index{$1}) { 984946379e7Schristos warn "$ERROR Undefined index command: $_"; 985946379e7Schristos next; 986946379e7Schristos } 987946379e7Schristos $id = 'IDX' . ++$idx_num; 988946379e7Schristos $index = $1 . 'index'; 989946379e7Schristos $what = &substitute_style($'); 990946379e7Schristos $what =~ s/\s+$//; 991946379e7Schristos print "# found $index for '$what' id $id\n" 992946379e7Schristos if $debug & $DEBUG_INDEX; 993946379e7Schristos eval(<<EOC); 994946379e7Schristos if (defined(\$$index\{\$what\})) { 995946379e7Schristos \$$index\{\$what\} .= "$;$docu_doc#$id"; 996946379e7Schristos } else { 997946379e7Schristos \$$index\{\$what\} = "$docu_doc#$id"; 998946379e7Schristos } 999946379e7SchristosEOC 1000946379e7Schristos # 1001946379e7Schristos # dirty hack to see if I can put an invisible anchor... 1002946379e7Schristos # 1003946379e7Schristos if ($html_element eq 'P' || 1004946379e7Schristos $html_element eq 'LI' || 1005946379e7Schristos $html_element eq 'DT' || 1006946379e7Schristos $html_element eq 'DD' || 1007946379e7Schristos $html_element eq 'ADDRESS' || 1008946379e7Schristos $html_element eq 'B' || 1009946379e7Schristos $html_element eq 'BLOCKQUOTE' || 1010946379e7Schristos $html_element eq 'PRE' || 1011946379e7Schristos $html_element eq 'SAMP') { 1012946379e7Schristos push(@lines, &anchor($id, '', $invisible_mark, !$in_pre)); 1013946379e7Schristos } elsif ($html_element eq 'body') { 1014946379e7Schristos push(@lines, &debug("<P>\n", __LINE__)); 1015946379e7Schristos push(@lines, &anchor($id, '', $invisible_mark, !$in_pre)); 1016946379e7Schristos &html_push('P'); 1017946379e7Schristos } elsif ($html_element eq 'DL' || 1018946379e7Schristos $html_element eq 'UL' || 1019946379e7Schristos $html_element eq 'OL' ) { 1020946379e7Schristos $deferred_ref .= &anchor($id, '', $invisible_mark, !$in_pre) . " "; 1021946379e7Schristos } 1022946379e7Schristos next; 1023946379e7Schristos } 1024946379e7Schristos # list item 1025946379e7Schristos if (/^\@itemx?\s+/) { 1026946379e7Schristos $what = $'; 1027946379e7Schristos $what =~ s/\s+$//; 1028946379e7Schristos if ($in_bibliography && $use_bibliography) { 1029946379e7Schristos if ($what =~ /^$BIBRE$/o) { 1030946379e7Schristos $id = 'BIB' . ++$bib_num; 1031946379e7Schristos $bib2href{$what} = "$docu_doc#$id"; 1032946379e7Schristos print "# found bibliography for '$what' id $id\n" 1033946379e7Schristos if $debug & $DEBUG_BIB; 1034946379e7Schristos $what = &anchor($id, '', $what); 1035946379e7Schristos } 1036946379e7Schristos } elsif ($in_glossary && $use_glossary) { 1037946379e7Schristos $id = 'GLOSS' . ++$gloss_num; 1038946379e7Schristos $entry = $what; 1039946379e7Schristos $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/; 1040946379e7Schristos $gloss2href{$entry} = "$docu_doc#$id"; 1041946379e7Schristos print "# found glossary for '$entry' id $id\n" 1042946379e7Schristos if $debug & $DEBUG_GLOSS; 1043946379e7Schristos $what = &anchor($id, '', $what); 1044946379e7Schristos } 1045946379e7Schristos &html_pop_if('P'); 1046946379e7Schristos if ($html_element eq 'DL' || $html_element eq 'DD') { 1047946379e7Schristos if ($things_map{$in_table} && !$what) { 1048946379e7Schristos # special case to allow @table @bullet for instance 1049946379e7Schristos push(@lines, &debug("<DT>$things_map{$in_table}\n", __LINE__)); 1050946379e7Schristos } else { 1051946379e7Schristos push(@lines, &debug("<DT>\@$in_table\{$what\}\n", __LINE__)); 1052946379e7Schristos } 1053946379e7Schristos push(@lines, "<DD>"); 1054946379e7Schristos &html_push('DD') unless $html_element eq 'DD'; 1055946379e7Schristos if ($table_type) { # add also an index 1056946379e7Schristos unshift(@input_spool, "\@${table_type}index $what\n"); 1057946379e7Schristos } 1058946379e7Schristos } elsif ($html_element eq 'TABLE') { 1059946379e7Schristos push(@lines, &debug("<TR><TD>$what</TD>\n", __LINE__)); 1060946379e7Schristos &html_push('TR'); 1061946379e7Schristos } elsif ($html_element eq 'TR') { 1062946379e7Schristos push(@lines, &debug("</TR>\n", __LINE__)); 1063946379e7Schristos push(@lines, &debug("<TR><TD>$what</TD>\n", __LINE__)); 1064946379e7Schristos } else { 1065946379e7Schristos push(@lines, &debug("<LI>$what\n", __LINE__)); 1066946379e7Schristos &html_push('LI') unless $html_element eq 'LI'; 1067946379e7Schristos } 1068946379e7Schristos push(@lines, &html_debug("\n", __LINE__)); 1069946379e7Schristos if ($deferred_ref) { 1070946379e7Schristos push(@lines, &debug("$deferred_ref\n", __LINE__)); 1071946379e7Schristos $deferred_ref = ''; 1072946379e7Schristos } 1073946379e7Schristos next; 1074946379e7Schristos } elsif (/^\@tab\s+(.*)$/) { 1075946379e7Schristos push(@lines, "<TD>$1</TD>\n"); 1076946379e7Schristos next; 1077946379e7Schristos } 1078946379e7Schristos } 1079946379e7Schristos } 1080946379e7Schristos # paragraph separator 1081946379e7Schristos if ($_ eq "\n") { 1082946379e7Schristos next if $#lines >= 0 && $lines[$#lines] eq "\n"; 1083946379e7Schristos if ($html_element eq 'P') { 1084946379e7Schristos push(@lines, "\n"); 1085946379e7Schristos $_ = &debug("</P>\n", __LINE__); 1086946379e7Schristos &html_pop; 1087946379e7Schristos } 1088946379e7Schristos } elsif ($html_element eq 'body' || $html_element eq 'BLOCKQUOTE') { 1089946379e7Schristos push(@lines, "<P>\n"); 1090946379e7Schristos &html_push('P'); 1091946379e7Schristos $_ = &debug($_, __LINE__); 1092946379e7Schristos } 1093946379e7Schristos # otherwise 1094946379e7Schristos push(@lines, $_); 1095946379e7Schristos} 1096946379e7Schristos 1097946379e7Schristos# finish TOC 1098946379e7Schristos$level = 0; 1099946379e7Schristoswhile ($level < $curlevel) { 1100946379e7Schristos $curlevel--; 1101946379e7Schristos push(@toc_lines, "</UL>\n"); 1102946379e7Schristos} 1103946379e7Schristos 1104946379e7Schristosprint "# end of pass 1\n" if $verbose; 1105946379e7Schristos 1106946379e7Schristos#+++############################################################################ 1107946379e7Schristos# # 1108946379e7Schristos# Pass 2/3: handle style, menu, index, cross-reference # 1109946379e7Schristos# # 1110946379e7Schristos#---############################################################################ 1111946379e7Schristos 1112946379e7Schristos@lines2 = (); # whole document (2nd pass) 1113946379e7Schristos@lines3 = (); # whole document (3rd pass) 1114946379e7Schristos$in_menu = 0; # am I inside a menu 1115946379e7Schristos 1116946379e7Schristoswhile (@lines) { 1117946379e7Schristos $_ = shift(@lines); 1118946379e7Schristos # 1119946379e7Schristos # special case (protected sections) 1120946379e7Schristos # 1121946379e7Schristos if (/^$PROTECTTAG/o) { 1122946379e7Schristos push(@lines2, $_); 1123946379e7Schristos next; 1124946379e7Schristos } 1125946379e7Schristos # 1126946379e7Schristos # menu 1127946379e7Schristos # 1128946379e7Schristos $in_menu = 1, push(@lines2, &debug("<UL>\n", __LINE__)), next if /^\@menu\b/; 1129946379e7Schristos $in_menu = 0, push(@lines2, &debug("</UL>\n", __LINE__)), next if /^\@end\s+menu\b/; 1130946379e7Schristos if ($in_menu) { 1131946379e7Schristos if (/^\*\s+($NODERE)::/o) { 1132946379e7Schristos $descr = $'; 1133946379e7Schristos chop($descr); 1134946379e7Schristos &menu_entry($1, $1, $descr); 1135946379e7Schristos } elsif (/^\*\s+(.+):\s+([^\t,\.\n]+)[\t,\.\n]/) { 1136946379e7Schristos $descr = $'; 1137946379e7Schristos chop($descr); 1138946379e7Schristos &menu_entry($1, $2, $descr); 1139946379e7Schristos } elsif (/^\*/) { 1140946379e7Schristos warn "$ERROR Bad menu line: $_"; 1141946379e7Schristos } else { # description continued? 1142946379e7Schristos push(@lines2, $_); 1143946379e7Schristos } 1144946379e7Schristos next; 1145946379e7Schristos } 1146946379e7Schristos # 1147946379e7Schristos # printindex 1148946379e7Schristos # 1149946379e7Schristos if (/^\@printindex\s+(\w\w)\b/) { 1150946379e7Schristos local($index, *ary, @keys, $key, $letter, $last_letter, @refs); 1151946379e7Schristos if ($predefined_index{$1}) { 1152946379e7Schristos $index = $predefined_index{$1} . 'index'; 1153946379e7Schristos } else { 1154946379e7Schristos $index = $1 . 'index'; 1155946379e7Schristos } 1156946379e7Schristos eval("*ary = *$index"); 1157946379e7Schristos @keys = keys(%ary); 1158946379e7Schristos foreach $key (@keys) { 1159946379e7Schristos $_ = $key; 1160946379e7Schristos 1 while s/<(\w+)>\`(.*)\´<\/\1>/$2/; # remove HTML tags with quotes 1161946379e7Schristos 1 while s/<(\w+)>(.*)<\/\1>/$2/; # remove HTML tags 1162946379e7Schristos $_ = &unprotect_html($_); 1163946379e7Schristos &unprotect_texi; 1164946379e7Schristos tr/A-Z/a-z/; # lowercase 1165946379e7Schristos $key2alpha{$key} = $_; 1166946379e7Schristos print "# index $key sorted as $_\n" 1167946379e7Schristos if $key ne $_ && $debug & $DEBUG_INDEX; 1168946379e7Schristos } 1169946379e7Schristos push(@lines2, "Jump to:\n"); 1170946379e7Schristos $last_letter = undef; 1171946379e7Schristos foreach $key (sort byalpha @keys) { 1172946379e7Schristos $letter = substr($key2alpha{$key}, 0, 1); 1173946379e7Schristos $letter = substr($key2alpha{$key}, 0, 2) if $letter eq $;; 1174946379e7Schristos if (!defined($last_letter) || $letter ne $last_letter) { 1175946379e7Schristos push(@lines2, "-\n") if defined($last_letter); 1176946379e7Schristos push(@lines2, "<A HREF=\"#$index\_$letter\">" . &protect_html($letter) . "</A>\n"); 1177946379e7Schristos $last_letter = $letter; 1178946379e7Schristos } 1179946379e7Schristos } 1180946379e7Schristos push(@lines2, "<P>\n"); 1181946379e7Schristos $last_letter = undef; 1182946379e7Schristos foreach $key (sort byalpha @keys) { 1183946379e7Schristos $letter = substr($key2alpha{$key}, 0, 1); 1184946379e7Schristos $letter = substr($key2alpha{$key}, 0, 2) if $letter eq $;; 1185946379e7Schristos if (!defined($last_letter) || $letter ne $last_letter) { 1186946379e7Schristos push(@lines2, "</DIR>\n") if defined($last_letter); 1187946379e7Schristos push(@lines2, "<H2><A NAME=\"$index\_$letter\">" . &protect_html($letter) . "</A></H2>\n"); 1188946379e7Schristos push(@lines2, "<DIR>\n"); 1189946379e7Schristos $last_letter = $letter; 1190946379e7Schristos } 1191946379e7Schristos @refs = (); 1192946379e7Schristos foreach (split(/$;/, $ary{$key})) { 1193946379e7Schristos push(@refs, &anchor('', $_, $key, 0)); 1194946379e7Schristos } 1195946379e7Schristos push(@lines2, "<LI>" . join(", ", @refs) . "\n"); 1196946379e7Schristos } 1197946379e7Schristos push(@lines2, "</DIR>\n") if defined($last_letter); 1198946379e7Schristos next; 1199946379e7Schristos } 1200946379e7Schristos # 1201946379e7Schristos # simple style substitutions 1202946379e7Schristos # 1203946379e7Schristos $_ = &substitute_style($_); 1204946379e7Schristos # 1205946379e7Schristos # xref 1206946379e7Schristos # 1207946379e7Schristos while (/\@(x|px|info|)ref{($XREFRE)(}?)/o) { 1208946379e7Schristos # note: Texinfo may accept other characters 1209946379e7Schristos ($type, $nodes, $full) = ($1, $2, $3); 1210946379e7Schristos ($before, $after) = ($`, $'); 1211946379e7Schristos if (! $full && $after) { 1212946379e7Schristos warn "$ERROR Bad xref (no ending } on line): $_"; 1213946379e7Schristos $_ = "$before$;0${type}ref\{$nodes$after"; 1214946379e7Schristos next; # while xref 1215946379e7Schristos } 1216946379e7Schristos if ($type eq 'x') { 1217946379e7Schristos $type = 'See '; 1218946379e7Schristos } elsif ($type eq 'px') { 1219946379e7Schristos $type = 'see '; 1220946379e7Schristos } elsif ($type eq 'info') { 1221946379e7Schristos $type = 'See Info'; 1222946379e7Schristos } else { 1223946379e7Schristos $type = ''; 1224946379e7Schristos } 1225946379e7Schristos unless ($full) { 1226946379e7Schristos $next = shift(@lines); 1227946379e7Schristos $next = &substitute_style($next); 1228946379e7Schristos chop($nodes); # remove final newline 1229946379e7Schristos if ($next =~ /\}/) { # split on 2 lines 1230946379e7Schristos $nodes .= " $`"; 1231946379e7Schristos $after = $'; 1232946379e7Schristos } else { 1233946379e7Schristos $nodes .= " $next"; 1234946379e7Schristos $next = shift(@lines); 1235946379e7Schristos $next = &substitute_style($next); 1236946379e7Schristos chop($nodes); 1237946379e7Schristos if ($next =~ /\}/) { # split on 3 lines 1238946379e7Schristos $nodes .= " $`"; 1239946379e7Schristos $after = $'; 1240946379e7Schristos } else { 1241946379e7Schristos warn "$ERROR Bad xref (no ending }): $_"; 1242946379e7Schristos $_ = "$before$;0xref\{$nodes$after"; 1243946379e7Schristos unshift(@lines, $next); 1244946379e7Schristos next; # while xref 1245946379e7Schristos } 1246946379e7Schristos } 1247946379e7Schristos } 1248946379e7Schristos $nodes =~ s/\s+/ /g; # remove useless spaces 1249946379e7Schristos @args = split(/\s*,\s*/, $nodes); 1250946379e7Schristos $node = $args[0]; # the node is always the first arg 1251946379e7Schristos &normalise_node($node); 1252946379e7Schristos $sec = $node2sec{$node}; 1253946379e7Schristos if (@args == 5) { # reference to another manual 1254946379e7Schristos $sec = $args[2] || $node; 1255946379e7Schristos $man = $args[4] || $args[3]; 1256946379e7Schristos $_ = "${before}${type}section ‘$sec’ in \@cite{$man}$after"; 1257946379e7Schristos } elsif ($type =~ /Info/) { # inforef 1258946379e7Schristos warn "$ERROR Wrong number of arguments: $_" unless @args == 3; 1259946379e7Schristos ($nn, $_, $in) = @args; 1260946379e7Schristos $_ = "${before}${type} file ‘$in’, node ‘$nn’$after"; 1261946379e7Schristos } elsif ($sec) { 1262946379e7Schristos $href = $node2href{$node}; 1263946379e7Schristos $_ = "${before}${type}section " . &anchor('', $href, $sec) . $after; 1264946379e7Schristos } else { 1265946379e7Schristos warn "$ERROR Undefined node ($node): $_"; 1266946379e7Schristos $_ = "$before$;0xref{$nodes}$after"; 1267946379e7Schristos } 1268946379e7Schristos } 1269946379e7Schristos # 1270946379e7Schristos # try to guess bibliography references or glossary terms 1271946379e7Schristos # 1272946379e7Schristos unless (/^<H\d><A NAME=\"SEC\d/) { 1273946379e7Schristos if ($use_bibliography) { 1274946379e7Schristos $done = ''; 1275946379e7Schristos while (/$BIBRE/o) { 1276946379e7Schristos ($pre, $what, $post) = ($`, $&, $'); 1277946379e7Schristos $href = $bib2href{$what}; 1278946379e7Schristos if (defined($href) && $post !~ /^[^<]*<\/A>/) { 1279946379e7Schristos $done .= $pre . &anchor('', $href, $what); 1280946379e7Schristos } else { 1281946379e7Schristos $done .= "$pre$what"; 1282946379e7Schristos } 1283946379e7Schristos $_ = $post; 1284946379e7Schristos } 1285946379e7Schristos $_ = $done . $_; 1286946379e7Schristos } 1287946379e7Schristos if ($use_glossary) { 1288946379e7Schristos $done = ''; 1289946379e7Schristos while (/\b\w+\b/) { 1290946379e7Schristos ($pre, $what, $post) = ($`, $&, $'); 1291946379e7Schristos $entry = $what; 1292946379e7Schristos $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/; 1293946379e7Schristos $href = $gloss2href{$entry}; 1294946379e7Schristos if (defined($href) && $post !~ /^[^<]*<\/A>/) { 1295946379e7Schristos $done .= $pre . &anchor('', $href, $what); 1296946379e7Schristos } else { 1297946379e7Schristos $done .= "$pre$what"; 1298946379e7Schristos } 1299946379e7Schristos $_ = $post; 1300946379e7Schristos } 1301946379e7Schristos $_ = $done . $_; 1302946379e7Schristos } 1303946379e7Schristos } 1304946379e7Schristos # otherwise 1305946379e7Schristos push(@lines2, $_); 1306946379e7Schristos} 1307946379e7Schristosprint "# end of pass 2\n" if $verbose; 1308946379e7Schristos 1309946379e7Schristos# 1310946379e7Schristos# split style substitutions 1311946379e7Schristos# 1312946379e7Schristoswhile (@lines2) { 1313946379e7Schristos $_ = shift(@lines2); 1314946379e7Schristos # 1315946379e7Schristos # special case (protected sections) 1316946379e7Schristos # 1317946379e7Schristos if (/^$PROTECTTAG/o) { 1318946379e7Schristos push(@lines3, $_); 1319946379e7Schristos next; 1320946379e7Schristos } 1321946379e7Schristos # 1322946379e7Schristos # split style substitutions 1323946379e7Schristos # 1324946379e7Schristos $old = ''; 1325946379e7Schristos while ($old ne $_) { 1326946379e7Schristos $old = $_; 1327946379e7Schristos if (/\@(\w+|"|\~|,|\^)\{/) { 1328946379e7Schristos ($before, $style, $after) = ($`, $1, $'); 1329946379e7Schristos if (defined($style_map{$style})) { 1330946379e7Schristos $_ = $after; 1331946379e7Schristos $text = ''; 1332946379e7Schristos $after = ''; 1333946379e7Schristos $failed = 1; 1334946379e7Schristos while (@lines2) { 1335946379e7Schristos if (/\}/) { 1336946379e7Schristos $text .= $`; 1337946379e7Schristos $after = $'; 1338946379e7Schristos $failed = 0; 1339946379e7Schristos last; 1340946379e7Schristos } else { 1341946379e7Schristos $text .= $_; 1342946379e7Schristos $_ = shift(@lines2); 1343946379e7Schristos } 1344946379e7Schristos } 1345946379e7Schristos if ($failed) { 1346946379e7Schristos die "* Bad syntax (\@$style) after: $before\n"; 1347946379e7Schristos } else { 1348946379e7Schristos $text = &apply_style($style, $text); 1349946379e7Schristos $_ = "$before$text$after"; 1350946379e7Schristos } 1351946379e7Schristos } 1352946379e7Schristos } 1353946379e7Schristos } 1354946379e7Schristos # otherwise 1355946379e7Schristos push(@lines3, $_); 1356946379e7Schristos} 1357946379e7Schristosprint "# end of pass 3\n" if $verbose; 1358946379e7Schristos 1359946379e7Schristos#+++############################################################################ 1360946379e7Schristos# # 1361946379e7Schristos# Pass 4: foot notes, final cleanup # 1362946379e7Schristos# # 1363946379e7Schristos#---############################################################################ 1364946379e7Schristos 1365946379e7Schristos@foot_lines = (); # footnotes 1366946379e7Schristos@doc_lines = (); # final document 1367946379e7Schristos$end_of_para = 0; # true if last line is <P> 1368946379e7Schristos 1369946379e7Schristoswhile (@lines3) { 1370946379e7Schristos $_ = shift(@lines3); 1371946379e7Schristos # 1372946379e7Schristos # special case (protected sections) 1373946379e7Schristos # 1374946379e7Schristos if (/^$PROTECTTAG/o) { 1375946379e7Schristos push(@doc_lines, $_); 1376946379e7Schristos $end_of_para = 0; 1377946379e7Schristos next; 1378946379e7Schristos } 1379946379e7Schristos # 1380946379e7Schristos # footnotes 1381946379e7Schristos # 1382946379e7Schristos while (/\@footnote([^\{\s]+)\{/) { 1383946379e7Schristos ($before, $d, $after) = ($`, $1, $'); 1384946379e7Schristos $_ = $after; 1385946379e7Schristos $text = ''; 1386946379e7Schristos $after = ''; 1387946379e7Schristos $failed = 1; 1388946379e7Schristos while (@lines3) { 1389946379e7Schristos if (/\}/) { 1390946379e7Schristos $text .= $`; 1391946379e7Schristos $after = $'; 1392946379e7Schristos $failed = 0; 1393946379e7Schristos last; 1394946379e7Schristos } else { 1395946379e7Schristos $text .= $_; 1396946379e7Schristos $_ = shift(@lines3); 1397946379e7Schristos } 1398946379e7Schristos } 1399946379e7Schristos if ($failed) { 1400946379e7Schristos die "* Bad syntax (\@footnote) after: $before\n"; 1401946379e7Schristos } else { 1402946379e7Schristos $foot_num++; 1403946379e7Schristos $docid = "DOCF$foot_num"; 1404946379e7Schristos $footid = "FOOT$foot_num"; 1405946379e7Schristos $foot = "($foot_num)"; 1406946379e7Schristos push(@foot_lines, "<H3>" . &anchor($footid, "$d#$docid", $foot) . "</H3>\n"); 1407946379e7Schristos $text = "<P>$text" unless $text =~ /^\s*<P>/; 1408946379e7Schristos push(@foot_lines, "$text\n"); 1409946379e7Schristos $_ = $before . &anchor($docid, "$docu_foot#$footid", $foot) . $after; 1410946379e7Schristos } 1411946379e7Schristos } 1412946379e7Schristos # 1413946379e7Schristos # remove unnecessary <P> 1414946379e7Schristos # 1415946379e7Schristos if (/^\s*<P>\s*$/) { 1416946379e7Schristos next if $end_of_para++; 1417946379e7Schristos } else { 1418946379e7Schristos $end_of_para = 0; 1419946379e7Schristos } 1420946379e7Schristos # otherwise 1421946379e7Schristos push(@doc_lines, $_); 1422946379e7Schristos} 1423946379e7Schristosprint "# end of pass 4\n" if $verbose; 1424946379e7Schristos 1425946379e7Schristos#+++############################################################################ 1426946379e7Schristos# # 1427946379e7Schristos# Pass 5: print things # 1428946379e7Schristos# # 1429946379e7Schristos#---############################################################################ 1430946379e7Schristos 1431946379e7Schristos$header = <<EOT; 1432946379e7Schristos<!-- This HTML file has been created by $THISPROG 1433946379e7Schristos from $docu on $TODAY --> 1434946379e7SchristosEOT 1435946379e7Schristos 1436946379e7Schristos$full_title = $value{'_title'} || $value{'_settitle'} || "Untitled Document"; 1437946379e7Schristos$title = $value{'_settitle'} || $full_title; 1438946379e7Schristos$_ = &substitute_style($full_title); 1439946379e7Schristos&unprotect_texi; 1440946379e7Schristoss/\n$//; # rmv last \n (if any) 1441946379e7Schristos$full_title = "<H1>" . join("</H1>\n<H1>", split(/\n/, $_)) . "</H1>\n"; 1442946379e7Schristos 1443946379e7Schristos# 1444946379e7Schristos# print ToC 1445946379e7Schristos# 1446946379e7Schristosif (!$monolithic && @toc_lines) { 1447946379e7Schristos if (open(FILE, "> $docu_toc")) { 1448946379e7Schristos print "# creating $docu_toc...\n" if $verbose; 1449946379e7Schristos &print_toplevel_header("$title - Table of Contents"); 1450946379e7Schristos &print_ruler; 1451946379e7Schristos &print(*toc_lines, FILE); 1452946379e7Schristos &print_toplevel_footer; 1453946379e7Schristos close(FILE); 1454946379e7Schristos } else { 1455946379e7Schristos warn "$ERROR Can't write to $docu_toc: $!\n"; 1456946379e7Schristos } 1457946379e7Schristos} 1458946379e7Schristos 1459946379e7Schristos# 1460946379e7Schristos# print footnotes 1461946379e7Schristos# 1462946379e7Schristosif (!$monolithic && @foot_lines) { 1463946379e7Schristos if (open(FILE, "> $docu_foot")) { 1464946379e7Schristos print "# creating $docu_foot...\n" if $verbose; 1465946379e7Schristos &print_toplevel_header("$title - Footnotes"); 1466946379e7Schristos &print_ruler; 1467946379e7Schristos &print(*foot_lines, FILE); 1468946379e7Schristos &print_toplevel_footer; 1469946379e7Schristos close(FILE); 1470946379e7Schristos } else { 1471946379e7Schristos warn "$ERROR Can't write to $docu_foot: $!\n"; 1472946379e7Schristos } 1473946379e7Schristos} 1474946379e7Schristos 1475946379e7Schristos# 1476946379e7Schristos# print document 1477946379e7Schristos# 1478946379e7Schristosif ($split_chapter || $split_node) { # split 1479946379e7Schristos $doc_num = 0; 1480946379e7Schristos $last_num = scalar(@sections); 1481946379e7Schristos $first_doc = &doc_name(1); 1482946379e7Schristos $last_doc = &doc_name($last_num); 1483946379e7Schristos while (@sections) { 1484946379e7Schristos $section = shift(@sections); 1485946379e7Schristos &next_doc; 1486946379e7Schristos if (open(FILE, "> $docu_doc")) { 1487946379e7Schristos print "# creating $docu_doc...\n" if $verbose; 1488946379e7Schristos &print_header("$title - $section"); 1489946379e7Schristos $prev_doc = ($doc_num == 1 ? undef : &doc_name($doc_num - 1)); 1490946379e7Schristos $next_doc = ($doc_num == $last_num ? undef : &doc_name($doc_num + 1)); 1491946379e7Schristos $navigation = "Go to the "; 1492946379e7Schristos $navigation .= ($prev_doc ? &anchor('', $first_doc, "first") : "first"); 1493946379e7Schristos $navigation .= ", "; 1494946379e7Schristos $navigation .= ($prev_doc ? &anchor('', $prev_doc, "previous") : "previous"); 1495946379e7Schristos $navigation .= ", "; 1496946379e7Schristos $navigation .= ($next_doc ? &anchor('', $next_doc, "next") : "next"); 1497946379e7Schristos $navigation .= ", "; 1498946379e7Schristos $navigation .= ($next_doc ? &anchor('', $last_doc, "last") : "last"); 1499946379e7Schristos $navigation .= " section, " . &anchor('', $docu_toc, "table of contents") . ".\n"; 1500946379e7Schristos print FILE $navigation; 1501946379e7Schristos &print_ruler; 1502946379e7Schristos # find corresponding lines 1503946379e7Schristos @tmp_lines = (); 1504946379e7Schristos while (@doc_lines) { 1505946379e7Schristos $_ = shift(@doc_lines); 1506946379e7Schristos last if ($_ eq $SPLITTAG); 1507946379e7Schristos push(@tmp_lines, $_); 1508946379e7Schristos } 1509946379e7Schristos &print(*tmp_lines, FILE); 1510946379e7Schristos &print_ruler; 1511946379e7Schristos print FILE $navigation; 1512946379e7Schristos &print_footer; 1513946379e7Schristos close(FILE); 1514946379e7Schristos } else { 1515946379e7Schristos warn "$ERROR Can't write to $docu_doc: $!\n"; 1516946379e7Schristos } 1517946379e7Schristos } 1518946379e7Schristos} else { # not split 1519946379e7Schristos if (open(FILE, "> $docu_doc")) { 1520946379e7Schristos print "# creating $docu_doc...\n" if $verbose; 1521946379e7Schristos if ($monolithic || !@toc_lines) { 1522946379e7Schristos &print_toplevel_header($title); 1523946379e7Schristos } else { 1524946379e7Schristos &print_header($title); 1525946379e7Schristos print FILE $full_title; 1526946379e7Schristos } 1527946379e7Schristos if ($monolithic && @toc_lines) { 1528946379e7Schristos &print_ruler; 1529946379e7Schristos print FILE "<H1>Table of Contents</H1>\n"; 1530946379e7Schristos &print(*toc_lines, FILE); 1531946379e7Schristos } 1532946379e7Schristos &print_ruler; 1533946379e7Schristos &print(*doc_lines, FILE); 1534946379e7Schristos if ($monolithic && @foot_lines) { 1535946379e7Schristos &print_ruler; 1536946379e7Schristos print FILE "<H1>Footnotes</H1>\n"; 1537946379e7Schristos &print(*foot_lines, FILE); 1538946379e7Schristos } 1539946379e7Schristos if ($monolithic || !@toc_lines) { 1540946379e7Schristos &print_toplevel_footer; 1541946379e7Schristos } else { 1542946379e7Schristos &print_footer; 1543946379e7Schristos } 1544946379e7Schristos close(FILE); 1545946379e7Schristos } else { 1546946379e7Schristos warn "$ERROR Can't write to $docu_doc: $!\n"; 1547946379e7Schristos } 1548946379e7Schristos} 1549946379e7Schristos 1550946379e7Schristosprint "# that's all folks\n" if $verbose; 1551946379e7Schristos 1552946379e7Schristos#+++############################################################################ 1553946379e7Schristos# # 1554946379e7Schristos# Low level functions # 1555946379e7Schristos# # 1556946379e7Schristos#---############################################################################ 1557946379e7Schristos 1558946379e7Schristossub update_sec_num { 1559946379e7Schristos local($name, $level) = @_; 1560946379e7Schristos 1561946379e7Schristos $level--; # here we start at 0 1562946379e7Schristos if ($name =~ /^appendix/) { 1563946379e7Schristos # appendix style 1564*95b39c65Schristos if (@appendix_sec_num) { 1565946379e7Schristos &incr_sec_num($level, @appendix_sec_num); 1566946379e7Schristos } else { 1567946379e7Schristos @appendix_sec_num = ('A', 0, 0, 0); 1568946379e7Schristos } 1569946379e7Schristos return(join('.', @appendix_sec_num[0..$level])); 1570946379e7Schristos } else { 1571946379e7Schristos # normal style 1572*95b39c65Schristos if (@normal_sec_num) { 1573946379e7Schristos &incr_sec_num($level, @normal_sec_num); 1574946379e7Schristos } else { 1575946379e7Schristos @normal_sec_num = (1, 0, 0, 0); 1576946379e7Schristos } 1577946379e7Schristos return(join('.', @normal_sec_num[0..$level])); 1578946379e7Schristos } 1579946379e7Schristos} 1580946379e7Schristos 1581946379e7Schristossub incr_sec_num { 1582946379e7Schristos local($level, $l); 1583946379e7Schristos $level = shift(@_); 1584946379e7Schristos $_[$level]++; 1585946379e7Schristos foreach $l ($level+1 .. 3) { 1586946379e7Schristos $_[$l] = 0; 1587946379e7Schristos } 1588946379e7Schristos} 1589946379e7Schristos 1590946379e7Schristossub check { 1591946379e7Schristos local($_, %seen, %context, $before, $match, $after); 1592946379e7Schristos 1593946379e7Schristos while (<>) { 1594946379e7Schristos if (/\@(\*|\.|\:|\@|\{|\})/) { 1595946379e7Schristos $seen{$&}++; 1596946379e7Schristos $context{$&} .= "> $_" if $verbose; 1597946379e7Schristos $_ = "$`XX$'"; 1598946379e7Schristos redo; 1599946379e7Schristos } 1600946379e7Schristos if (/\@(\w+)/) { 1601946379e7Schristos ($before, $match, $after) = ($`, $&, $'); 1602946379e7Schristos if ($before =~ /\b[\w-]+$/ && $after =~ /^[\w-.]*\b/) { # e-mail address 1603946379e7Schristos $seen{'e-mail address'}++; 1604946379e7Schristos $context{'e-mail address'} .= "> $_" if $verbose; 1605946379e7Schristos } else { 1606946379e7Schristos $seen{$match}++; 1607946379e7Schristos $context{$match} .= "> $_" if $verbose; 1608946379e7Schristos } 1609946379e7Schristos $match =~ s/^\@/X/; 1610946379e7Schristos $_ = "$before$match$after"; 1611946379e7Schristos redo; 1612946379e7Schristos } 1613946379e7Schristos } 1614946379e7Schristos 1615946379e7Schristos foreach (sort(keys(%seen))) { 1616946379e7Schristos if ($verbose) { 1617946379e7Schristos print "$_\n"; 1618946379e7Schristos print $context{$_}; 1619946379e7Schristos } else { 1620946379e7Schristos print "$_ ($seen{$_})\n"; 1621946379e7Schristos } 1622946379e7Schristos } 1623946379e7Schristos} 1624946379e7Schristos 1625946379e7Schristossub open { 1626946379e7Schristos local($name) = @_; 1627946379e7Schristos 1628946379e7Schristos ++$fh_name; 1629946379e7Schristos if (open($fh_name, $name)) { 1630946379e7Schristos unshift(@fhs, $fh_name); 1631946379e7Schristos } else { 1632946379e7Schristos warn "$ERROR Can't read file $name: $!\n"; 1633946379e7Schristos } 1634946379e7Schristos} 1635946379e7Schristos 1636946379e7Schristossub init_input { 1637946379e7Schristos @fhs = (); # hold the file handles to read 1638946379e7Schristos @input_spool = (); # spooled lines to read 1639946379e7Schristos $fh_name = 'FH000'; 1640946379e7Schristos &open($docu); 1641946379e7Schristos} 1642946379e7Schristos 1643946379e7Schristossub next_line { 1644946379e7Schristos local($fh, $line); 1645946379e7Schristos 1646946379e7Schristos if (@input_spool) { 1647946379e7Schristos $line = shift(@input_spool); 1648946379e7Schristos return($line); 1649946379e7Schristos } 1650946379e7Schristos while (@fhs) { 1651946379e7Schristos $fh = $fhs[0]; 1652946379e7Schristos $line = <$fh>; 1653946379e7Schristos return($line) if $line; 1654946379e7Schristos close($fh); 1655946379e7Schristos shift(@fhs); 1656946379e7Schristos } 1657946379e7Schristos return(undef); 1658946379e7Schristos} 1659946379e7Schristos 1660946379e7Schristos# used in pass 1, use &next_line 1661946379e7Schristossub skip_until { 1662946379e7Schristos local($tag) = @_; 1663946379e7Schristos local($_); 1664946379e7Schristos 1665946379e7Schristos while ($_ = &next_line) { 1666946379e7Schristos return if /^\@end\s+$tag\s*$/; 1667946379e7Schristos } 1668946379e7Schristos die "* Failed to find '$tag' after: " . $lines[$#lines]; 1669946379e7Schristos} 1670946379e7Schristos 1671946379e7Schristos# 1672946379e7Schristos# HTML stacking to have a better HTML output 1673946379e7Schristos# 1674946379e7Schristos 1675946379e7Schristossub html_reset { 1676946379e7Schristos @html_stack = ('html'); 1677946379e7Schristos $html_element = 'body'; 1678946379e7Schristos} 1679946379e7Schristos 1680946379e7Schristossub html_push { 1681946379e7Schristos local($what) = @_; 1682946379e7Schristos push(@html_stack, $html_element); 1683946379e7Schristos $html_element = $what; 1684946379e7Schristos} 1685946379e7Schristos 1686946379e7Schristossub html_push_if { 1687946379e7Schristos local($what) = @_; 1688946379e7Schristos push(@html_stack, $html_element) 1689946379e7Schristos if ($html_element && $html_element ne 'P'); 1690946379e7Schristos $html_element = $what; 1691946379e7Schristos} 1692946379e7Schristos 1693946379e7Schristossub html_pop { 1694946379e7Schristos $html_element = pop(@html_stack); 1695946379e7Schristos} 1696946379e7Schristos 1697946379e7Schristossub html_pop_if { 1698946379e7Schristos local($elt); 1699946379e7Schristos 1700946379e7Schristos if (@_) { 1701946379e7Schristos foreach $elt (@_) { 1702946379e7Schristos if ($elt eq $html_element) { 1703946379e7Schristos $html_element = pop(@html_stack) if @html_stack; 1704946379e7Schristos last; 1705946379e7Schristos } 1706946379e7Schristos } 1707946379e7Schristos } else { 1708946379e7Schristos $html_element = pop(@html_stack) if @html_stack; 1709946379e7Schristos } 1710946379e7Schristos} 1711946379e7Schristos 1712946379e7Schristossub html_debug { 1713946379e7Schristos local($what, $line) = @_; 1714946379e7Schristos return("<!-- $line @html_stack, $html_element -->$what") 1715946379e7Schristos if $debug & $DEBUG_HTML; 1716946379e7Schristos return($what); 1717946379e7Schristos} 1718946379e7Schristos 1719946379e7Schristos# to debug the output... 1720946379e7Schristossub debug { 1721946379e7Schristos local($what, $line) = @_; 1722946379e7Schristos return("<!-- $line -->$what") 1723946379e7Schristos if $debug & $DEBUG_HTML; 1724946379e7Schristos return($what); 1725946379e7Schristos} 1726946379e7Schristos 1727946379e7Schristossub normalise_node { 1728946379e7Schristos $_[0] =~ s/\s+/ /g; 1729946379e7Schristos $_[0] =~ s/ $//; 1730946379e7Schristos $_[0] =~ s/^ //; 1731946379e7Schristos} 1732946379e7Schristos 1733946379e7Schristossub menu_entry { 1734946379e7Schristos local($entry, $node, $descr) = @_; 1735946379e7Schristos local($href); 1736946379e7Schristos 1737946379e7Schristos &normalise_node($node); 1738946379e7Schristos $href = $node2href{$node}; 1739946379e7Schristos if ($href) { 1740946379e7Schristos $descr =~ s/^\s+//; 1741946379e7Schristos $descr = ": $descr" if $descr; 1742946379e7Schristos push(@lines2, "<LI>" . &anchor('', $href, $entry) . "$descr\n"); 1743946379e7Schristos } else { 1744946379e7Schristos warn "$ERROR Undefined node ($node): $_"; 1745946379e7Schristos } 1746946379e7Schristos} 1747946379e7Schristos 1748946379e7Schristossub do_ctrl { "^$_[0]" } 1749946379e7Schristos 1750946379e7Schristossub do_email { 1751946379e7Schristos local($addr, $text) = split(/,\s*/, $_[0]); 1752946379e7Schristos 1753946379e7Schristos $text = $addr unless $text; 1754946379e7Schristos &anchor('', "mailto:$addr", $text); 1755946379e7Schristos} 1756946379e7Schristos 1757946379e7Schristossub do_sc { "\U$_[0]\E" } 1758946379e7Schristos 1759946379e7Schristossub do_uref { 1760946379e7Schristos local($url, $text) = split(/,\s*/, $_[0]); 1761946379e7Schristos 1762946379e7Schristos $text = $url unless $text; 1763946379e7Schristos &anchor('', $url, $text); 1764946379e7Schristos} 1765946379e7Schristos 1766946379e7Schristossub do_url { &anchor('', $_[0], $_[0]) } 1767946379e7Schristos 1768946379e7Schristossub do_diaeresis { return "&$_[0]uml;"; } 1769946379e7Schristossub do_acuteaccent { return "&$_[0]acute;"; } 1770946379e7Schristossub do_graveaccent { return "&$_[0]grave;"; } 1771946379e7Schristossub do_tildeaccent { return "&$_[0]tilde;"; } 1772946379e7Schristossub do_cedilla { return "&$_[0]cedil;"; } 1773946379e7Schristossub do_circumflex { return "&$_[0]circ;"; } 1774946379e7Schristos 1775946379e7Schristossub apply_style { 1776946379e7Schristos local($texi_style, $text) = @_; 1777946379e7Schristos local($style); 1778946379e7Schristos 1779946379e7Schristos $style = $style_map{$texi_style}; 1780946379e7Schristos if (defined($style)) { # known style 1781946379e7Schristos if ($style =~ /^\"/) { # add quotes 1782946379e7Schristos $style = $'; 1783946379e7Schristos $text = "\‘$text\’"; 1784946379e7Schristos } 1785946379e7Schristos if ($style =~ /^\&/) { # custom 1786946379e7Schristos $style = $'; 1787946379e7Schristos $text = &$style($text); 1788946379e7Schristos } elsif ($style) { # good style 1789946379e7Schristos $text = "<$style>$text</$style>"; 1790946379e7Schristos } else { # no style 1791946379e7Schristos } 1792946379e7Schristos } else { # unknown style 1793946379e7Schristos $text = undef; 1794946379e7Schristos } 1795946379e7Schristos return($text); 1796946379e7Schristos} 1797946379e7Schristos 1798946379e7Schristos# remove Texinfo styles 1799946379e7Schristossub remove_style { 1800946379e7Schristos local($_) = @_; 1801946379e7Schristos s/\@\w+{([^\{\}]+)}/$1/g; 1802946379e7Schristos return($_); 1803946379e7Schristos} 1804946379e7Schristos 1805946379e7Schristossub substitute_style { 1806946379e7Schristos local($_) = @_; 1807946379e7Schristos local($changed, $done, $style, $text); 1808946379e7Schristos 1809946379e7Schristos $changed = 1; 1810946379e7Schristos while ($changed) { 1811946379e7Schristos $changed = 0; 1812946379e7Schristos $done = ''; 1813946379e7Schristos while (/\@(\w+|"|\~|,|\^){([^\{\}]+)}/) { 1814946379e7Schristos $text = &apply_style($1, $2); 1815946379e7Schristos if ($text) { 1816946379e7Schristos $_ = "$`$text$'"; 1817946379e7Schristos $changed = 1; 1818946379e7Schristos } else { 1819946379e7Schristos $done .= "$`\@$1"; 1820946379e7Schristos $_ = "{$2}$'"; 1821946379e7Schristos } 1822946379e7Schristos } 1823946379e7Schristos $_ = $done . $_; 1824946379e7Schristos } 1825946379e7Schristos return($_); 1826946379e7Schristos} 1827946379e7Schristos 1828946379e7Schristossub anchor { 1829946379e7Schristos local($name, $href, $text, $newline) = @_; 1830946379e7Schristos local($result); 1831946379e7Schristos 1832946379e7Schristos $result = "<A"; 1833946379e7Schristos $result .= " NAME=\"$name\"" if $name; 1834946379e7Schristos $result .= " HREF=\"$href\"" if $href; 1835946379e7Schristos $result .= ">$text</A>"; 1836946379e7Schristos $result .= "\n" if $newline; 1837946379e7Schristos return($result); 1838946379e7Schristos} 1839946379e7Schristos 1840946379e7Schristossub pretty_date { 1841946379e7Schristos local(@MoY, $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst); 1842946379e7Schristos 1843946379e7Schristos @MoY = ('January', 'Febuary', 'March', 'April', 'May', 'June', 1844946379e7Schristos 'July', 'August', 'September', 'October', 'November', 'December'); 1845946379e7Schristos ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time); 1846946379e7Schristos $year += ($year < 70) ? 2000 : 1900; 1847946379e7Schristos return("$mday $MoY[$mon] $year"); 1848946379e7Schristos} 1849946379e7Schristos 1850946379e7Schristossub doc_name { 1851946379e7Schristos local($num) = @_; 1852946379e7Schristos 1853946379e7Schristos return("${docu_name}_$num.html"); 1854946379e7Schristos} 1855946379e7Schristos 1856946379e7Schristossub next_doc { 1857946379e7Schristos $docu_doc = &doc_name(++$doc_num); 1858946379e7Schristos} 1859946379e7Schristos 1860946379e7Schristossub print { 1861946379e7Schristos local(*lines, $fh) = @_; 1862946379e7Schristos local($_); 1863946379e7Schristos 1864946379e7Schristos while (@lines) { 1865946379e7Schristos $_ = shift(@lines); 1866946379e7Schristos if (/^$PROTECTTAG/o) { 1867946379e7Schristos $_ = $tag2pro{$_}; 1868946379e7Schristos } else { 1869946379e7Schristos &unprotect_texi; 1870946379e7Schristos } 1871946379e7Schristos print $fh $_; 1872946379e7Schristos } 1873946379e7Schristos} 1874946379e7Schristos 1875946379e7Schristossub print_ruler { 1876946379e7Schristos print FILE "<P><HR><P>\n"; 1877946379e7Schristos} 1878946379e7Schristos 1879946379e7Schristossub print_header { 1880946379e7Schristos local($_); 1881946379e7Schristos 1882946379e7Schristos # clean the title 1883946379e7Schristos $_ = &remove_style($_[0]); 1884946379e7Schristos &unprotect_texi; 1885946379e7Schristos # print the header 1886946379e7Schristos if ($doctype eq 'html2') { 1887946379e7Schristos print FILE $html2_doctype; 1888946379e7Schristos } elsif ($doctype) { 1889946379e7Schristos print FILE $doctype; 1890946379e7Schristos } 1891946379e7Schristos print FILE <<EOT; 1892946379e7Schristos<HTML> 1893946379e7Schristos<HEAD> 1894946379e7Schristos$header 1895946379e7Schristos<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"> 1896946379e7Schristos<TITLE>$_</TITLE> 1897946379e7Schristos</HEAD> 1898946379e7Schristos<BODY> 1899946379e7SchristosEOT 1900946379e7Schristos} 1901946379e7Schristos 1902946379e7Schristossub print_toplevel_header { 1903946379e7Schristos local($_); 1904946379e7Schristos 1905946379e7Schristos &print_header; # pass given arg... 1906946379e7Schristos print FILE $full_title; 1907946379e7Schristos if ($value{'_subtitle'}) { 1908946379e7Schristos $value{'_subtitle'} =~ s/\n+$//; 1909946379e7Schristos foreach (split(/\n/, $value{'_subtitle'})) { 1910946379e7Schristos $_ = &substitute_style($_); 1911946379e7Schristos &unprotect_texi; 1912946379e7Schristos print FILE "<H2>$_</H2>\n"; 1913946379e7Schristos } 1914946379e7Schristos } 1915946379e7Schristos if ($value{'_author'}) { 1916946379e7Schristos $value{'_author'} =~ s/\n+$//; 1917946379e7Schristos foreach (split(/\n/, $value{'_author'})) { 1918946379e7Schristos $_ = &substitute_style($_); 1919946379e7Schristos &unprotect_texi; 1920946379e7Schristos s/[\w.-]+\@[\w.-]+/<A HREF="mailto:$&">$&<\/A>/g; 1921946379e7Schristos print FILE "<ADDRESS>$_</ADDRESS>\n"; 1922946379e7Schristos } 1923946379e7Schristos } 1924946379e7Schristos print FILE "<P>\n"; 1925946379e7Schristos} 1926946379e7Schristos 1927946379e7Schristossub print_footer { 1928946379e7Schristos print FILE <<EOT; 1929946379e7Schristos</BODY> 1930946379e7Schristos</HTML> 1931946379e7SchristosEOT 1932946379e7Schristos} 1933946379e7Schristos 1934946379e7Schristossub print_toplevel_footer { 1935946379e7Schristos &print_ruler; 1936946379e7Schristos print FILE <<EOT; 1937946379e7SchristosThis document was generated on $TODAY using the 1938946379e7Schristos<A HREF=\"$HOMEPAGE\">texi2html</A> 1939946379e7Schristostranslator version 1.52b.</P> 1940946379e7SchristosEOT 1941946379e7Schristos &print_footer; 1942946379e7Schristos} 1943946379e7Schristos 1944946379e7Schristossub protect_texi { 1945946379e7Schristos # protect @ { } ` ' 1946946379e7Schristos s/\@\@/$;0/go; 1947946379e7Schristos s/\@\{/$;1/go; 1948946379e7Schristos s/\@\}/$;2/go; 1949946379e7Schristos s/\@\`/$;3/go; 1950946379e7Schristos s/\@\'/$;4/go; 1951946379e7Schristos} 1952946379e7Schristos 1953946379e7Schristossub protect_html { 1954946379e7Schristos local($what) = @_; 1955946379e7Schristos # protect & < > 1956946379e7Schristos $what =~ s/\&/\&\#38;/g; 1957946379e7Schristos $what =~ s/\</\&\#60;/g; 1958946379e7Schristos $what =~ s/\>/\&\#62;/g; 1959946379e7Schristos # but recognize some HTML things 1960946379e7Schristos $what =~ s/\&\#60;\/A\&\#62;/<\/A>/g; # </A> 1961946379e7Schristos $what =~ s/\&\#60;A ([^\&]+)\&\#62;/<A $1>/g; # <A [^&]+> 1962946379e7Schristos $what =~ s/\&\#60;IMG ([^\&]+)\&\#62;/<IMG $1>/g; # <IMG [^&]+> 1963946379e7Schristos return($what); 1964946379e7Schristos} 1965946379e7Schristos 1966946379e7Schristossub unprotect_texi { 1967946379e7Schristos s/$;0/\@/go; 1968946379e7Schristos s/$;1/\{/go; 1969946379e7Schristos s/$;2/\}/go; 1970946379e7Schristos s/$;3/\`/go; 1971946379e7Schristos s/$;4/\'/go; 1972946379e7Schristos} 1973946379e7Schristos 1974946379e7Schristossub unprotect_html { 1975946379e7Schristos local($what) = @_; 1976946379e7Schristos $what =~ s/\&\#38;/\&/g; 1977946379e7Schristos $what =~ s/\&\#60;/\</g; 1978946379e7Schristos $what =~ s/\&\#62;/\>/g; 1979946379e7Schristos return($what); 1980946379e7Schristos} 1981946379e7Schristos 1982946379e7Schristossub byalpha { 1983946379e7Schristos $key2alpha{$a} cmp $key2alpha{$b}; 1984946379e7Schristos} 1985946379e7Schristos 1986946379e7Schristos############################################################################## 1987946379e7Schristos 1988946379e7Schristos # These next few lines are legal in both Perl and nroff. 1989946379e7Schristos 1990946379e7Schristos.00 ; # finish .ig 1991946379e7Schristos 1992946379e7Schristos'di \" finish diversion--previous line must be blank 1993946379e7Schristos.nr nl 0-1 \" fake up transition to first page again 1994946379e7Schristos.nr % 0 \" start at page 1 1995946379e7Schristos'; __END__ ############# From here on it's a standard manual page ############ 1996946379e7Schristos.TH TEXI2HTML 1 "01/05/98" 1997946379e7Schristos.AT 3 1998946379e7Schristos.SH NAME 1999946379e7Schristostexi2html \- a Texinfo to HTML converter 2000946379e7Schristos.SH SYNOPSIS 2001946379e7Schristos.B texi2html [options] file 2002946379e7Schristos.PP 2003946379e7Schristos.B texi2html -check [-verbose] files 2004946379e7Schristos.SH DESCRIPTION 2005946379e7Schristos.I Texi2html 2006946379e7Schristosconverts the given Texinfo file to a set of HTML files. It tries to handle 2007946379e7Schristosmost of the Texinfo commands. It creates hypertext links for cross-references, 2008946379e7Schristosfootnotes... 2009946379e7Schristos.PP 2010946379e7SchristosIt also tries to add links from a reference to its corresponding entry in the 2011946379e7Schristosbibliography (if any). It may also handle a glossary (see the 2012946379e7Schristos.B \-glossary 2013946379e7Schristosoption). 2014946379e7Schristos.PP 2015946379e7Schristos.I Texi2html 2016946379e7Schristoscreates several files depending on the contents of the Texinfo file and on 2017946379e7Schristosthe chosen options (see FILES). 2018946379e7Schristos.PP 2019946379e7SchristosThe HTML files created by 2020946379e7Schristos.I texi2html 2021946379e7Schristosare closer to TeX than to Info, that's why 2022946379e7Schristos.I texi2html 2023946379e7Schristosconverts @ifhtml sections and not @ifinfo or @iftex ones by default. You can 2024946379e7Schristoschange this with the \-expandinfo or \-expandtex options. 2025946379e7Schristos.SH OPTIONS 2026946379e7Schristos.TP 12 2027946379e7Schristos.B \-check 2028946379e7SchristosCheck the given file and give the list of all things that may be Texinfo commands. 2029946379e7SchristosThis may be used to check the output of 2030946379e7Schristos.I texi2html 2031946379e7Schristosto find the Texinfo commands that have been left in the HTML file. 2032946379e7Schristos.TP 2033946379e7Schristos.B \-expandinfo 2034946379e7SchristosExpand @ifinfo sections, not @ifhtml ones. 2035946379e7Schristos.TP 2036946379e7Schristos.B \-expandtex 2037946379e7SchristosExpand @iftex sections, not @ifhtml ones. 2038946379e7Schristos.TP 2039946379e7Schristos.B \-glossary 2040946379e7SchristosUse the section named 'Glossary' to build a list of terms and put links in the HTML 2041946379e7Schristosdocument from each term toward its definition. 2042946379e7Schristos.TP 2043946379e7Schristos.B \-invisible \fIname\fP 2044946379e7SchristosUse \fIname\fP to create invisible destination anchors for index links 2045946379e7Schristos(you can for instance use the invisible.xbm file shipped with this program). 2046946379e7SchristosThis is a workaround for a known bug of many WWW browsers, including netscape. 2047946379e7Schristos.TP 2048946379e7Schristos.B \-I \fIdir\fP 2049946379e7SchristosLook also in \fIdir\fP to find included files. 2050946379e7Schristos.TP 2051946379e7Schristos.B \-menu 2052946379e7SchristosShow the Texinfo menus; by default they are ignored. 2053946379e7Schristos.TP 2054946379e7Schristos.B \-monolithic 2055946379e7SchristosOutput only one file, including the table of contents and footnotes. 2056946379e7Schristos.TP 2057946379e7Schristos.B \-number 2058946379e7SchristosNumber the sections. 2059946379e7Schristos.TP 2060946379e7Schristos.B \-split_chapter 2061946379e7SchristosSplit the output into several HTML files (one per main section: 2062946379e7Schristoschapter, appendix...). 2063946379e7Schristos.TP 2064946379e7Schristos.B \-split_node 2065946379e7SchristosSplit the output into several HTML files (one per node). 2066946379e7Schristos.TP 2067946379e7Schristos.B \-usage 2068946379e7SchristosPrint usage instructions, listing the current available command-line options. 2069946379e7Schristos.TP 2070946379e7Schristos.B \-verbose 2071946379e7SchristosGive a verbose output. Can be used with the 2072946379e7Schristos.B \-check 2073946379e7Schristosoption. 2074946379e7Schristos.PP 2075946379e7Schristos.SH FILES 2076946379e7SchristosBy default 2077946379e7Schristos.I texi2html 2078946379e7Schristoscreates the following files (foo being the name of the Texinfo file): 2079946379e7Schristos.TP 16 2080946379e7Schristos.B foo_toc.html 2081946379e7SchristosThe table of contents. 2082946379e7Schristos.TP 2083946379e7Schristos.B foo.html 2084946379e7SchristosThe document's contents. 2085946379e7Schristos.TP 2086946379e7Schristos.B foo_foot.html 2087946379e7SchristosThe footnotes (if any). 2088946379e7Schristos.PP 2089946379e7SchristosWhen used with the 2090946379e7Schristos.B \-split 2091946379e7Schristosoption, it creates several files (one per chapter or node), named 2092946379e7Schristos.B foo_n.html 2093946379e7Schristos(n being the indice of the chapter or node), instead of the single 2094946379e7Schristos.B foo.html 2095946379e7Schristosfile. 2096946379e7Schristos.PP 2097946379e7SchristosWhen used with the 2098946379e7Schristos.B \-monolithic 2099946379e7Schristosoption, it creates only one file: 2100946379e7Schristos.B foo.html 2101946379e7Schristos.SH VARIABLES 2102946379e7Schristos.I texi2html 2103946379e7Schristospredefines the following variables: \fBhtml\fP, \fBtexi2html\fP. 2104946379e7Schristos.SH ADDITIONAL COMMANDS 2105946379e7Schristos.I texi2html 2106946379e7Schristosimplements the following non-Texinfo commands (maybe they are in Texinfo now...): 2107946379e7Schristos.TP 16 2108946379e7Schristos.B @ifhtml 2109946379e7SchristosThis indicates the start of an HTML section, this section will passed through 2110946379e7Schristoswithout any modification. 2111946379e7Schristos.TP 2112946379e7Schristos.B @end ifhtml 2113946379e7SchristosThis indicates the end of an HTML section. 2114946379e7Schristos.SH VERSION 2115946379e7SchristosThis is \fItexi2html\fP version 1.52b, 01/05/98. 2116946379e7Schristos.PP 2117946379e7SchristosThe latest version of \fItexi2html\fP can be found in WWW, cf. URL 2118946379e7Schristoshttp://wwwinfo.cern.ch/dis/texi2html/ 2119946379e7Schristos.SH AUTHOR 2120946379e7SchristosThe main author is Lionel Cons, CERN IT/DIS/OSE, Lionel.Cons@cern.ch. 2121946379e7SchristosMany other people around the net contributed to this program. 2122946379e7Schristos.SH COPYRIGHT 2123946379e7SchristosThis program is the intellectual property of the European 2124946379e7SchristosLaboratory for Particle Physics (known as CERN). No guarantee whatsoever is 2125946379e7Schristosprovided by CERN. No liability whatsoever is accepted for any loss or damage 2126946379e7Schristosof any kind resulting from any defect or inaccuracy in this information or 2127946379e7Schristoscode. 2128946379e7Schristos.PP 2129946379e7SchristosCERN, 1211 Geneva 23, Switzerland 2130946379e7Schristos.SH "SEE ALSO" 2131946379e7SchristosGNU Texinfo Documentation Format, 2132946379e7SchristosHyperText Markup Language (HTML), 2133946379e7SchristosWorld Wide Web (WWW). 2134946379e7Schristos.SH BUGS 2135946379e7SchristosThis program does not understand all Texinfo commands (yet). 2136946379e7Schristos.ex 2137