mirror of
				https://github.com/MariaDB/server.git
				synced 2025-10-30 04:26:45 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			2252 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			2252 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
| #!PATH_TO_PERL -*- perl -*-
 | |
| # Add path to perl on the previous line and make this executable
 | |
| # if you want to use this as a normal script.
 | |
| 'di ';
 | |
| 'ig 00 ';
 | |
| #+##############################################################################
 | |
| #                                                                              #
 | |
| # File: texi2html                                                              #
 | |
| #                                                                              #
 | |
| # Description: Program to transform most Texinfo documents to HTML             #
 | |
| #                                                                              #
 | |
| #-##############################################################################
 | |
| 
 | |
| # @(#)texi2html	1.52 971230 Written (mainly) by Lionel Cons, Lionel.Cons@cern.ch
 | |
| # Enhanced by David Axmark, david@detron.se
 | |
| 
 | |
| # The man page for this program is included at the end of this file and can be
 | |
| # viewed using the command 'nroff -man texi2html'.
 | |
| # Please read the copyright at the end of the man page.
 | |
| 
 | |
| #+++############################################################################
 | |
| #                                                                              #
 | |
| # Constants                                                                    #
 | |
| #                                                                              #
 | |
| #---############################################################################
 | |
| 
 | |
| $DEBUG_TOC   =  1;
 | |
| $DEBUG_INDEX =  2;
 | |
| $DEBUG_BIB   =  4;
 | |
| $DEBUG_GLOSS =  8;
 | |
| $DEBUG_DEF   = 16;
 | |
| $DEBUG_HTML  = 32;
 | |
| $DEBUG_USER  = 64;
 | |
| 
 | |
| $BIBRE = '\[[\w\/]+\]';			# RE for a bibliography reference
 | |
| $FILERE = '[\/\w.+-]+';			# RE for a file name
 | |
| $VARRE = '[^\s\{\}]+';			# RE for a variable name
 | |
| $NODERE = '[^@{}:\'`",]+';		# RE for a node name
 | |
| $NODESRE = '[^@{}:\'`"]+';		# RE for a list of node names
 | |
| $XREFRE = '[^@{}]+';			# RE for a xref (should use NODERE)
 | |
| 
 | |
| $ERROR = "***";			        # prefix for errors and warnings
 | |
| $THISPROG = "texi2html 1.52 (hacked by david\@detron.se)";	# program name and version
 | |
| $HOMEPAGE = "http://www.mathematik.uni-kl.de/~obachman/Texi2html/"; # program home page
 | |
| $TODAY = &pretty_date;			# like "20 September 1993"
 | |
| $SPLITTAG = "<!-- SPLIT HERE -->\n";	# tag to know where to split
 | |
| $PROTECTTAG = "_ThisIsProtected_";	# tag to recognize protected sections
 | |
| $html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//EN">';
 | |
| 
 | |
| #
 | |
| # language dependent constants
 | |
| #
 | |
| #$LDC_SEE = 'see';
 | |
| #$LDC_SECTION = 'section';
 | |
| #$LDC_IN = 'in';
 | |
| #$LDC_TOC = 'Table of Contents';
 | |
| #$LDC_GOTO = 'Go to the';
 | |
| #$LDC_FOOT = 'Footnotes';
 | |
| # TODO: @def* shortcuts
 | |
| 
 | |
| #$user_sub{"email"} = "fix_email";
 | |
| 
 | |
| #
 | |
| # pre-defined indices
 | |
| #
 | |
| %predefined_index = (
 | |
| 		     'cp', 'c',
 | |
| 		     'fn', 'f',
 | |
| 		     'vr', 'v',
 | |
| 		     'ky', 'k',
 | |
| 		     'pg', 'p',
 | |
| 		     'tp', 't',
 | |
| 		     );
 | |
| 
 | |
| #
 | |
| # valid indices
 | |
| #
 | |
| %valid_index = (
 | |
| 		'c', 1,
 | |
| 		'f', 1,
 | |
| 		'v', 1,
 | |
| 		'k', 1,
 | |
| 		'p', 1,
 | |
| 		't', 1,
 | |
| 		);
 | |
| 
 | |
| #
 | |
| # texinfo section names to level
 | |
| #
 | |
| %sec2level = (
 | |
| 	      'top', 0,
 | |
| 	      'chapter', 1,
 | |
| 	      'unnumbered', 1,
 | |
| 	      'majorheading', 1,
 | |
| 	      'chapheading', 1,
 | |
| 	      'appendix', 1,
 | |
| 	      'section', 2,
 | |
| 	      'unnumberedsec', 2,
 | |
| 	      'heading', 2,
 | |
| 	      'appendixsec', 2,
 | |
| 	      'appendixsection', 2,
 | |
| 	      'subsection', 3,
 | |
| 	      'unnumberedsubsec', 3,
 | |
| 	      'subheading', 3,
 | |
| 	      'appendixsubsec', 3,
 | |
| 	      'subsubsection', 4,
 | |
| 	      'unnumberedsubsubsec', 4,
 | |
| 	      'subsubheading', 4,
 | |
| 	      'appendixsubsubsec', 4,
 | |
| 	      );
 | |
| 
 | |
| #
 | |
| # accent map, TeX command to ISO name
 | |
| #
 | |
| %accent_map = (
 | |
| 	       '"',  'uml',
 | |
| 	       '~',  'tilde',
 | |
| 	       '^',  'circ',
 | |
| 	       '`',  'grave',
 | |
| 	       '\'', 'acute',
 | |
| 	       );
 | |
| 
 | |
| #
 | |
| # texinfo "simple things" (@foo) to HTML ones
 | |
| #
 | |
| %simple_map = (
 | |
| 	       # cf. makeinfo.c
 | |
| 	       "*", "<BR>",	# HTML+
 | |
| 	       " ", " ",
 | |
| 	       "\n", "\n",
 | |
| 	       "|", "",
 | |
| 	       # spacing commands
 | |
| 	       ":", "",
 | |
| 	       "!", "!",
 | |
| 	       "?", "?",
 | |
| 	       ".", ".",
 | |
| 	       );
 | |
| 
 | |
| #
 | |
| # texinfo "things" (@foo{}) to HTML ones
 | |
| #
 | |
| %things_map = (
 | |
| 	       'TeX', 'TeX',
 | |
| 	       'br', '<P>',	# paragraph break
 | |
| 	       'bullet', '*',
 | |
| 	       'copyright', '(C)',
 | |
| 	       'dots', '...',
 | |
| 	       'equiv', '==',
 | |
| 	       'error', 'error-->',
 | |
| 	       'expansion', '==>',
 | |
| 	       'minus', '-',
 | |
| 	       'point', '-!-',
 | |
| 	       'print', '-|',
 | |
| 	       'result', '=>',
 | |
| 	       'today', $TODAY,
 | |
| 	       );
 | |
| 
 | |
| #
 | |
| # texinfo styles (@foo{bar}) to HTML ones
 | |
| #
 | |
| %style_map = (
 | |
| 	      'asis', '',
 | |
| 	      'b', 'B',
 | |
| 	      'cite', 'CITE',
 | |
| 	      'code', 'CODE',
 | |
| 	      'ctrl', '&do_ctrl', # special case
 | |
| 	      'dfn', 'STRONG',	# DFN tag is illegal in the standard
 | |
| 	      'dmn', '',	# useless
 | |
| 	      'email', '&fix_email',	# special
 | |
| 	      'emph', 'EM',
 | |
| 	      'file', '"TT',	# will put quotes, cf. &apply_style
 | |
| 	      'i', 'I',
 | |
| 	      'kbd', 'KBD',
 | |
| 	      'key', 'KBD',
 | |
| 	      'r', '',		# unsupported
 | |
| 	      'samp', '"SAMP',	# will put quotes, cf. &apply_style
 | |
| 	      'sc', '&do_sc',	# special case
 | |
| 	      'strong', 'STRONG',
 | |
| 	      't', 'TT',
 | |
| 	      'titlefont', '',	# useless
 | |
| 	      'image', '&fix_image',	# Image
 | |
| 	      'url', '&fix_url',	# URL
 | |
| 	      'uref', '&fix_uref',	# URL Reference
 | |
| 	      'var', 'VAR',
 | |
| 	      'w', '',		# unsupported
 | |
| 	      );
 | |
| 
 | |
| #
 | |
| # texinfo format (@foo/@end foo) to HTML ones
 | |
| #
 | |
| %format_map = (
 | |
| 	       'display', 'PRE',
 | |
| 	       'example', 'PRE',
 | |
| 	       'format', 'PRE',
 | |
| 	       'lisp', 'PRE',
 | |
| 	       'quotation', 'BLOCKQUOTE',
 | |
| 	       'smallexample', 'PRE',
 | |
| 	       'smalllisp', 'PRE',
 | |
| 	       # lists
 | |
| 	       'itemize', 'UL',
 | |
| 	       'enumerate', 'OL',
 | |
| 	       # poorly supported
 | |
| 	       'flushleft', 'PRE',
 | |
| 	       'flushright', 'PRE',
 | |
| 	       );
 | |
| 
 | |
| #
 | |
| # texinfo definition shortcuts to real ones
 | |
| #
 | |
| %def_map = (
 | |
| 	    # basic commands
 | |
| 	    'deffn', 0,
 | |
| 	    'defvr', 0,
 | |
| 	    'deftypefn', 0,
 | |
| 	    'deftypevr', 0,
 | |
| 	    'defcv', 0,
 | |
| 	    'defop', 0,
 | |
| 	    'deftp', 0,
 | |
| 	    # basic x commands
 | |
| 	    'deffnx', 0,
 | |
| 	    'defvrx', 0,
 | |
| 	    'deftypefnx', 0,
 | |
| 	    'deftypevrx', 0,
 | |
| 	    'defcvx', 0,
 | |
| 	    'defopx', 0,
 | |
| 	    'deftpx', 0,
 | |
| 	    # shortcuts
 | |
| 	    'defun', 'deffn Function',
 | |
| 	    'defmac', 'deffn Macro',
 | |
| 	    'defspec', 'deffn {Special Form}',
 | |
| 	    'defvar', 'defvr Variable',
 | |
| 	    'defopt', 'defvr {User Option}',
 | |
| 	    'deftypefun', 'deftypefn Function',
 | |
| 	    'deftypevar', 'deftypevr Variable',
 | |
| 	    'defivar', 'defcv {Instance Variable}',
 | |
| 	    'defmethod', 'defop Method',
 | |
| 	    # x shortcuts
 | |
| 	    'defunx', 'deffnx Function',
 | |
| 	    'defmacx', 'deffnx Macro',
 | |
| 	    'defspecx', 'deffnx {Special Form}',
 | |
| 	    'defvarx', 'defvrx Variable',
 | |
| 	    'defoptx', 'defvrx {User Option}',
 | |
| 	    'deftypefunx', 'deftypefnx Function',
 | |
| 	    'deftypevarx', 'deftypevrx Variable',
 | |
| 	    'defivarx', 'defcvx {Instance Variable}',
 | |
| 	    'defmethodx', 'defopx Method',
 | |
| 	    );
 | |
| 
 | |
| #
 | |
| # things to skip
 | |
| #
 | |
| %to_skip = (
 | |
| 	    # comments
 | |
| 	    'c', 1,
 | |
| 	    'comment', 1,
 | |
| 	    # useless
 | |
| 	    'contents', 1,
 | |
| 	    'shortcontents', 1,
 | |
| 	    'summarycontents', 1,
 | |
| 	    'footnotestyle', 1,
 | |
| 	    'end ifclear', 1,
 | |
| 	    'end ifset', 1,
 | |
| 	    'titlepage', 1,
 | |
| 	    'end titlepage', 1,
 | |
| 	    # unsupported commands (formatting)
 | |
| 	    'afourpaper', 1,
 | |
| 	    'cropmarks', 1,
 | |
| 	    'finalout', 1,
 | |
| 	    'headings', 1,
 | |
| 	    'need', 1,
 | |
| 	    'page', 1,
 | |
| 	    'setchapternewpage', 1,
 | |
| 	    'everyheading', 1,
 | |
| 	    'everyfooting', 1,
 | |
| 	    'evenheading', 1,
 | |
| 	    'evenfooting', 1,
 | |
| 	    'oddheading', 1,
 | |
| 	    'oddfooting', 1,
 | |
| 	    'smallbook', 1,
 | |
| 	    'vskip', 1,
 | |
| 	    'filbreak', 1,
 | |
| 	    # unsupported formats
 | |
| 	    'cartouche', 1,
 | |
| 	    'end cartouche', 1,
 | |
| 	    'group', 1,
 | |
| 	    'end group', 1,
 | |
| 	    );
 | |
| 
 | |
| #+++############################################################################
 | |
| #                                                                              #
 | |
| # Argument parsing, initialisation                                             #
 | |
| #                                                                              #
 | |
| #---############################################################################
 | |
| 
 | |
| %value = ();			# hold texinfo variables
 | |
| 
 | |
| $use_bibliography = 1;
 | |
| $use_acc = 0;
 | |
| $debug = 0;
 | |
| $doctype = '';
 | |
| $check = 0;
 | |
| $expandinfo = 0;
 | |
| $use_glossary = 0;
 | |
| $invisible_mark = '';
 | |
| $use_iso = 0;
 | |
| @include_dirs = ();
 | |
| $show_menu = 0;
 | |
| $number_sections = 0;
 | |
| $split_node = 0;
 | |
| $split_chapter = 0;
 | |
| $monolithic = 0;
 | |
| $verbose = 0;
 | |
| $opt_use_numbers = 0;
 | |
| $opt_empty_headers = 0;
 | |
| $opt_special_links = "";
 | |
| $usage = <<EOT;
 | |
| This is $THISPROG
 | |
| To convert a Texinfo file to HMTL: $0 [options] file
 | |
| where options can be:
 | |
| -expandinfo    : use \@ifinfo sections, not \@iftex
 | |
| -glossary      : handle a glossary
 | |
| -invisible name: use 'name' as an invisible anchor
 | |
| -I dir         : search also for files in 'dir'
 | |
| -Dvar=value    : define a variable, as with \@set
 | |
| -menu          : handle menus
 | |
| -monolithic    : output only one file including ToC
 | |
| -number        : number sections
 | |
| -split_chapter : split on main sections
 | |
| -split_node    : split on nodes
 | |
| -ref_num       : use numeric names when spliting
 | |
| -empty_headers : no headers and implicit links (for inclusion into other documents)
 | |
| -usage         : print usage instructions
 | |
| -verbose       : verbose output
 | |
| To check converted files: $0 -check [-verbose] files
 | |
| EOT
 | |
|   # 
 | |
| while ($#ARGV >= 0 && $ARGV[0] =~ /^-/)
 | |
| {
 | |
|   $_ = shift(@ARGV);
 | |
|   if (/^-acc$/)            { $use_acc = 1; next; }
 | |
|   if (/^-d(ebug)?(\d+)?$/) { $debug = $2 || shift(@ARGV); next; }
 | |
|   if (/^-doctype$/)        { $doctype = shift(@ARGV); next; }
 | |
|   if (/^-c(heck)?$/)       { $check = 1; next; }
 | |
|   if (/^-e(xpandinfo)?$/)  { $expandinfo = 1; next; }
 | |
|   if (/^-g(lossary)?$/)    { $use_glossary = 1; next; }
 | |
|   if (/^-i(nvisible)?$/)   { $invisible_mark = shift(@ARGV); next; }
 | |
|   if (/^-iso$/)            { $use_iso = 1; next; }
 | |
|   if (/^-I(.+)?$/)         { push(@include_dirs, $2 || shift(@ARGV)); next; }
 | |
|   if (/^-D([a-zA-Z0-9]+)=?(.+)?$/)
 | |
| 			   { $value{$1} = $2 ? $2 : 1; next; }
 | |
|   if (/^-m(enu)?$/)        { $show_menu = 1; next; }
 | |
|   if (/^-mono(lithic)?$/)  { $monolithic = 1; next; }
 | |
|   if (/^-n(umber)?$/)      { $number_sections = 1; next; }
 | |
|   if (/^-ref_num$/)        { $opt_use_numbers = 1; next; }
 | |
|   if (/^-empty_headers$/)  { $opt_empty_headers = 1; next; }
 | |
|   if (/^-special_links$/)  { $opt_special_links = $2 || shift(@ARGV); next; }
 | |
|   if (/^-s(plit)?_?(n(ode)?|c(hapter)?)?$/) {
 | |
|     if ($2 =~ /^n/) {
 | |
|       $split_node = 1;
 | |
|     } else {
 | |
|       $split_chapter = 1;
 | |
|     }
 | |
|     next;
 | |
|   }
 | |
|   if (/^-v(erbose)?$/)     { $verbose = 1; next; }
 | |
|   die $usage;
 | |
| }
 | |
| if ($check) {
 | |
|   die $usage unless @ARGV > 0;
 | |
|   ✓
 | |
|   exit;
 | |
| }
 | |
| 
 | |
| die "Can't use -special_links with -ref_num.\n"
 | |
|   if $opt_special_links && $opt_use_numbers;
 | |
| die "Must have -split_node with -special_links.\n"
 | |
|   if $opt_special_links && !$split_node;
 | |
| 
 | |
| if (($split_node || $split_chapter) && $monolithic) {
 | |
|   warn "Can't use -monolithic with -split, -monolithic ignored.\n";
 | |
|   $monolithic = 0;
 | |
| }
 | |
| if ($expandinfo) {
 | |
|   $to_skip{'ifinfo'}++;
 | |
|   $to_skip{'end ifinfo'}++;
 | |
| } else {
 | |
|   $to_skip{'iftex'}++;
 | |
|   $to_skip{'end iftex'}++;
 | |
| }
 | |
| $invisible_mark = '<IMG SRC="invisible.xbm">' if $invisible_mark eq 'xbm';
 | |
| die $usage unless @ARGV == 1;
 | |
| $docu = shift(@ARGV);
 | |
| if ($docu =~ /.*\//) {
 | |
|   chop($docu_dir = $&);
 | |
|   $docu_name = $';
 | |
| } else {
 | |
|   $docu_dir = '.';
 | |
|   $docu_name = $docu;
 | |
| }
 | |
| unshift(@include_dirs, $docu_dir);
 | |
| $docu_name =~ s/\.te?x(i|info)?$//; # basename of the document
 | |
| 
 | |
| $docu_doc = "$docu_name.html"; # document's contents
 | |
| $link_doc = $docu_doc;
 | |
| if ($monolithic) {
 | |
|   $docu_toc = $docu_foot = $docu_doc;
 | |
| } else {
 | |
|   $docu_toc  = "${docu_name}_toc.html"; # document's table of contents
 | |
|   $docu_foot = "${docu_name}_foot.html"; # document's footnotes
 | |
| }
 | |
| 
 | |
| #
 | |
| # variables
 | |
| #
 | |
| $value{'html'} = 1;		# predefine html (the output format)
 | |
| $value{'texi2html'} = '1.52';	# predefine texi2html (the translator)
 | |
| # _foo: internal to track @foo
 | |
| foreach ('_author', '_title', '_subtitle',
 | |
| 	 '_settitle', '_setfilename') {
 | |
|   $value{$_} = '';		# prevent -w warnings
 | |
| }
 | |
| %node2sec = ();		# node to section name
 | |
| %node2href = ();	# node to HREF
 | |
| %bib2href = ();		# bibliography reference to HREF
 | |
| %gloss2href = ();	# glossary term to HREF
 | |
| @sections = ();		# list of sections
 | |
| %tag2pro = ();		# protected sections
 | |
| 
 | |
| #
 | |
| # initial indexes
 | |
| #
 | |
| $bib_num = 0;
 | |
| $foot_num = 0;
 | |
| $gloss_num = 0;
 | |
| $idx_num = 0;
 | |
| $sec_num = 0;
 | |
| $doc_num = 0;
 | |
| $current_chapter_link = "";
 | |
| @maybe_wrong_links = ();
 | |
| $html_num = 0;
 | |
| 
 | |
| #
 | |
| # can I use ISO8879 characters? (HTML+)
 | |
| #
 | |
| if ($use_iso) {
 | |
|   $things_map{'bullet'} = "•";
 | |
|   $things_map{'copyright'} = "©";
 | |
|   $things_map{'dots'} = "…";
 | |
|   $things_map{'equiv'} = "≡";
 | |
|   $things_map{'expansion'} = "→";
 | |
|   $things_map{'point'} = "∗";
 | |
|   $things_map{'result'} = "⇒";
 | |
| }
 | |
| 
 | |
| #
 | |
| # read texi2html extensions (if any)
 | |
| #
 | |
| $extensions = 'texi2html.ext'; # extensions in working directory
 | |
| if (-f $extensions) {
 | |
|   print "# reading extensions from $extensions\n" if $verbose;
 | |
|   require($extensions);
 | |
| }
 | |
| ($progdir = $0) =~ s/[^\/]+$//;
 | |
| if ($progdir && ($progdir ne './'))
 | |
| {
 | |
|   $extensions = "${progdir}texi2html.ext"; # extensions in texi2html directory
 | |
|   if (-f $extensions) {
 | |
|     print "# reading extensions from $extensions\n" if $verbose;
 | |
|     require($extensions);
 | |
|   }
 | |
| }
 | |
| 
 | |
|   print "# reading from $docu\n" if $verbose;
 | |
| 
 | |
| #+++############################################################################
 | |
| #                                                                              #
 | |
| # Pass 1: read source, handle command, variable, simple substitution           #
 | |
| #                                                                              #
 | |
| #---############################################################################
 | |
| 
 | |
| @lines = ();			# whole document
 | |
| @toc_lines = ();		# table of contents
 | |
| $toplevel = 0;			# top level seen in hierarchy
 | |
| $curlevel = 0;			# current level in TOC
 | |
| $node = '';			# current node name
 | |
| $in_table = 0;			# am I inside a table
 | |
| $table_type = '';		# type of table ('', 'f', 'v')
 | |
| @tables = ();			# nested table support
 | |
| $in_bibliography = 0;		# am I inside a bibliography
 | |
| $in_glossary = 0;		# am I inside a glossary
 | |
| $in_top = 0;			# am I inside the top node
 | |
| $in_pre = 0;			# am I inside a preformatted section
 | |
| $in_list = 0;			# am I inside a list
 | |
| $in_html = 0;			# am I inside an HTML section
 | |
| $first_line = 1;		# is it the first line
 | |
| $dont_html = 0;			# don't protect HTML on this line
 | |
| $split_num = 0;			# split index
 | |
| $deferred_ref = '';		# deferred reference for indexes
 | |
| @html_stack = ();		# HTML elements stack
 | |
| $html_element = '';		# current HTML element
 | |
| &html_reset;
 | |
| 
 | |
| # build code for simple substitutions
 | |
| # the maps used (%simple_map and %things_map) MUST be aware of this
 | |
| # watch out for regexps, / and escaped characters!
 | |
| $subst_code = '';
 | |
| foreach (keys(%simple_map)) {
 | |
|   ($re = $_) =~ s/(\W)/\\$1/g;	# protect regexp chars
 | |
|   $subst_code .= "s/\\\@$re/$simple_map{$_}/g;\n";
 | |
| }
 | |
| foreach (keys(%things_map)) {
 | |
|   $subst_code .= "s/\\\@$_\\{\\}/$things_map{$_}/g;\n";
 | |
| }
 | |
| if ($use_acc) {
 | |
|   # accentuated characters
 | |
|   foreach (keys(%accent_map)) {
 | |
|     if ($_ eq "`") {
 | |
|       $subst_code .= "s/$;3";
 | |
|     } elsif ($_ eq "'") {
 | |
|       $subst_code .= "s/$;4";
 | |
|     } else {
 | |
|       $subst_code .= "s/\\\@\\$_";
 | |
|     }
 | |
|     $subst_code .= "([aeiou])/&\${1}$accent_map{$_};/gi;\n";
 | |
|   }
 | |
| }
 | |
| eval("sub simple_substitutions { $subst_code }");
 | |
| 
 | |
| &init_input;
 | |
| READ_LINE: while ($_ = &next_line)
 | |
| {
 | |
|   #
 | |
|   # remove \input on the first lines only
 | |
|   #
 | |
|   if ($first_line) {
 | |
|     next if /^\\input/;
 | |
|     $first_line = 0;
 | |
|   }
 | |
|   #
 | |
|   # parse texinfo tags
 | |
|   #
 | |
|   $tag = '';
 | |
|   $end_tag = '';
 | |
|   if (/^\s*\@end\s+(\w+)\b/) {
 | |
|     $end_tag = $1;
 | |
|   } elsif (/^\s*\@(\w+)\b/) {
 | |
|     $tag = $1;
 | |
|   }
 | |
|   #
 | |
|   # handle @ifhtml / @end ifhtml
 | |
|   #
 | |
|   if ($in_html) {
 | |
|     if ($end_tag eq 'ifhtml') {
 | |
|       $in_html = 0;
 | |
|     } else {
 | |
|       $tag2pro{$in_html} .= $_;
 | |
|     }
 | |
|     next;
 | |
|   } elsif ($tag eq 'ifhtml') {
 | |
|     $in_html = $PROTECTTAG . ++$html_num;
 | |
|     push(@lines, $in_html);
 | |
|     next;
 | |
|   }
 | |
|   #
 | |
|   # try to skip the line
 | |
|   #
 | |
|   if ($end_tag) {
 | |
|     next if $to_skip{"end $end_tag"};
 | |
|   } elsif ($tag) {
 | |
|     next if $to_skip{$tag};
 | |
|     last if $tag eq 'bye';
 | |
|   }
 | |
|   if ($in_top) {
 | |
|     # parsing the top node
 | |
|     if ($tag eq 'node' || $tag eq 'include' || $sec2level{$tag}) {
 | |
|       # no more in top
 | |
|       $in_top = 0;
 | |
|     } else {
 | |
|       # skip it
 | |
|       next;
 | |
|     }
 | |
|   }
 | |
|   #
 | |
|   # try to remove inlined comments
 | |
|   # syntax from tex-mode.el comment-start-skip
 | |
|   #
 | |
|   s/((^|[^\s*\@])(\@\@)*)\@c(omment)? .*/$1/;
 | |
|   # non-@ substitutions cf. texinfmt.el
 | |
|   # Since these changes break code examples in the source they were removed. David 990729
 | |
|   #s/``/\"/g;
 | |
|   #s/''/\"/g;
 | |
|   s/([\w ])---([\w ])/$1--$2/g;
 | |
|   #
 | |
|   # analyze the tag
 | |
|   #
 | |
|   if ($tag) {
 | |
|     # skip lines
 | |
|     &skip_until($tag), next if $tag eq 'ignore';
 | |
|     if ($expandinfo) {
 | |
|       &skip_until($tag), next if $tag eq 'iftex';
 | |
|     } else {
 | |
|       &skip_until($tag), next if $tag eq 'ifinfo';
 | |
|     }
 | |
|     &skip_until($tag), next if $tag eq 'tex';
 | |
|     # handle special tables
 | |
|     if ($tag eq 'table') {
 | |
|       $table_type = '';
 | |
|     } elsif ($tag eq 'ftable') {
 | |
|       $tag = 'table';
 | |
|       $table_type = 'f';
 | |
|     } elsif ($tag eq 'vtable') {
 | |
|       $tag = 'table';
 | |
|       $table_type = 'v';
 | |
|     }
 | |
|     # special cases
 | |
|     if ($tag eq 'top' || ($tag eq 'node' && /^\s*\@node\s+top\s*,/i)) {
 | |
|       $in_top = 1;
 | |
|       @lines = ();		# ignore all lines before top (title page garbage)
 | |
|       next;
 | |
|     } elsif ($tag eq 'node') {
 | |
|       $in_top = 0;
 | |
|       warn "$ERROR Bad node line: $_" unless $_ =~ /^\s*\@node\s$NODESRE$/o;
 | |
|       $_ = &protect_html($_);	# if node contains '&' for instance
 | |
|       s/^\s*\@node\s+//;
 | |
|       ($node) = split(/,/);
 | |
|       &normalise_node($node);
 | |
|       if ($split_node) {
 | |
| 	($doc_node_name[$doc_num + 1] = $node) =~ s|[ /]|_|g;
 | |
| 	$doc_node_name_links[$doc_num + 1] = $current_chapter_link;
 | |
| 	&next_doc;
 | |
| 	push(@lines, $SPLITTAG) if $split_num++;
 | |
| 	push(@sections, $node);
 | |
|       }
 | |
|       next;
 | |
|     } elsif ($tag eq 'include') {
 | |
|       if (/^\s*\@include\s+($FILERE)\s*$/o) {
 | |
| 	$file = $1;
 | |
| 	unless (-e $file) {
 | |
| 	  foreach $dir (@include_dirs) {
 | |
| 	    $file = "$dir/$1";
 | |
| 	    last if -e $file;
 | |
| 	  }
 | |
| 	}
 | |
| 	if (-e $file) {
 | |
| 	  &open($file);
 | |
| 	  print "# including $file\n" if $verbose;
 | |
| 	} else {
 | |
| 	  warn "$ERROR Can't find $file, skipping";
 | |
| 	}
 | |
|       } else {
 | |
| 	warn "$ERROR Bad include line: $_";
 | |
|       }
 | |
|       next;
 | |
|     } elsif ($tag eq 'ifclear') {
 | |
|       if (/^\s*\@ifclear\s+($VARRE)\s*$/o) {
 | |
| 	next unless defined($value{$1});
 | |
| 	&skip_until($tag);
 | |
|       } else {
 | |
| 	warn "$ERROR Bad ifclear line: $_";
 | |
|       }
 | |
|       next;
 | |
|     } elsif ($tag eq 'ifset') {
 | |
|       if (/^\s*\@ifset\s+($VARRE)\s*$/o) {
 | |
| 	next if defined($value{$1});
 | |
| 	&skip_until($tag);
 | |
|       } else {
 | |
| 	warn "$ERROR Bad ifset line: $_";
 | |
|       }
 | |
|       next;
 | |
|     } elsif ($tag eq 'menu') {
 | |
|       unless ($show_menu) {
 | |
| 	&skip_until($tag);
 | |
| 	next;
 | |
|       }
 | |
|       &html_push_if($tag);
 | |
|       push(@lines, &html_debug("\n", __LINE__));
 | |
|     } elsif ($format_map{$tag}) {
 | |
|       $in_pre = 1 if $format_map{$tag} eq 'PRE';
 | |
|       &html_push_if($format_map{$tag});
 | |
|       push(@lines, &html_debug("\n", __LINE__));
 | |
|       $in_list++ if $format_map{$tag} eq 'UL' || $format_map{$tag} eq 'OL' ;
 | |
|       push(@lines, &debug("<$format_map{$tag}>\n", __LINE__));
 | |
|       next;
 | |
|     } elsif ($tag eq 'table') {
 | |
|       if (/^\s*\@[fv]?table\s+\@(\w+)\s*$/) {
 | |
| 	$in_table = $1;
 | |
| 	unshift(@tables, join($;, $table_type, $in_table));
 | |
| 	push(@lines, &debug("<DL COMPACT>\n", __LINE__));
 | |
| 	&html_push_if('DL');
 | |
| 	push(@lines, &html_debug("\n", __LINE__));
 | |
|       } else {
 | |
| 	warn "$ERROR Bad table line: $_";
 | |
|       }
 | |
|       next;
 | |
|     } elsif ($tag eq 'multitable') {
 | |
|       if (/^\s*\@multitable\s*\@columnfractions\s+([\.\d\s]+)\s*$/ ||
 | |
| 	  /^\s*\@multitable\s*({[^{}]+})+\s*$/)
 | |
|       {
 | |
| 	$in_multitable = 1;
 | |
| 	html_push('TABLE');
 | |
| 	my($col_list) = $1;
 | |
| 	$multitable_cols = ($col_list =~ /\@columnfractions/ ? s/[\d.]+\s+//g :
 | |
| 			    s/{[^{}]+}//g);
 | |
| 	print "# Multitable with $multitable_cols columns\n"
 | |
| 	  if $debug and $DEBUG_USER;
 | |
| 	push(@lines, &debug("<TABLE BORDER WIDTH=\"100%\">\n", __LINE__));
 | |
|       } else {
 | |
| 	warn "$ERROR Bad table line: $_";
 | |
|       }
 | |
|       next;
 | |
|     } elsif ($tag eq 'synindex' || $tag eq 'syncodeindex') {
 | |
|       if (/^\s*\@$tag\s+(\w)\w\s+(\w)\w\s*$/) {
 | |
| 	eval("*${1}index = *${2}index");
 | |
|       } else {
 | |
| 	warn "$ERROR Bad syn*index line: $_";
 | |
|       }
 | |
|       next;
 | |
|     } elsif ($tag eq 'sp') {
 | |
|       push(@lines, &debug("<P>\n", __LINE__));
 | |
|       next;
 | |
|     } elsif ($tag eq 'setref') {
 | |
|       &protect_html;		# if setref contains '&' for instance
 | |
|       if (/^\s*\@$tag\s*{($NODERE)}\s*$/) {
 | |
| 	$setref = $1;
 | |
| 	$setref =~ s/\s+/ /g;	# normalize
 | |
| 	$setref =~ s/ $//;
 | |
| 	$node2sec{$setref} = $name;
 | |
| 	$node2href{$setref} = "$link_doc#$docid";
 | |
| 	push(@maybe_wrong_links, $setref);
 | |
|       } else {
 | |
| 	warn "$ERROR Bad setref line: $_";
 | |
|       }
 | |
|       next;
 | |
|     } elsif ($tag eq 'defindex' || $tag eq 'defcodeindex') {
 | |
|       if (/^\s*\@$tag\s+(\w\w)\s*$/) {
 | |
| 	$valid_index{$1} = 1;
 | |
|       } else {
 | |
| 	warn "$ERROR Bad defindex line: $_";
 | |
|       }
 | |
|       next;
 | |
|     } elsif (defined($def_map{$tag})) {
 | |
|       if ($def_map{$tag}) {
 | |
| 	s/^\s*\@$tag\s+//;
 | |
| 	$tag = $def_map{$tag};
 | |
| 	$_ = "\@$tag $_";
 | |
| 	$tag =~ s/\s.*//;
 | |
|       }
 | |
|     } elsif (defined($user_sub{$tag})) {
 | |
|       s/^\s*\@$tag\s+//;
 | |
|       $sub = $user_sub{$tag};
 | |
|       print "# user $tag = $sub, arg: $_" if $debug & $DEBUG_USER;
 | |
|       if (defined(&$sub)) {
 | |
| 	chop($_);
 | |
| 	&$sub($_);
 | |
|       } else {
 | |
| 	warn "$ERROR Bad user sub for $tag: $sub\n";
 | |
|       }
 | |
|       next;
 | |
|     }
 | |
|     if (defined($def_map{$tag})) {
 | |
|       s/^\s*\@$tag\s+//;
 | |
|       if ($tag =~ /x$/) {
 | |
| 	# extra definition line
 | |
| 	$tag = $`;
 | |
| 	$is_extra = 1;
 | |
|       } else {
 | |
| 	$is_extra = 0;
 | |
|       }
 | |
|       while (/\{([^\{\}]*)\}/) {
 | |
| 	# this is a {} construct
 | |
| 	($before, $contents, $after) = ($`, $1, $');
 | |
| 	# protect spaces
 | |
| 	$contents =~ s/\s+/$;9/g;
 | |
| 	# restore $_ protecting {}
 | |
| 	$_ = "$before$;7$contents$;8$after";
 | |
|       }
 | |
|       @args = split(/\s+/, &protect_html($_));
 | |
|       foreach (@args) {
 | |
| 	s/$;9/ /g;		# unprotect spaces
 | |
| 	s/$;7/\{/g;		# ... {
 | |
| 	s/$;8/\}/g;		# ... }
 | |
|       }
 | |
|       $type = shift(@args);
 | |
|       $type =~ s/^\{(.*)\}$/$1/;
 | |
|       print "# def ($tag): {$type} ", join(', ', @args), "\n"
 | |
| 	if $debug & $DEBUG_DEF;
 | |
|       $type .= ':';		# it's nicer like this
 | |
|       $name = shift(@args);
 | |
|       $name =~ s/^\{(.*)\}$/$1/;
 | |
|       if ($is_extra) {
 | |
| 	$_ = &debug("<DT>", __LINE__);
 | |
|       } else {
 | |
| 	$_ = &debug("<DL>\n<DT>", __LINE__);
 | |
|       }
 | |
|       if ($tag eq 'deffn' || $tag eq 'defvr' || $tag eq 'deftp') {
 | |
| 	$_ .= "<U>$type</U> <B>$name</B>";
 | |
| 	$_ .= " <I>@args</I>" if @args;
 | |
|       } elsif ($tag eq 'deftypefn' || $tag eq 'deftypevr'
 | |
| 	       || $tag eq 'defcv' || $tag eq 'defop') {
 | |
| 	$ftype = $name;
 | |
| 	$name = shift(@args);
 | |
| 	$name =~ s/^\{(.*)\}$/$1/;
 | |
| 	$_ .= "<U>$type</U> $ftype <B>$name</B>";
 | |
| 	$_ .= " <I>@args</I>" if @args;
 | |
|       } else {
 | |
| 	warn "$ERROR Unknown definition type: $tag\n";
 | |
| 	$_ .= "<U>$type</U> <B>$name</B>";
 | |
| 	$_ .= " <I>@args</I>" if @args;
 | |
|       }
 | |
|       $_ .= &debug("\n<DD>", __LINE__);
 | |
|       $name = &unprotect_html($name);
 | |
|       if ($tag eq 'deffn' || $tag eq 'deftypefn') {
 | |
| 	unshift(@input_spool, "\@findex $name\n");
 | |
|       } elsif ($tag eq 'defop') {
 | |
| 	unshift(@input_spool, "\@findex $name on $ftype\n");
 | |
|       } elsif ($tag eq 'defvr' || $tag eq 'deftypevr' || $tag eq 'defcv') {
 | |
| 	unshift(@input_spool, "\@vindex $name\n");
 | |
|       } else {
 | |
| 	unshift(@input_spool, "\@tindex $name\n");
 | |
|       }
 | |
|       $dont_html = 1;
 | |
|     }
 | |
|   } elsif ($end_tag) {
 | |
|     if ($format_map{$end_tag}) {
 | |
|       $in_pre = 0 if $format_map{$end_tag} eq 'PRE';
 | |
|       $in_list-- if $format_map{$end_tag} eq 'UL' || $format_map{$end_tag} eq 'OL' ;
 | |
|       &html_pop_if('LI', 'P');
 | |
|       &html_pop_if();
 | |
|       push(@lines, &debug("</$format_map{$end_tag}>\n", __LINE__));
 | |
|       push(@lines, &html_debug("\n", __LINE__));
 | |
|     } elsif ($end_tag eq 'table' ||
 | |
| 	     $end_tag eq 'ftable' ||
 | |
| 	     $end_tag eq 'vtable') {
 | |
|       shift(@tables);
 | |
|       if (@tables) {
 | |
| 	($table_type, $in_table) = split($;, $tables[0]);
 | |
|       } else {
 | |
| 	$in_table = 0;
 | |
| 	$table_type = '';
 | |
|       }
 | |
|       push(@lines, "</DL>\n");
 | |
|       &html_pop_if('DD');
 | |
|       &html_pop_if();
 | |
|     } elsif ($end_tag eq 'multitable') {
 | |
|       print "# end of multitable with $multitable_cols columns\n"
 | |
| 	if $debug and $DEBUG_USER;
 | |
|       $in_multitable = 0;
 | |
|       push(@lines, "</TD></TR>\n");
 | |
|       &html_pop_if('TR');
 | |
|       push(@lines, "</TABLE>\n");
 | |
| &html_pop_if('TABLE');
 | |
|     } elsif (defined($def_map{$end_tag})) {
 | |
|       push(@lines, &debug("</DL>\n", __LINE__));
 | |
|     } elsif ($end_tag eq 'menu') {
 | |
|       &html_pop_if();
 | |
|       push(@lines, $_);		# must keep it for pass 2
 | |
|     }
 | |
|     next;
 | |
|   }
 | |
|   #
 | |
|   # misc things
 | |
|   #
 | |
|   # protect texi and HTML things
 | |
|   &protect_texi;
 | |
|   $_ = &protect_html($_) unless $dont_html;
 | |
|   $dont_html = 0;
 | |
|   # substitution (unsupported things)
 | |
|   s/^\s*\@center\s+//g;
 | |
|   s/^\s*\@exdent\s+//g;
 | |
|   s/\@noindent\s+//g;
 | |
|   s/\@refill\s+//g;
 | |
|   # other substitutions
 | |
|   &simple_substitutions;
 | |
|   s/\@value{($VARRE)}/$value{$1}/eg;
 | |
|   s/\@footnote\{/\@footnote$docu_doc\{/g; # mark footnotes, cf. pass 4
 | |
|   s|\s+\@tab\s*| </TD><TD> |g if ($in_multitable);
 | |
| 
 | |
|   #
 | |
|   # analyze the tag again
 | |
|   #
 | |
|   if ($tag) {
 | |
|     if (defined($sec2level{$tag}) && $sec2level{$tag} > 0) {
 | |
|       if (/^\s*\@$tag\s+(.+)$/) {
 | |
| 	$name = $1;
 | |
| 	$name =~ s/\s+$//;
 | |
| 	$level = $sec2level{$tag};
 | |
| 	$name = &update_sec_num($tag, $level) . "  $name"
 | |
| 	  if $number_sections && $tag !~ /^unnumbered/;
 | |
| 	if ($tag =~ /heading$/) {
 | |
| 	  push(@lines, &html_debug("\n", __LINE__));
 | |
| 	  if ($html_element ne 'body') {
 | |
| 	    # We are in a nice pickle here. We are trying to get a H? heading
 | |
| 	    # even though we are not in the body level. So, we convert
 | |
| 	    # it to a nice, bold, line by itself.
 | |
| 	    $_ = &debug("\n\n<P><STRONG>$name</STRONG></P>\n\n", __LINE__);
 | |
| 	  } else {
 | |
| 	    $_ = &debug("<H$level>$name</H$level>\n", __LINE__);
 | |
| 	    &html_push_if('body');
 | |
| 	  }
 | |
| 	  print "# heading, section $name, level $level\n"
 | |
| 	    if $debug & $DEBUG_TOC;
 | |
| 	} else {
 | |
| 	  if ($split_chapter) {
 | |
| 	    unless ($toplevel) {
 | |
| 	      # first time we see a "section"
 | |
| 	      unless ($level == 1) {
 | |
| 		warn "$ERROR The first section found is not of level 1: $_";
 | |
| 		warn "$ERROR I'll split on sections of level $level...\n";
 | |
| 	      }
 | |
| 	      $toplevel = $level;
 | |
| 	    };
 | |
| 	    if ($level == $toplevel) {
 | |
| 	      print "# Splitting at section $name\n"
 | |
| 		if $debug & $DEBUG_TOC;
 | |
| 	      ($doc_node_name[$doc_num + 1] = $node) =~ s|[ /]|_|g;
 | |
| 	      &next_doc;
 | |
| 	      push(@lines, $SPLITTAG) if $split_num++;
 | |
| 	      push(@sections, $name);
 | |
| 	    }
 | |
| 	  } elsif ($split_node && $opt_special_links) {
 | |
| 	    $toplevel = $level unless $toplevel;
 | |
| 	    if ($level == $toplevel) {
 | |
| 	      ($current_chapter_link = $node) =~ s|[ /]|_|g;
 | |
| 	      # Set this again to the right value.
 | |
| 	      $doc_node_name_links[$doc_num] = $current_chapter_link;
 | |
| 	      ($docu_doc, $link_doc) = &doc_name($doc_num);
 | |
| 	    }
 | |
| 	  }
 | |
| 	  $sec_num++;
 | |
| 	  # Was "SEC$sec_num"
 | |
| 	  ($docid = "$node") =~ s|[ /]|_|g;
 | |
| 	  ($tocid = "$node") =~ s|[ /]|_|g;
 | |
| $docid = "SEC$sec_num" unless $docid;
 | |
| $tocid = "SEC$sec_num" unless $tocid;
 | |
| 	  # check biblio and glossary
 | |
| 	  $in_bibliography =
 | |
| 	    ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*bibliography$/i);
 | |
| 	  $in_glossary = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*glossary$/i);
 | |
| 	  # check node
 | |
| 	  if ($node) {
 | |
| 	    if ($node2sec{$node}) {
 | |
| 	      warn "$ERROR Duplicate node found: $node\n";
 | |
| 	    } else {
 | |
| 	      $node2sec{$node} = $name;
 | |
| 	      $node2href{$node} = "$link_doc#$docid";
 | |
| 	      push(@maybe_wrong_links, $node);
 | |
| 	      print "# node $node, section $name, level $level\n"
 | |
| 		if $debug & $DEBUG_TOC;
 | |
| 	    }
 | |
| 	    $node = '';
 | |
| 	  } else {
 | |
| 	    print "# no node, section $name, level $level\n"
 | |
| 	      if $debug & $DEBUG_TOC;
 | |
| 	  }
 | |
| 	  # update TOC
 | |
| 	  while ($level > $curlevel) {
 | |
| 	    $curlevel++;
 | |
| 	    push(@toc_lines, "<UL>\n");
 | |
| 	  }
 | |
| 	  while ($level < $curlevel) {
 | |
| 	    $curlevel--;
 | |
| 	    push(@toc_lines, "</UL>\n");
 | |
| 	  }
 | |
| 	  $_ = "<LI>" . &anchor($tocid, "$link_doc#$docid", $name, 1);
 | |
| 	  push(@toc_lines, &substitute_style($_));
 | |
| 	  # update DOC
 | |
| 	  push(@lines, &html_debug("\n", __LINE__));
 | |
| 	  &html_reset;
 | |
| 	  $_ =  "<H$level>".&anchor($docid,  $opt_empty_headers ? "" : "$docu_toc#$tocid",
 | |
| 				    $name)."</H$level>\n";
 | |
| 	  $_ = &debug($_, __LINE__);
 | |
| 	  push(@lines, &html_debug("\n", __LINE__));
 | |
| 	}
 | |
| 	# update DOC
 | |
| 	foreach $line (split(/\n+/, $_)) {
 | |
| 	  push(@lines, "$line\n");
 | |
| 	}
 | |
| 	next;
 | |
|       } else {
 | |
| 	warn "$ERROR Bad section line: $_";
 | |
|       }
 | |
|     } else {
 | |
|       # track variables
 | |
|       $value{$1} = $2, next if /^\s*\@set\s+($VARRE)\s+(.*)$/o;
 | |
|       delete $value{$1}, next if /^\s*\@clear\s+($VARRE)\s*$/o;
 | |
|       # store things
 | |
|       $value{'_setfilename'}   = $1, next if /^\s*\@setfilename\s+(.*)$/;
 | |
|       $value{'_settitle'}      = $1, next if /^\s*\@settitle\s+(.*)$/;
 | |
|       $value{'_author'}   .= "$1\n", next if /^\s*\@author\s+(.*)$/;
 | |
|       $value{'_subtitle'} .= "$1\n", next if /^\s*\@subtitle\s+(.*)$/;
 | |
|       $value{'_title'}    .= "$1\n", next if /^\s*\@title\s+(.*)$/;
 | |
|       # index
 | |
|       if (/^\s*\@(..?)index\s+/) {
 | |
| 	unless ($valid_index{$1}) {
 | |
| 	  warn "$ERROR Undefined index command: $_";
 | |
| 	  next;
 | |
| 	}
 | |
| 	$id = 'IDX' . ++$idx_num;
 | |
| 	$index = $1 . 'index';
 | |
| 	$what = &substitute_style($');
 | |
| 	$what =~ s/\s+$//;
 | |
| 	print "# found $index for '$what' id $id\n"
 | |
| 	  if $debug & $DEBUG_INDEX;
 | |
| 	eval(<<EOC);
 | |
|  if (defined(\$$index\{\$what\})) {
 | |
|    \$$index\{\$what\} .= "$;$link_doc#$id";
 | |
|  } else {
 | |
|    \$$index\{\$what\} = "$link_doc#$id";
 | |
|  }
 | |
| EOC
 | |
| 	  #
 | |
| 	  # dirty hack to see if I can put an invisible anchor...
 | |
| 	  #
 | |
| 	  if ($html_element eq 'P' ||
 | |
| 	      $html_element eq 'LI' ||
 | |
| 	      $html_element eq 'DT' ||
 | |
| 	      $html_element eq 'DD' ||
 | |
| 	      $html_element eq 'ADDRESS' ||
 | |
| 	      $html_element eq 'B' ||
 | |
| 	      $html_element eq 'BLOCKQUOTE' ||
 | |
| 	      $html_element eq 'PRE' ||
 | |
| 	      $html_element eq 'SAMP') {
 | |
| 	    push(@lines, &anchor($id, '', $invisible_mark, !$in_pre));
 | |
| 	  } elsif ($html_element eq 'body') {
 | |
| 	    push(@lines, &debug("<P>\n", __LINE__));
 | |
| 	    push(@lines, &anchor($id, '', $invisible_mark, !$in_pre));
 | |
| 	    &html_push('P');
 | |
| 	  } elsif ($html_element eq 'DL' ||
 | |
| 		   $html_element eq 'UL' ||
 | |
| 		   $html_element eq 'OL' ||
 | |
| 		   $html_element eq 'TR') {
 | |
| 	    $deferred_ref .=
 | |
| 	      &anchor($id, '', $invisible_mark, !$in_pre) . " ";
 | |
| 	  }
 | |
| 	next;
 | |
|       }
 | |
|       # list item
 | |
|       if (/^\s*\@itemx?\s+/)
 | |
|       {
 | |
| 	$what = $';
 | |
| 	$what =~ s/\s+$//;
 | |
| 
 | |
| 	# add an index before the item if applicable
 | |
| 	if ($table_type ne '' && !$in_multitable) {
 | |
| 	  print "# Adding table index (type $table_type) for $what\n"
 | |
| 	    if $debug & $DEBUG_INDEX;
 | |
| 	  # This is realy ugly. We should do a pass before this to
 | |
| 	  # add index entrys before instead.
 | |
| 	  if ($global_added_this_index) {
 | |
| 	    $global_added_this_index = 0;
 | |
| 	  } else {
 | |
| 	    unshift(@input_spool, "\@${table_type}index $what\n", $_);
 | |
| 	    $global_added_this_index = 1;
 | |
| 	    next READ_LINE;
 | |
| 	  }
 | |
| 	}
 | |
| 
 | |
| 	if ($in_bibliography && $use_bibliography) {
 | |
| 	  if ($what =~ /^$BIBRE$/o) {
 | |
| 	    $id = 'BIB' . ++$bib_num;
 | |
| 	    $bib2href{$what} = "$link_doc#$id";
 | |
| 	    print "# found bibliography for '$what' id $id\n"
 | |
| 	      if $debug & $DEBUG_BIB;
 | |
| 	    $what = &anchor($id, '', $what);
 | |
| 	  }
 | |
| 	} elsif ($in_glossary && $use_glossary) {
 | |
| 	  $id = 'GLOSS' . ++$gloss_num;
 | |
| 	  $entry = $what;
 | |
| 	  $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/;
 | |
| 	  $gloss2href{$entry} = "$link_doc#$id";
 | |
| 	  print "# found glossary for '$entry' id $id\n"
 | |
| 	    if $debug & $DEBUG_GLOSS;
 | |
| 	  $what = &anchor($id, '', $what);
 | |
| 	}
 | |
| 	if ($in_multitable)
 | |
| 	{
 | |
| 	  # All this is a **HACK**.
 | |
| 	  # It does only work for a FEW SIMPLE CASES !!!
 | |
| 	  push(@lines, &debug("</TD></TR>\n", __LINE__))
 | |
| 	    unless $html_element eq 'TABLE';
 | |
| 	  &html_pop_if('TR');
 | |
| 	  $what =~ s|\s+\@tab\s*| </TD><TD> |g;
 | |
| 	  push(@lines, &debug("<TR><TD>$what\n", __LINE__));
 | |
| 	  &html_push('TR');
 | |
| 	  if ($deferred_ref)
 | |
| 	  {
 | |
| 	    push(@lines, &debug("$deferred_ref\n", __LINE__));
 | |
| 	    $deferred_ref = '';
 | |
| 	  }
 | |
| 	  next;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	  &html_pop_if('P');
 | |
| 	  if ($html_element eq 'DL' || $html_element eq 'DD') {
 | |
| 	    if ($things_map{$in_table} && !$what) {
 | |
| 	      # special case to allow @table @bullet for instance
 | |
| 	      push(@lines, &debug("<DT>$things_map{$in_table}\n", __LINE__));
 | |
| 	    } else {
 | |
| 	      push(@lines, &debug("<DT>\@$in_table\{$what\}\n", __LINE__));
 | |
| 	    }
 | |
| 	    push(@lines, "<DD>");
 | |
| 	    &html_push('DD') unless $html_element eq 'DD';
 | |
| 	    # Old index add was here
 | |
| 	  } else {
 | |
| 	    push(@lines, &debug("<LI>$what\n", __LINE__));
 | |
| 	    &html_push('LI') unless $html_element eq 'LI';
 | |
| 	  }
 | |
| 	  push(@lines, &html_debug("\n", __LINE__));
 | |
| 	  if ($deferred_ref) {
 | |
| 	    push(@lines, &debug("$deferred_ref\n", __LINE__));
 | |
| 	    $deferred_ref = '';
 | |
| 	  }
 | |
| 	  next;
 | |
| 	}
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   # paragraph separator
 | |
|   if ($_ eq "\n") {
 | |
|     next if $#lines >= 0 && $lines[$#lines] eq "\n";
 | |
|     if ($html_element eq 'P') {
 | |
|       push(@lines, "\n");
 | |
|       $_ = &debug("</P>\n", __LINE__);
 | |
|       &html_pop;
 | |
|     }
 | |
|   } elsif ($html_element eq 'body' || $html_element eq 'BLOCKQUOTE') {
 | |
|     push(@lines, "<P>\n");
 | |
|     &html_push('P');
 | |
|     $_ = &debug($_, __LINE__);
 | |
|   }
 | |
|   # otherwise
 | |
|   push(@lines, $_);
 | |
| }
 | |
| 
 | |
| # finish TOC
 | |
| $level = 0;
 | |
| while ($level < $curlevel)
 | |
| {
 | |
|   $curlevel--;
 | |
|   push(@toc_lines, "</UL>\n");
 | |
| }
 | |
| 
 | |
| print "# end of pass 1\n" if $verbose;
 | |
| 
 | |
| #+++############################################################################
 | |
| #                                                                              #
 | |
| # Pass 2/3: handle style, menu, index, cross-reference                         #
 | |
| #                                                                              #
 | |
| #---############################################################################
 | |
| 
 | |
| @lines2 = ();			# whole document (2nd pass)
 | |
| @lines3 = ();			# whole document (3rd pass)
 | |
| $in_menu = 0;			# am I inside a menu
 | |
| 
 | |
| while (@lines)
 | |
| {
 | |
|   $_ = shift(@lines);
 | |
|   #
 | |
|   # special case (protected sections)
 | |
|   #
 | |
|   if (/^$PROTECTTAG/o) {
 | |
|     push(@lines2, $_);
 | |
|     next;
 | |
|   }
 | |
|   #
 | |
|   # menu
 | |
|   #
 | |
|   $in_menu = 1, push(@lines2, &debug("<UL>\n", __LINE__)), next if /^\s*\@menu\b/;
 | |
|   $in_menu = 0, push(@lines2, &debug("</UL>\n", __LINE__)), next if /^\s*\@end\s+menu\b/;
 | |
|   if ($in_menu) {
 | |
|     if (/^\*\s+($NODERE)::/o) {
 | |
|       $descr = $';
 | |
|       chop($descr);
 | |
|       &menu_entry($1, $1, $descr);
 | |
|     } elsif (/^\*\s+(.+):\s+([^\t,\.\n]+)[\t,\.\n]/) {
 | |
|       $descr = $';
 | |
|       chop($descr);
 | |
|       &menu_entry($1, $2, $descr);
 | |
|     } elsif (/^\*/) {
 | |
|       warn "$ERROR Bad menu line: $_";
 | |
|     } else {			# description continued?
 | |
|       push(@lines2, $_);
 | |
|     }
 | |
|     next;
 | |
|   }
 | |
|   #
 | |
|   # printindex
 | |
|   #
 | |
|   if (/^\s*\@printindex\s+(\w\w)\b/) {
 | |
|     local($index, *ary, @keys, $key, $letter, $last_letter, @refs);
 | |
|     if ($predefined_index{$1}) {
 | |
|       $index = $predefined_index{$1} . 'index';
 | |
|     } else {
 | |
|       $index = $1 . 'index';
 | |
|     }
 | |
|     eval("*ary = *$index");
 | |
|     @keys = keys(%ary);
 | |
|     foreach $key (@keys) {
 | |
|       $_ = $key;
 | |
|       1 while s/<(\w+)>\`(.*)\'<\/\1>/$2/; # remove HTML tags with quotes
 | |
|       1 while s/<(\w+)>(.*)<\/\1>/$2/; # remove HTML tags
 | |
|       $_ = &unprotect_html($_);
 | |
|       &unprotect_texi;
 | |
|       tr/A-Z/a-z/;		# lowercase
 | |
|       $key2alpha{$key} = $_;
 | |
|       print "# index $key sorted as $_\n"
 | |
| 	if $key ne $_ && $debug & $DEBUG_INDEX;
 | |
|     }
 | |
|     $last_letter = undef;
 | |
|     foreach $key (sort byalpha @keys) {
 | |
|       $letter = substr($key2alpha{$key}, 0, 1);
 | |
|       $letter = substr($key2alpha{$key}, 0, 2) if $letter eq $;;
 | |
|       $letter = " " unless $letter =~ /[a-zA-Z]/;
 | |
|       if (!defined($last_letter) || $letter ne $last_letter) {
 | |
| 	push(@lines2, "</DIR>\n") if defined($last_letter);
 | |
| 	push(@lines2, "<H2>" . &protect_html(uc($letter)) . "</H2>\n");
 | |
| 	push(@lines2, "<DIR>\n");
 | |
| 	$last_letter = $letter;
 | |
|       }
 | |
|       @refs = ();
 | |
|       foreach (split(/$;/, $ary{$key})) {
 | |
| 	push(@refs, &anchor('', $_, $key, 0));
 | |
|       }
 | |
|       push(@lines2, "<LI>" . join(", ", @refs) . "\n");
 | |
|     }
 | |
|     push(@lines2, "</DIR>\n") if defined($last_letter);
 | |
|     next;
 | |
|   }
 | |
|   #
 | |
|   # simple style substitutions
 | |
|   #
 | |
|   $_ = &substitute_style($_);
 | |
|   #
 | |
|   # xref
 | |
|   #
 | |
|   while (/\@(x|px|info|)ref{($XREFRE)(}?)/o) {
 | |
|     # note: Texinfo may accept other characters
 | |
|     ($type, $nodes, $full) = ($1, $2, $3);
 | |
|     ($before, $after) = ($`, $');
 | |
|     if (! $full && $after) {
 | |
|       warn "$ERROR Bad xref (no ending } on line): $_";
 | |
|       $_ = "$before$;0${type}ref\{$nodes$after";
 | |
|       next;			# while xref
 | |
|     }
 | |
|     if ($type eq 'x') {
 | |
|       $type = 'See ';
 | |
|     } elsif ($type eq 'px') {
 | |
|       $type = 'see ';
 | |
|     } elsif ($type eq 'info') {
 | |
|       $type = 'See Info';
 | |
|     } elsif ($type eq 'u') {
 | |
|       $type = 'See ';
 | |
|     } else {
 | |
|       $type = '';
 | |
|     }
 | |
|     unless ($full) {
 | |
|       $next = shift(@lines);
 | |
|       $next = &substitute_style($next);
 | |
|       chop($nodes);		# remove final newline
 | |
|       if ($next =~ /\}/) {	# split on 2 lines
 | |
| 	$nodes .= " $`";
 | |
| 	$after = $';
 | |
|       } else {
 | |
| 	$nodes .= " $next";
 | |
| 	$next = shift(@lines);
 | |
| 	$next = &substitute_style($next);
 | |
| 	chop($nodes);
 | |
| 	if ($next =~ /\}/) {	# split on 3 lines
 | |
| 	  $nodes .= " $`";
 | |
| 	  $after = $';
 | |
| 	} else {
 | |
| 	  warn "$ERROR Bad xref (no ending }): $_";
 | |
| 	  $_ = "$before$;0xref\{$nodes$after";
 | |
| 	  unshift(@lines, $next);
 | |
| 	  next;			# while xref
 | |
| 	}
 | |
|       }
 | |
|     }
 | |
|     $nodes =~ s/\s+/ /g;	# remove useless spaces
 | |
|     @args = split(/\s*,\s*/, $nodes);
 | |
|     $node = $args[0];		# the node is always the first arg
 | |
|     &normalise_node($node);
 | |
|     $sec = $node2sec{$node};
 | |
|     if (@args == 5) {		# reference to another manual
 | |
|       $sec = $args[2] || $node;
 | |
|       $man = $args[4] || $args[3];
 | |
|       $_ = "${before}${type}section `$sec' in \@cite{$man}$after";
 | |
|     } elsif ($type =~ /Info/) { # inforef
 | |
|       warn "$ERROR Wrong number of arguments: $_" unless @args == 3;
 | |
|       ($nn, $_, $in) = @args;
 | |
|       $_ = "${before}${type} file `$in', node `$nn'$after";
 | |
|     } elsif ($sec) {
 | |
|       $href = $node2href{$node};
 | |
|       $_ = "${before}${type}section " . &anchor('', $href, $sec) . $after;
 | |
|     } else {
 | |
|       warn "$ERROR Undefined node ($node): $_";
 | |
|       $_ = "$before$;0xref{$nodes}$after";
 | |
|     }
 | |
|   }
 | |
|   #
 | |
|   # try to guess bibliography references or glossary terms
 | |
|   #
 | |
|   # This checked for NAME="SEC\d". The current version is probably broken.
 | |
|   unless (/^<H\d><A NAME=\"/) {
 | |
|     if ($use_bibliography) {
 | |
|       $done = '';
 | |
|       while (/$BIBRE/o) {
 | |
| 	($pre, $what, $post) = ($`, $&, $');
 | |
| 	$href = $bib2href{$what};
 | |
| 	if (defined($href) && $post !~ /^[^<]*<\/A>/) {
 | |
| 	  $done .= $pre . &anchor('', $href, $what);
 | |
| 	} else {
 | |
| 	  $done .= "$pre$what";
 | |
| 	}
 | |
| 	$_ = $post;
 | |
|       }
 | |
|       $_ = $done . $_;
 | |
|     }
 | |
|     if ($use_glossary) {
 | |
|       $done = '';
 | |
|       while (/\b\w+\b/) {
 | |
| 	($pre, $what, $post) = ($`, $&, $');
 | |
| 	$entry = $what;
 | |
| 	$entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/;
 | |
| 	$href = $gloss2href{$entry};
 | |
| 	if (defined($href) && $post !~ /^[^<]*<\/A>/) {
 | |
| 	  $done .= $pre . &anchor('', $href, $what);
 | |
| 	} else {
 | |
| 	  $done .= "$pre$what";
 | |
| 	}
 | |
| 	$_ = $post;
 | |
|       }
 | |
|       $_ = $done . $_;
 | |
|     }
 | |
|   }
 | |
|   # otherwise
 | |
|   push(@lines2, $_);
 | |
| }
 | |
| print "# end of pass 2\n" if $verbose;
 | |
| 
 | |
| #
 | |
| # split style substitutions
 | |
| #
 | |
| while (@lines2)
 | |
| {
 | |
|   $_ = shift(@lines2);
 | |
|   #
 | |
|   # special case (protected sections)
 | |
|   #
 | |
|   if (/^$PROTECTTAG/o) {
 | |
|     push(@lines3, $_);
 | |
|     next;
 | |
|   }
 | |
|   #
 | |
|   # split style substitutions
 | |
|   #
 | |
|   $old = '';
 | |
|   while ($old ne $_) {
 | |
|     $old = $_;
 | |
|     if (/\@(\w+)\{/) {
 | |
|       ($before, $style, $after) = ($`, $1, $');
 | |
|       if (defined($style_map{$style})) {
 | |
| 	$_ = $after;
 | |
| 	$text = '';
 | |
| 	$after = '';
 | |
| 	$failed = 1;
 | |
| 	while (@lines2) {
 | |
| 	  if (/\}/) {
 | |
| 	    $text .= $`;
 | |
| 	    $after = $';
 | |
| 	    $failed = 0;
 | |
| 	    last;
 | |
| 	  } else {
 | |
| 	    $text .= $_;
 | |
| 	    $_ = shift(@lines2);
 | |
| 	  }
 | |
| 	}
 | |
| 	if ($failed) {
 | |
| 	  die "* Bad syntax (\@$style) after: $before\n";
 | |
| 	} else {
 | |
| 	  $text = &apply_style($style, $text);
 | |
| 	  $_ = "$before$text$after";
 | |
| 	}
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   # otherwise
 | |
|   push(@lines3, $_);
 | |
| }
 | |
| print "# end of pass 3\n" if $verbose;
 | |
| 
 | |
| #+++############################################################################
 | |
| #                                                                              #
 | |
| # Pass 4: foot notes, final cleanup                                            #
 | |
| #                                                                              #
 | |
| #---############################################################################
 | |
| 
 | |
| @foot_lines = ();		# footnotes
 | |
| @doc_lines = ();		# final document
 | |
| $end_of_para = 0;		# true if last line is <P>
 | |
| 
 | |
| while (@lines3)
 | |
| {
 | |
|   $_ = shift(@lines3);
 | |
|   #
 | |
|   # special case (protected sections)
 | |
|   #
 | |
|   if (/^$PROTECTTAG/o) {
 | |
|     push(@doc_lines, $_);
 | |
|     $end_of_para = 0;
 | |
|     next;
 | |
|   }
 | |
|   #
 | |
|   # footnotes
 | |
|   #
 | |
|   while (/\@footnote([^\{\s]+)\{/) {
 | |
|     ($before, $d, $after) = ($`, $1, $');
 | |
|     $_ = $after;
 | |
|     $text = '';
 | |
|     $after = '';
 | |
|     $failed = 1;
 | |
|     while (@lines3) {
 | |
|       if (/\}/) {
 | |
| 	$text .= $`;
 | |
| 	$after = $';
 | |
| 	$failed = 0;
 | |
| 	last;
 | |
|       } else {
 | |
| 	$text .= $_;
 | |
| 	$_ = shift(@lines3);
 | |
|       }
 | |
|     }
 | |
|     if ($failed) {
 | |
|       die "* Bad syntax (\@footnote) after: $before\n";
 | |
|     } else {
 | |
|       $foot_num++;
 | |
|       $docid  = "DOCF$foot_num";
 | |
|       $footid = "FOOT$foot_num";
 | |
|       $foot = "($foot_num)";
 | |
|       push(@foot_lines, "<H3>" . &anchor($footid, "$d#$docid", $foot) . "</H3>\n");
 | |
|       $text = "<P>$text" unless $text =~ /^\s*<P>/;
 | |
|       push(@foot_lines, "$text\n");
 | |
|       $_ = $before . &anchor($docid, "$docu_foot#$footid", $foot) . $after;
 | |
|     }
 | |
|   }
 | |
|   #
 | |
|   # remove unnecessary <P>
 | |
|   #
 | |
|   if (/^\s*<P>\s*$/) {
 | |
|     next if $end_of_para++;
 | |
|   } else {
 | |
|     $end_of_para = 0;
 | |
|   }
 | |
|   # otherwise
 | |
|   push(@doc_lines, $_);
 | |
| }
 | |
| print "# end of pass 4\n" if $verbose;
 | |
| 
 | |
| #+++############################################################################
 | |
| #                                                                              #
 | |
| # Pass 5: print things                                                         #
 | |
| #                                                                              #
 | |
| #---############################################################################
 | |
| 
 | |
| $header = <<EOT;
 | |
| <!-- This HTML file has been created by $THISPROG
 | |
|      from $docu on $TODAY -->
 | |
| EOT
 | |
| 
 | |
|   $full_title = $value{'_title'} || $value{'_settitle'} || "Untitled Document";
 | |
|   $title = $value{'_settitle'} || $full_title;
 | |
|   $_ = &substitute_style($full_title);
 | |
|   &unprotect_texi;
 | |
|   s/\n$//;			# rmv last \n (if any)
 | |
|   $full_title = "<H1>" . join("</H1>\n<H1>", split(/\n/, $_)) . "</H1>\n";
 | |
| 
 | |
| #
 | |
| # print ToC
 | |
| #
 | |
| if (!$monolithic && @toc_lines)
 | |
| {
 | |
|   if (open(FILE, "> $docu_toc")) {
 | |
|     print "# creating $docu_toc...\n" if $verbose;
 | |
|     &print_toplevel_header("$title - Table of Contents");
 | |
|     &print_ruler;
 | |
|     &print(*toc_lines, FILE);
 | |
|     &print_toplevel_footer;
 | |
|     close(FILE);
 | |
|   } else {
 | |
|     warn "$ERROR Can't write (toc) to $docu_toc: $!\n";
 | |
|   }
 | |
| }
 | |
| 
 | |
| #
 | |
| # print footnotes
 | |
| #
 | |
| if (!$monolithic && @foot_lines)
 | |
| {
 | |
|   if (open(FILE, "> $docu_foot")) {
 | |
|     print "# creating $docu_foot...\n" if $verbose;
 | |
|     &print_toplevel_header("$title - Footnotes");
 | |
|     &print_ruler;
 | |
|     &print(*foot_lines, FILE);
 | |
|     &print_toplevel_footer;
 | |
|     close(FILE);
 | |
|   } else {
 | |
|     warn "$ERROR Can't write (foot) to $docu_foot: $!\n";
 | |
|   }
 | |
| }
 | |
| 
 | |
| #
 | |
| # print document
 | |
| #
 | |
| 
 | |
| if ($split_chapter || $split_node)
 | |
| {				# split
 | |
|   $doc_num = 0;
 | |
|   $last_num = scalar(@sections);
 | |
|   $first_doc = &doc_name(1);
 | |
|   $last_doc = &doc_name($last_num);
 | |
|   while (@sections) {
 | |
|     $section = shift(@sections);
 | |
|     &next_doc;
 | |
|     # Remove added links part
 | |
|     if (open(FILE, ">$docu_doc")) {
 | |
|       print "# creating $docu_doc... ($section)\n" if $verbose;
 | |
|       &print_header("$title - $section") unless $opt_empty_headers;
 | |
|       $prev_doc = ($doc_num == 1 ? undef : &doc_name($doc_num - 1));
 | |
|       $next_doc = ($doc_num == $last_num ? undef : &doc_name($doc_num + 1));
 | |
|       $navigation = "Go to the ";
 | |
|       $navigation .= ($prev_doc ? &anchor('', $first_doc, "first") : "first");
 | |
|       $navigation .= ", ";
 | |
|       $navigation .= ($prev_doc ? &anchor('', $prev_doc, "previous") : "previous");
 | |
|       $navigation .= ", ";
 | |
|       $navigation .= ($next_doc ? &anchor('', $next_doc, "next") : "next");
 | |
|       $navigation .= ", ";
 | |
|       $navigation .= ($next_doc ? &anchor('', $last_doc, "last") : "last");
 | |
|       $navigation .= " section, " . &anchor('', $docu_toc, "table of contents") . ".\n";
 | |
|       print FILE $navigation unless $opt_empty_headers;
 | |
|       &print_ruler unless $opt_empty_headers;
 | |
|       # find corresponding lines
 | |
|       @tmp_lines = ();
 | |
|       while (@doc_lines) {
 | |
| 	$_ = shift(@doc_lines);
 | |
| 	last if ($_ eq $SPLITTAG);
 | |
| 	push(@tmp_lines, $_);
 | |
|       }
 | |
|       &print(*tmp_lines, FILE);
 | |
|       &print_ruler unless $opt_empty_headers;
 | |
|       print FILE $navigation unless $opt_empty_headers;
 | |
|       &print_footer unless $opt_empty_headers;
 | |
|       close(FILE);
 | |
|     } else {
 | |
|       warn "$ERROR Can't write (doc) to $docu_doc: $!\n";
 | |
|     }
 | |
|   }
 | |
| }
 | |
| else
 | |
| {				# not split
 | |
|   if (open(FILE, ">$docu_doc")) {
 | |
|     print "# creating $docu_doc...\n" if $verbose;
 | |
|     if ($monolithic || !@toc_lines) {
 | |
|       &print_toplevel_header($title);
 | |
|     } else {
 | |
|       &print_header($title);
 | |
|       print FILE $full_title;
 | |
|     }
 | |
|     if ($monolithic && @toc_lines) {
 | |
|       &print_ruler;
 | |
|       print FILE "<H1>Table of Contents</H1>\n";
 | |
|       &print(*toc_lines, FILE);
 | |
|     }
 | |
|     &print_ruler;
 | |
|     &print(*doc_lines, FILE);
 | |
|     if ($monolithic && @foot_lines) {
 | |
|       &print_ruler;
 | |
|       print FILE "<H1>Footnotes</H1>\n";
 | |
|       &print(*foot_lines, FILE);
 | |
|     }
 | |
|     if ($monolithic || !@toc_lines) {
 | |
|       &print_toplevel_footer;
 | |
|     } else {
 | |
|       &print_footer;
 | |
|     }
 | |
|     close(FILE);
 | |
|   } else {
 | |
|     warn "$ERROR Can't write (doc2) to $docu_doc: $!\n";
 | |
|   }
 | |
| }
 | |
| 
 | |
| print "# that's all folks\n" if $verbose;
 | |
| 
 | |
| #+++############################################################################
 | |
| #                                                                              #
 | |
| # Low level functions                                                          #
 | |
| #                                                                              #
 | |
| #---############################################################################
 | |
| 
 | |
| sub update_sec_num
 | |
| {
 | |
|   local($name, $level) = @_;
 | |
| 
 | |
|   $level--;			# here we start at 0
 | |
|   if ($name =~ /^appendix/) {
 | |
|     # appendix style
 | |
|     if (defined(@appendix_sec_num)) {
 | |
|       &incr_sec_num($level, @appendix_sec_num);
 | |
|     } else {
 | |
|       @appendix_sec_num = ('A', 0, 0, 0);
 | |
|     }
 | |
|     return(join('.', @appendix_sec_num[0..$level]));
 | |
|   } else {
 | |
|     # normal style
 | |
|     if (defined(@normal_sec_num)) {
 | |
|       &incr_sec_num($level, @normal_sec_num);
 | |
|     } else {
 | |
|       @normal_sec_num = (1, 0, 0, 0);
 | |
|     }
 | |
|     return(join('.', @normal_sec_num[0..$level]));
 | |
|   }
 | |
| }
 | |
| 
 | |
| sub incr_sec_num
 | |
| {
 | |
|   local($level, $l);
 | |
|   $level = shift(@_);
 | |
|   $_[$level]++;
 | |
|   foreach $l ($level+1 .. 3) {
 | |
|     $_[$l] = 0;
 | |
|   }
 | |
| }
 | |
| 
 | |
| sub check
 | |
| {
 | |
|   local($_, %seen, %context, $before, $match, $after);
 | |
| 
 | |
|   while (<>) {
 | |
|     if (/\@(\*|\.|\:|\@|\{|\})/) {
 | |
|       $seen{$&}++;
 | |
|       $context{$&} .= "> $_" if $verbose;
 | |
|       $_ = "$`XX$'";
 | |
|       redo;
 | |
|     }
 | |
|     if (/\@(\w+)/) {
 | |
|       ($before, $match, $after) = ($`, $&, $');
 | |
|       if ($before =~ /\b[\w-]+$/ && $after =~ /^[\w-.]*\b/) { # e-mail address
 | |
| 	$seen{'e-mail address'}++;
 | |
| 	$context{'e-mail address'} .= "> $_" if $verbose;
 | |
|       } else {
 | |
| 	$seen{$match}++;
 | |
| 	$context{$match} .= "> $_" if $verbose;
 | |
|       }
 | |
|       $match =~ s/^\s*\@/X/;
 | |
|       $_ = "$before$match$after";
 | |
|       redo;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   foreach (sort(keys(%seen))) {
 | |
|     if ($verbose) {
 | |
|       print "$_\n";
 | |
|       print $context{$_};
 | |
|     } else {
 | |
|       print "$_ ($seen{$_})\n";
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| sub open
 | |
| {
 | |
|   local($name) = @_;
 | |
| 
 | |
|   ++$fh_name;
 | |
|   if (open($fh_name, $name)) {
 | |
|     unshift(@fhs, $fh_name);
 | |
|   } else {
 | |
|     warn "$ERROR Can't read file $name: $!\n";
 | |
|   }
 | |
| }
 | |
| 
 | |
| sub init_input
 | |
| {
 | |
|   @fhs = ();			# hold the file handles to read
 | |
|   @input_spool = ();		# spooled lines to read
 | |
|   $fh_name = 'FH000';
 | |
|   &open($docu);
 | |
| }
 | |
| 
 | |
| sub next_line
 | |
| {
 | |
|   local($fh, $line);
 | |
| 
 | |
|   if (@input_spool) {
 | |
|     $line = shift(@input_spool);
 | |
|     return($line);
 | |
|   }
 | |
|   while (@fhs) {
 | |
|     $fh = $fhs[0];
 | |
|     $line = <$fh>;
 | |
|     return($line) if $line;
 | |
|     close($fh);
 | |
|     shift(@fhs);
 | |
|   }
 | |
|   return(undef);
 | |
| }
 | |
| 
 | |
| # used in pass 1, use &next_line
 | |
| sub skip_until
 | |
| {
 | |
|   local($tag) = @_;
 | |
|   local($_);
 | |
| 
 | |
|   while ($_ = &next_line) {
 | |
|     return if /^\s*\@end\s+$tag\s*$/;
 | |
|   }
 | |
|   die "* Failed to find '$tag' after: " . $lines[$#lines];
 | |
| }
 | |
| 
 | |
| #
 | |
| # HTML stacking to have a better HTML output
 | |
| #
 | |
| 
 | |
| sub html_reset
 | |
| {
 | |
|   @html_stack = ('html');
 | |
|   $html_element = 'body';
 | |
| }
 | |
| 
 | |
| sub html_push
 | |
| {
 | |
|   local($what) = @_;
 | |
|   push(@html_stack, $html_element);
 | |
|   $html_element = $what;
 | |
| }
 | |
| 
 | |
| sub html_push_if
 | |
| {
 | |
|   local($what) = @_;
 | |
|   push(@html_stack, $html_element)
 | |
|     if ($html_element && $html_element ne 'P');
 | |
|   $html_element = $what;
 | |
| }
 | |
| 
 | |
| sub html_pop
 | |
| {
 | |
|   $html_element = pop(@html_stack);
 | |
| }
 | |
| 
 | |
| sub html_pop_if
 | |
| {
 | |
|   local($elt);
 | |
| 
 | |
|   if (@_) {
 | |
|     foreach $elt (@_) {
 | |
|       if ($elt eq $html_element) {
 | |
| 	$html_element = pop(@html_stack) if @html_stack;
 | |
| 	last;
 | |
|       }
 | |
|     }
 | |
|   } else {
 | |
|     $html_element = pop(@html_stack) if @html_stack;
 | |
|   }
 | |
| }
 | |
| 
 | |
| sub html_debug
 | |
| {
 | |
|   local($what, $line) = @_;
 | |
|   return("<!-- $line @html_stack, $html_element -->$what")
 | |
|     if $debug & $DEBUG_HTML;
 | |
|   return($what);
 | |
| }
 | |
| 
 | |
| # to debug the output...
 | |
| sub debug
 | |
| {
 | |
|   local($what, $line) = @_;
 | |
|   return("<!-- $line -->$what")
 | |
|     if $debug & $DEBUG_HTML;
 | |
|   return($what);
 | |
| }
 | |
| 
 | |
| sub normalise_node
 | |
| {
 | |
|   $_[0] =~ s/\s+/ /g;
 | |
|   $_[0] =~ s/ $//;
 | |
|   $_[0] =~ s/^ //;
 | |
| }
 | |
| 
 | |
| sub menu_entry
 | |
| {
 | |
|   local($entry, $node, $descr) = @_;
 | |
|   local($href);
 | |
| 
 | |
|   &normalise_node($node);
 | |
|   $href = $node2href{$node};
 | |
|   if ($href) {
 | |
|     $descr =~ s/^\s+//;
 | |
|     $descr = ": $descr" if $descr;
 | |
|     push(@lines2, "<LI>" . &anchor('', $href, $entry) . "$descr\n");
 | |
|   } else {
 | |
|     warn "$ERROR Undefined node ($node): $_";
 | |
|   }
 | |
| }
 | |
| 
 | |
| sub do_ctrl { "^$_[0]" }
 | |
| 
 | |
| sub do_sc { "\U$_[0]\E" }
 | |
| 
 | |
| sub fix_image
 | |
| {
 | |
|   my($text) = @_;
 | |
|   my($arg1, $ext);
 | |
|   $text =~ /^([^,]*)$/;
 | |
|   die "error in image: '$text'" unless defined($1);
 | |
|   $arg1 = $1;
 | |
|   $arg1 =~ s/@@/@/g;
 | |
|   $ext = "jpg" if -f "$arg1.jpg";
 | |
|   $ext = "gif" if -f "$arg1.gif";
 | |
|   if (defined($ext))
 | |
|   {
 | |
|     "<IMG SRC=\"$arg1.$ext\">";
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     warn "Image $arg1 not found";
 | |
|     "";
 | |
|   }
 | |
| }
 | |
| 
 | |
| sub fix_url
 | |
| {
 | |
|   my($text) = @_;
 | |
|   $text =~ s/@@/@/g;
 | |
|   $text;
 | |
| }
 | |
| 
 | |
| sub fix_uref
 | |
| {
 | |
|   my($text) = @_;
 | |
|   my($arg1, $arg2);
 | |
|   $text =~ /^([^,]*),?([^,]*)?$/;
 | |
|   die "error in uref: '$text'" unless defined($1);
 | |
|   $arg1 = $1;
 | |
|   $arg2 = (defined($2) && $2) ? $2 : $arg1;
 | |
|   $arg1 =~ s/@@/@/g;
 | |
|   $arg2 =~ s/@@/@/g;
 | |
|   "<a HREF=\"$arg1\">$arg2</a>";
 | |
| }
 | |
| 
 | |
| sub fix_email
 | |
| {
 | |
|   my($text) = @_;
 | |
|   my($arg1, $arg2);
 | |
|   $text =~ /^([^,]*)(,[^,]*)?$/;
 | |
|   die "error in email: '$text'" unless defined($1);
 | |
|   $arg1 = $1;
 | |
|   $arg2 = defined($2) ? $2 : $arg1;
 | |
|   $arg1 =~ s/@@/@/g;
 | |
|   $arg2 =~ s/@@/@/g;
 | |
|   "<a HREF=\"mailto:$arg1\">$arg2</a>";
 | |
| }
 | |
| 
 | |
| sub apply_style
 | |
| {
 | |
|   local($texi_style, $text) = @_;
 | |
|   local($style);
 | |
| 
 | |
|   $style = $style_map{$texi_style};
 | |
|   if (defined($style)) {	# known style
 | |
|     if ($style =~ /^\"/) {	# add quotes
 | |
|       $style = $';
 | |
|       $text = "\`$text\'";
 | |
|     }
 | |
|     if ($style =~ /^\&/) {	# custom
 | |
|       $style = $';
 | |
|       $text = &$style($text);
 | |
|     } elsif ($style) {		# good style
 | |
|       $text = "<$style>$text</$style>";
 | |
|     } else {			# no style
 | |
|     }
 | |
|   } else {			# unknown style
 | |
|     $text = undef;
 | |
|   }
 | |
|   return($text);
 | |
| }
 | |
| 
 | |
| # remove Texinfo styles
 | |
| sub remove_style
 | |
| {
 | |
|   local($_) = @_;
 | |
|   s/\@\w+{([^\{\}]+)}/$1/g;
 | |
|   return($_);
 | |
| }
 | |
| 
 | |
| sub substitute_style
 | |
| {
 | |
|   local($_) = @_;
 | |
|   local($changed, $done, $style, $text);
 | |
| 
 | |
|   $changed = 1;
 | |
|   while ($changed) {
 | |
|     $changed = 0;
 | |
|     $done = '';
 | |
|     while (/\@(\w+){([^\{\}]+)}/) {
 | |
|       $text = &apply_style($1, $2);
 | |
|       if ($text) {
 | |
| 	$_ = "$`$text$'";
 | |
| 	$changed = 1;
 | |
|       } else {
 | |
| 	$done .= "$`\@$1";
 | |
| 	$_ = "{$2}$'";
 | |
|       }
 | |
|     }
 | |
|     $_ = $done . $_;
 | |
|   }
 | |
|   return($_);
 | |
| }
 | |
| 
 | |
| sub anchor
 | |
| {
 | |
|   local($name, $href, $text, $newline) = @_;
 | |
|   local($result);
 | |
| 
 | |
|   $result = "<A";
 | |
|   $result .= " NAME=\"$name\"" if $name;
 | |
|   $result .= " HREF=\"$href\"" if $href;
 | |
|   $result .= ">$text</A>";
 | |
|   $result .= "\n" if $newline;
 | |
|   return($result);
 | |
| }
 | |
| 
 | |
| sub pretty_date
 | |
| {
 | |
|   local(@MoY, $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);
 | |
| 
 | |
|   @MoY = ('January', 'Febuary', 'March', 'April', 'May', 'June',
 | |
| 	  'July', 'August', 'September', 'October', 'November', 'December');
 | |
|   ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
 | |
|   $year += ($year < 70) ? 2000 : 1900;
 | |
|   return("$mday $MoY[$mon] $year");
 | |
| }
 | |
| 
 | |
| sub doc_name
 | |
| {
 | |
|   local($num) = @_;
 | |
|   my($real_name, $link_name);
 | |
|   $real_name = ($opt_use_numbers) ? $num : $doc_node_name[$num];
 | |
|   $link_name = ($opt_special_links) ?
 | |
|     $doc_node_name_links[$num] : $real_name;
 | |
|   # print "# num $num osl $opt_special_links link $link_name\n";
 | |
|   return("${docu_name}_$real_name.html",
 | |
| 	 "$opt_special_links${docu_name}_$link_name.html");
 | |
| }
 | |
| 
 | |
| sub next_doc
 | |
| {
 | |
|   ($docu_doc, $link_doc) = &doc_name(++$doc_num);
 | |
| }
 | |
| 
 | |
| sub print
 | |
| {
 | |
|   local(*lines, $fh) = @_;
 | |
|   local($_);
 | |
| 
 | |
|   while (@lines) {
 | |
|     $_ = shift(@lines);
 | |
|     if (/^$PROTECTTAG/o) {
 | |
|       $_ = $tag2pro{$_};
 | |
|     } else {
 | |
|       &unprotect_texi;
 | |
|     }
 | |
|     print $fh $_;
 | |
|   }
 | |
| }
 | |
| 
 | |
| sub print_ruler
 | |
| {
 | |
|   print FILE "<P><HR><P>\n";
 | |
| }
 | |
| 
 | |
| sub print_header
 | |
| {
 | |
|   local($_);
 | |
| 
 | |
|   # clean the title
 | |
|   $_ = &remove_style($_[0]);
 | |
|   &unprotect_texi;
 | |
|   # print the header
 | |
|   if ($doctype eq 'html2') {
 | |
|     print FILE $html2_doctype;
 | |
|   } elsif ($doctype) {
 | |
|     print FILE $doctype;
 | |
|   }
 | |
|   my($tags) = defined($value{"_body_tags"}) ? " " . $value{"_body_tags"} : "";
 | |
|   my($et) = defined($value{"_extra_head"}) ? " " . $value{"_extra_head"} : "";
 | |
|   $et = &unprotect_html($et);
 | |
|   print FILE <<EOT;
 | |
|   <HTML>
 | |
|   <HEAD>
 | |
|   $header
 | |
|   <TITLE>$_</TITLE>
 | |
|   $et
 | |
|   </HEAD>
 | |
|   <BODY$tags>
 | |
| EOT
 | |
| }
 | |
| 
 | |
| sub print_toplevel_header
 | |
| {
 | |
|   local($_);
 | |
| 
 | |
|   &print_header;		# pass given arg...
 | |
|   print FILE $full_title;
 | |
|   if ($value{'_subtitle'}) {
 | |
|     $value{'_subtitle'} =~ s/\n+$//;
 | |
|     foreach (split(/\n/, $value{'_subtitle'})) {
 | |
|       $_ = &substitute_style($_);
 | |
|       &unprotect_texi;
 | |
|       print FILE "<H2>$_</H2>\n";
 | |
|     }
 | |
|   }
 | |
|   if ($value{'_author'}) {
 | |
|     $value{'_author'} =~ s/\n+$//;
 | |
|     foreach (split(/\n/, $value{'_author'})) {
 | |
|       $_ = &substitute_style($_);
 | |
|       &unprotect_texi;
 | |
|       s/[\w.-]+\@[\w.-]+/<A HREF="mailto:$&">$&<\/A>/g;
 | |
|       print FILE "<ADDRESS>$_</ADDRESS>\n";
 | |
|     }
 | |
|   }
 | |
|   print FILE "<P>\n";
 | |
| }
 | |
| 
 | |
| sub print_footer
 | |
| {
 | |
|   print FILE <<EOT;
 | |
|  </BODY>
 | |
|  </HTML>
 | |
| EOT
 | |
| }
 | |
| 
 | |
| sub print_toplevel_footer
 | |
| {
 | |
|   &print_ruler;
 | |
|   print FILE <<EOT;
 | |
| This document was generated on $TODAY using the
 | |
| <A HREF=\"$HOMEPAGE\">texi2html</A>
 | |
| translator version 1.52 (extended by davida\@detron.se).</P>
 | |
| EOT
 | |
|   &print_footer;
 | |
| }
 | |
| 
 | |
| sub protect_texi
 | |
| {
 | |
|   # protect @ { } ` '
 | |
|   s/\@\@/$;0/go;
 | |
|   s/\@\{/$;1/go;
 | |
|   s/\@\}/$;2/go;
 | |
|   s/\@\`/$;3/go;
 | |
|   s/\@\'/$;4/go;
 | |
| }
 | |
| 
 | |
| sub protect_html
 | |
| {
 | |
|   local($what) = @_;
 | |
|   # protect & < >
 | |
|   # Avoid loop in & replacement. This instead bugs out for &# in text..
 | |
|   $what =~ s/\&([^#]|$)/\&\#38;$1/g;
 | |
|   $what =~ s/\</\&\#60;/g;
 | |
|   $what =~ s/\>/\&\#62;/g;
 | |
|   # but recognize some HTML things
 | |
|   $what =~ s/\&\#60;\/A\&\#62;/<\/A>/g;	# </A>
 | |
|   $what =~ s/\&\#60;A ([^\&]+)\&\#62;/<A $1>/g;	# <A [^&]+>
 | |
|   $what =~ s/\&\#60;IMG ([^\&]+)\&\#62;/<IMG $1>/g; # <IMG [^&]+>
 | |
|   return($what);
 | |
| }
 | |
| 
 | |
| sub unprotect_texi
 | |
| {
 | |
|   s/$;0/\@/go;
 | |
|   s/$;1/\{/go;
 | |
|   s/$;2/\}/go;
 | |
|   s/$;3/\`/go;
 | |
|   s/$;4/\'/go;
 | |
| }
 | |
| 
 | |
| sub unprotect_html
 | |
| {
 | |
|   local($what) = @_;
 | |
|   $what =~ s/\&\#38;/\&/g;
 | |
|   $what =~ s/\&\#60;/\</g;
 | |
|   $what =~ s/\&\#62;/\>/g;
 | |
|   return($what);
 | |
| }
 | |
| 
 | |
| sub byalpha
 | |
| {
 | |
|   $key2alpha{$a} cmp $key2alpha{$b};
 | |
| }
 | |
| 
 | |
| ##############################################################################
 | |
| 
 | |
|   # These next few lines are legal in both Perl and nroff.
 | |
| 
 | |
|   .00 ;				# finish .ig
 | |
| 
 | |
|   'di			\" finish diversion--previous line must be blank
 | |
| .nr nl 0-1		\" fake up transition to first page again
 | |
| .nr % 0			\" start at page 1
 | |
| '; __END__			############# From here on it's a standard manual page ############
 | |
| .TH TEXI2HTML 1 "09/10/96"
 | |
| .AT 3
 | |
| .SH NAME
 | |
| texi2html \- a Texinfo to HTML converter
 | |
| .SH SYNOPSIS
 | |
| .B texi2html [options] file
 | |
| .PP
 | |
| .B texi2html -check [-verbose] files
 | |
| .SH DESCRIPTION
 | |
| .I Texi2html
 | |
| converts the given Texinfo file to a set of HTML files. It tries to handle
 | |
| most of the Texinfo commands. It creates hypertext links for cross-references,
 | |
| footnotes...
 | |
| .PP
 | |
| It also tries to add links from a reference to its corresponding entry in the
 | |
| bibliography (if any). It may also handle a glossary (see the
 | |
| .B \-glossary
 | |
| option).
 | |
| .PP
 | |
| .I Texi2html
 | |
| creates several files depending on the contents of the Texinfo file and on
 | |
| the chosen options (see FILES).
 | |
| .PP
 | |
| The HTML files created by
 | |
| .I texi2html
 | |
| are closer to TeX than to Info, that's why
 | |
| .I texi2html
 | |
| converts @iftex sections and not @ifinfo ones by default. You can reverse
 | |
| this with the \-expandinfo option.
 | |
| .SH OPTIONS
 | |
| .TP 12
 | |
| .B \-check
 | |
| Check the given file and give the list of all things that may be Texinfo commands.
 | |
| This may be used to check the output of
 | |
| .I texi2html
 | |
| to find the Texinfo commands that have been left in the HTML file.
 | |
| .TP
 | |
| .B \-expandinfo
 | |
| Expand @ifinfo sections, not @iftex ones.
 | |
| .TP
 | |
| .B \-glossary
 | |
| Use the section named 'Glossary' to build a list of terms and put links in the HTML
 | |
| document from each term toward its definition.
 | |
| .TP
 | |
| .B \-invisible \fIname\fP
 | |
| Use \fIname\fP to create invisible destination anchors for index links. This is a workaround
 | |
| for a known bug of many WWW browsers, including xmosaic.
 | |
| .TP
 | |
| .B \-I \fIdir\fP
 | |
| Look also in \fIdir\fP to find included files.
 | |
| .TP
 | |
| .B \-menu
 | |
| Show the Texinfo menus; by default they are ignored.
 | |
| .TP
 | |
| .B \-monolithic
 | |
| Output only one file, including the table of contents and footnotes.
 | |
| .TP
 | |
| .B \-number
 | |
| Number the sections.
 | |
| .TP
 | |
| .B \-split_chapter
 | |
| Split the output into several HTML files (one per main section:
 | |
| chapter, appendix...).
 | |
| .TP
 | |
| .B \-split_node
 | |
| Split the output into several HTML files (one per node).
 | |
| .TP
 | |
| .B \-usage
 | |
| Print usage instructions, listing the current available command-line options.
 | |
| .TP
 | |
| .B \-verbose
 | |
| Give a verbose output. Can be used with the
 | |
| .B \-check
 | |
| option.
 | |
| .PP
 | |
| .SH FILES
 | |
| By default
 | |
| .I texi2html
 | |
| creates the following files (foo being the name of the Texinfo file):
 | |
| .TP 16
 | |
| .B foo_toc.html
 | |
| The table of contents.
 | |
| .TP
 | |
| .B foo.html
 | |
| The document's contents.
 | |
| .TP
 | |
| .B foo_foot.html
 | |
| The footnotes (if any).
 | |
| .PP
 | |
| When used with the
 | |
| .B \-split
 | |
| option, it creates several files (one per chapter or node), named
 | |
| .B foo_n.html
 | |
| (n being the indice of the chapter or node), instead of the single
 | |
| .B foo.html
 | |
| file.
 | |
| .PP
 | |
| When used with the
 | |
| .B \-monolithic
 | |
| option, it creates only one file:
 | |
| .B foo.html
 | |
| .SH VARIABLES
 | |
| .I texi2html
 | |
| predefines the following variables: \fBhtml\fP, \fBtexi2html\fP.
 | |
| .SH ADDITIONAL COMMANDS
 | |
| .I texi2html
 | |
| implements the following non-Texinfo commands:
 | |
| .TP 16
 | |
| .B @ifhtml
 | |
| This indicates the start of an HTML section, this section will passed through
 | |
| without any modofication.
 | |
| .TP
 | |
| .B @end ifhtml
 | |
| This indcates the end of an HTML section.
 | |
| .SH VERSION
 | |
| This is \fItexi2html\fP version 1.52, 09/10/96.
 | |
| .PP
 | |
| The latest version of \fItexi2html\fP can be found in WWW, cf. URL
 | |
| http://wwwcn.cern.ch/dci/texi2html/
 | |
| .SH AUTHOR
 | |
| The main author is Lionel Cons, CERN CN/DCI/UWS, Lionel.Cons@cern.ch.
 | |
| Many other people around the net contributed to this program.
 | |
| .SH COPYRIGHT
 | |
| This program is the intellectual property of the European
 | |
| Laboratory for Particle Physics (known as CERN). No guarantee whatsoever is
 | |
| provided by CERN. No liability whatsoever is accepted for any loss or damage
 | |
| of any kind resulting from any defect or inaccuracy in this information or
 | |
| code.
 | |
| .PP
 | |
| CERN, 1211 Geneva 23, Switzerland
 | |
| .SH "SEE ALSO"
 | |
| GNU Texinfo Documentation Format,
 | |
| HyperText Markup Language (HTML),
 | |
| World Wide Web (WWW).
 | |
| .SH BUGS
 | |
| This program does not understand all Texinfo commands (yet).
 | |
| .PP
 | |
| TeX specific commands (normally enclosed in @iftex) will be
 | |
| passed unmodified.
 | |
| .ex
 | 
