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