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