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