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