# -*- perl -*- # ### File: html3.1.pl ### Language definitions for HTML 3.1 (Math) ### Written by Marcus E. Hennecke ### Version 0.3, April 3, 1997 ### extended math-parsing, when $NO_SIMPLE_MATH is set ### Version 0.4, July, August 1997 by Ross Moore ### extended math-parsing, when $NO_SIMPLE_MATH is set ### Version 0.5, many modifications and extensions ### made during 1997 and 1998 by Ross Moore ## Copyright (C) 1995 by Marcus E. Hennecke ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. if ($HTML_OPTIONS =~ /math/) { do { $DOCTYPE = ''; $STRICT_HTML = 0 } unless ($NO_SIMPLE_MATH||$NO_MATH_PARSING); } ######################### ## Support HTML 3.0 math #### Mathematical Formulas package main; sub do_env_math { local($_) = @_; local($math_mode, $failed, $labels, $comment,$img_params) = ("inline",'',''); $failed = (/$htmlimage_rx|$htmlimage_pr_rx/); # force an image local($attribs, $border); if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } local($saved) = $_; ($labels, $comment, $_) = &process_math_env($math_mode,$_); if ($failed) { $_ = join ('', $comment, $labels , ($USING_STYLES ? '' : '') , &process_undefined_environment("tex2html_wrap", $id, $saved) , ($USING_STYLES ? '' : '')) } elsif ($NO_SIMPLE_MATH) { if ($USING_STYLES) { $_ = join('', $comment, $labels , '', $_ , ""); } else { $_ = join('', $comment, $labels, " ", $_ ); } } else { $_ = join('', $comment, $labels, "\n$_\n"); } if (($border||($attributes))&&($HTML_VERSION > 2.1 )) { &make_table( $border, $attribs, '', '', '', $_ ) } else { $_ } } $math_start_rx = "(\\\$|\\\\\\(|\\\\math\\b)(\\begin(($O|$OP)\\d+($C|$CP))tex2html_wrap\\4)?"; $math_end_rx = "(\\end(($O|$OP)\\d+($C|$CP))tex2html_wrap\\7)?(\\\$|\\\\\\)|\\\\endmath\\b)"; sub do_env_tex2html_wrap { local($_) = @_; local($math_mode, $failed, $labels, $comment,$img_params) = ("inline",'',''); $failed = (/$htmlimage_rx|$htmlimage_pr_rx/); # force an image local($attribs, $border); if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } $* = 1; s/^\s*|\s*$//g; $*=0; local($saved) = $_; # if (s/^\\\(|^\$|^\\math|\\\)$|\$$|\\endmath//g) {} if (s/^$math_start_rx|${math_end_rx}$//g) {} elsif (/^\\ensuremath/om) { } else { $failed = 1 }; # catch non-math environments or commands ($labels, $comment, $_) = &process_math_env($math_mode,$_); if ($failed) { $_ = join ('', $comment, $labels , &process_undefined_environment("tex2html_wrap", $id, $saved)); } elsif ($NO_SIMPLE_MATH) { # no need for comment/labels if already inside a math-env if (defined $math_outer) { s/^\s*|\s*$//g } else { $_ = $comment . $labels ." ".$_; } } else { $_ = $comment . $labels . "\n$_\n"; } if (($border||($attribs))&&($HTML_VERSION > 2.1 )) { &make_table( $border, $attribs, '', '', '', $_ ) } else { $_ } } sub do_env_tex2html_wrap_inline { local($_) = @_; local($math_mode, $failed, $labels, $comment) = ("inline",'',''); $failed = (/$htmlimage_rx|$htmlimage_pr_rx/); # force an image local($attribs, $border); if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } local($saved) = $_; # s/(^\s*(\$|\\\()\s*|\s*(\$|\\\))\s*$)//g; # remove the \$ signs or \(..\) # s/^\\ensuremath(($O|$OP)\d+($C|$CP))(.*)\1/$4/; # remove an ensuremath wrapper if (s/^$math_start_rx|$math_end_rx$//gs ) {} elsif (s/^\\ensuremath(($O|$OP)\d+($C|$CP))(.*)\1/$4/){} # remove an ensuremath wrapper else { $failed = 1 } s/\\(begin|end)(($O|$OP)\d+($C|$CP))tex2html_wrap\w*\2//g; # remove wrappers $_ = &translate_environments($_) unless (($NO_SIMPLE_MATH)||($failed)); ($labels, $comment, $_) = &process_math_env($math_mode,$_); if ($failed) { if ($USING_STYLES) { $env_id =~ s/\"$/ image\"/; $env_id = ' CLASS="MATH"' if ($env_id =~ /^\s*$/); $_ = join ('', $labels, $comment, "" , &process_undefined_environment("tex2html_wrap_inline", $id, $saved) , ""); } else { $_ = join ('', $labels, $comment , &process_undefined_environment("tex2html_wrap_inline", $id, $saved)); } } elsif (($NO_SIMPLE_MATH)&&($USING_STYLES)) { $env_id = ' CLASS="MATH"' if ($env_id =~ /^\s*$/); $_ = join('', $labels, $comment, "", $_, ""); } elsif ($NO_SIMPLE_MATH) { $_ = join('', $labels, $comment, $_); } else { $_ = join('', $labels, $comment, "\n$_\n"); } if (($border||($attribs))&&($HTML_VERSION > 2.1 )) { &make_table( $border, $attribs, '', '', '', $_ ) } else { $_ } } # Allocate a fixed width for the equation-numbers: #$seqno = "\n"; $mvalign = ' VALIGN="MIDDLE"'; sub do_env_equation { local($_) = @_; local($math_mode, $failed, $labels, $comment) = ("equation",'',''); $failed = (/$htmlimage_rx|$htmlimage_pr_rx/); # force an image local($attribs, $border); if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } local($saved) = $_; local($sbig,$ebig); ($sbig,$ebig) = ('','') if (($DISP_SCALE_FACTOR)&&($DISP_SCALE_FACTOR >= 1.2 )); local($math_start,$math_end)= ($sbig,$ebig); local($eqno) = ' '; # spacer, when no numbering local($seqno) = join('',"\n\n"); $* = 1; do { # include the equation number, using a $global{'eqn_number'}++; $eqno = join('', $EQNO_START , &simplify(&translate_commands('\theequation')) , $EQNO_END); } unless ((s/(\\nonumber|\\notag)//g)||(/\\tag/)); if (s/\\tag(\*)?//){ # AmS-TEX line-number tags. local($nobrack,$before) = ($1,$`); $_ = $'; s/next_pair_pr_rx//o; if ($nobrack) { $eqno = $2 } else { $eqno = join('',$EQNO_START, $2, $EQNO_END ) } $_ = $before; } $* = 0; local($halign) = " ALIGN=\"CENTER\"" unless $FLUSH_EQN; if ($EQN_TAGS =~ /L/) { # equation number on left ($math_start,$math_end) = ( "\n\n" . $seqno . $eqno . "\n$sbig" , "$ebig\n
"); $border = $attribs = $env_id = ''; } else { # equation number on right ($math_start,$math_end) = ("\n\n" . "$sbig" , "$ebig". $seqno . $eqno ."\n"); $border = $attribs = $env_id = ''; } ($labels, $comment, $_) = &process_math_env($math_mode,$_); if ($failed) { $_ = join ('', $comment, $labels, $math_start , &process_undefined_environment('displaymath', $id, $saved) , $math_end ); } elsif ($NO_SIMPLE_MATH) { $_ = join('', "

", $labels , $comment, $math_start, "\n$_\n" , $math_end, "

" ); } else { $_ = join('', "" , $labels, $comment, $math_start , "\n\n" , $_ , "\n", $math_end ); } if (($border||($attribs))&&($HTML_VERSION > 2.1 )) { join('',"
\n\n" , &make_table( $border, $attribs, '', '', '', $_ ) , "\n
"); } else { $_ } } sub do_env_displaymath { local($_) = @_; local($math_mode, $failed, $labels, $comment) = ("display",'',''); $failed = (/$htmlimage_rx|$htmlimage_pr_rx/); # force an image local($attribs, $border); if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } local($saved) = $_; local($sbig,$ebig); ($sbig,$ebig) = ('','') if (($DISP_SCALE_FACTOR)&&($DISP_SCALE_FACTOR >= 1.2 )); ($labels, $comment, $_) = &process_math_env($math_mode,$_); if ($failed) { $_ = join('', $comment, "" , $labels , &process_undefined_environment("displaymath", $id, $saved ) , '

' ); } elsif ($NO_SIMPLE_MATH) { $_ =~ s//$&$sbig/sg; $_ = "$comment\n

$labels\n$sbig$_$ebig\n

" } else { $_ = join('', $comment, "", $labels , "$sbig\n\n",$_,"\n\n$ebig

"); } if (($border||($attribs))&&($HTML_VERSION > 2.1 )) { join('',"
\n\n" , &make_table( $border, $attribs, '', '', '', $_ ) , "\n
"); } else { $_ } } ### Some Common Structures ## Declare math mode and take care of sub- and superscripts. Also make ## sure to treat curly braces right. sub make_math { local($math_mode,$math_style,$math_face,$_) = @_; # Do spacing s/\\,/;SPMthinsp;/g; s/\\!/;SPMnegsp;/g; s/\\:/;SPMsp;/g; s/\\;/;SPMthicksp;/g; s/((^|[^\\])(\\\\)*)\\ /$1\\space /g; # convert \ to \space s/\\limits/\&limits;/g; # preserve the \limits commands # Find all _ and ^, but not \_ and \^ s/\\_/\\underscore/g; s/\\^/\\circflex/g; #RRM: The following code is just plain wrong !!! # local(@terms) = split(/([_^])/); # local($math,$i,$subsup,$level); # # Do the sub- and superscripts # $math = $terms[$[]; # for ( $i = $[+1; $i <= $#terms; $i+=2 ) { # $subsup = ( $terms[$i] eq "_" ? "SUB" : "SUP" ); # $_ = $terms[$i+1]; # if ( s/$next_pair_rx// ) { # $math .= "<$subsup>$2$_"; # } else { # s/^\s*(\w|\\[a-zA-Z]+)//; # $math .= "<$subsup>$1$_"; # }; # }; # $_ = $math; #RRM: This works much better (from &simple_math_env ). if ($NO_SIMPLE_MATH) { s/\&ldots;/.../g; $_ = &translate_math_commands($math_mode,$math_style,$math_face,0,$_); # remove redundant tags s/\s*<\/I>//go; s/<\/I>(\s*)/$1/go; } else { s/\^$any_next_pair_rx/$2<\/SUP>/go; s/_$any_next_pair_rx/$2<\/SUB>/go; s/\^(\\[a-zA-Z]+|.)/$1<\/SUP>/g; s/_(\\[a-zA-Z]+|.)/$1<\/SUB>/g; } s/\\underscore/\\_/g; s/\\circflex/\\^/g; s/&limits;//g; # not implemented, except via an image # Translate all commands inside the math environment $_ = &translate_commands($_) unless ($NO_SIMPLE_MATH); if ($NO_SIMPLE_MATH) { s/{/{/g; s/}/}/g; s/\s*×\s*/ x<\/TT> /g; # s/\s*×\s*/ × /g; s/\s*÷\s*/ ÷ /g; s/\s*&circ?;\s*/o<\/TT>/g; s/\s**\s*/ \*<\/TT> /g; s/\s*&l?dots;\s*/.../g; s/\s*∣\s*/ | /g; s/\s*|\s*/\|/g; s/\s*∥\s*/ || /g; s/;SPM(thin)?sp;/ /g; s/ / /g; s/&sp;/ /g; s/;SPMthicksp;/  /g; s/&thicksp;/  /g; s/  / /g; # &replace_math_constructions($math_mode); } else { # Inside , { and } have special meaning. Thus, need { # and } # s/{/{/g; s/}/}/g; # Where are these defined ? s/{/{/g; s/}/}/g; # Remove the safety markers for math-entities s/(\&\w+)#\w+;/$1;/g; # Substitute and with { and } to improve readability # on browsers that do not support math. s//$level++;'{'/ge; s/<\/BOX>/$level--;'}'/ge; # Make sure braces are matching. $_ .= '}' if ( $level > 0 ); $_ = '{'.$_ if ( $level < 0 ); # s/<\/?SUB>/_/g; s/<\/?SUP>/^/g; } # contract spaces s/(\s)\s+/\1/g; # remove bogus entities s/;SPMnegsp;//g; s/\&limits;/\\limits/g; # remove white space at the extremities # do{ $*=1; s/(^\s+|\s+$)//; $*=0; } unless ($NO_SIMPLE_MATH); $*=1; s/^\s//o;s/\s$//; $*=0; $_; } ## Fractions sub do_math_cmd_frac { local($_) = @_; local($fbarwidth,$optwidth) = &get_next_optional_argument; local($numer,$denom); local($cmd) = $cmd; if ($optwidth) { $optwidth = '' unless ($preamble =~ /[\{,]amstex[,\}]/ ) } $cmd = "frac" unless ($cmd =~ /frac/); $numer = &get_next_token(); # $numer = &missing_braces unless ( # (s/$next_pair_pr_rx/$numer = $2;''/e) # ||(s/$next_pair_rx/$numer = $2;''/e )); $denom = &get_next_token(); # $denom = &missing_braces unless ( # (s/$next_pair_pr_rx/$denom = $2;''/e) # ||(s/$next_pair_rx/$denom = $2;''/e )); if (($numer =~ /^\d$/)&&($denom =~ /^\d$/)) { local($frac) = &check_frac_entity($numer,$denom); if ($frac) { if ($NO_SIMPLE_MATH) { return ($frac , $_) } else { return ($frac . $_) } } } if ($NO_SIMPLE_MATH) { local($after) = $_; local($fracstyle) = ""; $fracstyle = "\\textstyle" if ( ($mode =~ /display|equation|eqnarray/) && ($numer =~ /^[\d\s]+$/)&& ($denom =~ /^[\d\s]+$/)); ( &process_math_in_latex( $mode, $math_style, $slevel , "{$fracstyle\\$cmd${optwidth}{$numer}{$denom}}") , $after ) } else { "$numer$denom$_" } } sub check_frac_entity { local($num,$den) = @_; local($ent,$cset,$char) = ("frac".$num.$den,$CHARSET,$char); $cset =~ s/\-/_/go; $cset = "\$${cset}_character_map{$ent}"; eval ("\$char = $cset"); $char; ''; # browsers don't recognise these characters yet. } ## Roots sub do_math_cmd_sqrt { local($_) = @_; local($n) = &get_next_optional_argument; local($surd) = &get_next_token(); if ($NO_SIMPLE_MATH) { local($after) = $_; ( &process_math_in_latex( $mode, $math_style, $slevel , "\\sqrt".( $n ? "[$n]" : '') . "{$surd}") , $after ) } else { $n ? "$n$surd$_" : "$surd$_"; } } sub do_math_cmd_thin_sp { ' '; } sub do_math_cmd_norm_sp { '&sp;'; } sub do_math_cmd_thick_sp { ' '; } %mathnomacros = ( 'omicron', 'o', 'Alpha', 'A', 'Beta', 'B', 'Epsilon', 'E', 'Zeta', 'Z', 'Eta', 'H', 'Iota', 'J', 'Kappa', 'K', 'Mu', 'M', 'Nu', 'N', 'Omicron', 'O', 'Rho', 'R', 'Tau', 'T', 'Chi', 'X' ); do { local($key, $val); foreach $key (keys %mathnomacros) { $val = $mathnomacros{$key}; $LaTeXmacros .= "\\providecommand{\\$key}{\\textrm{$val}}\n"; } }; %greekentities = ( # Greek letters %ISOgrk3; and %HTMLsymbol; 'alpha', 'alpha', 'beta', 'beta', 'gamma', 'gamma', 'delta', 'delta', 'epsilon', 'epsi', 'varepsilon', 'epsiv', 'zeta', 'zeta', 'eta', 'eta', 'theta', 'thetas', 'vartheta', 'thetav', 'iota', 'iota', 'kappa', 'kappa', 'lambda', 'lambda', 'mu', 'mu', 'nu', 'nu', 'xi', 'xi', 'pi', 'pi', 'varpi', 'piv', 'rho', 'rho', 'varrho', 'rhov', 'sigma', 'sigma', 'varsigma', 'sigmav', 'tau', 'tau', 'upsilon', 'upsi', 'phi', 'phis', 'varphi', 'phiv', 'chi', 'chi', 'psi', 'psi', 'omega', 'omega', 'Gamma', 'Gamma', 'Delta', 'Delta', 'Theta', 'Theta', 'Lambda', 'Lambda', 'Xi', 'Xi', 'Pi', 'Pi', 'Sigma', 'Sigma', 'Upsilon', 'Upsi', 'Phi', 'Phi', 'Psi', 'Psi', 'Omega', 'Omega', 'Alpha', 'Alpha', 'Beta', 'Beta', 'Epsilon', 'Epsilon', 'Zeta', 'Zeta', 'Eta', 'Eta', 'Iota', 'Iota', 'Kappa', 'Kappa', 'Mu', 'Mu', 'Nu', 'Nu', 'Omicron', 'Omicron', 'Rho', 'Rho', 'Tau', 'Tau', 'Chi', 'Chi', 'straightepsilon', 'epsis', 'omicron', 'omicron' ); %mathentities = ( # Ellipsis %ISOpub 'ldots', 'hellip', 'cdots', 'cdots', 'vdots', 'vellip', 'ddots', 'ddots', 'dotfill', 'dotfill', ### Mathematical Symbols %greekentities , # Binary operators %ISOnum %ISOamsb 'pm', 'plusmn', 'mp', 'mnplus', 'times', 'times', 'div', 'divide', 'ast', 'ast', 'star', 'sstarf', 'circ', 'cir', 'bullet', 'bull', 'cdot', 'sdot', 'cap', 'cap', 'cup', 'cup', 'uplus', 'uplus', 'sqcap', 'sqcap', 'sqcup', 'sqcup', 'vee', 'or', 'wedge', 'and', 'setminus', 'setmn', 'wr', 'wreath', 'diamond', 'diam', 'bigtriangleup', 'xutri', 'bigtriangledown', 'xdtri', 'triangleleft', 'ltri', 'triangleright', 'rtri', 'lhd', '', 'rhd', '', 'unlhd', '', 'unrhd', '', 'oplus', 'oplus', 'ominus', 'ominus', 'otimes', 'otimes', 'oslash', 'osol', 'odot', 'odot', 'bigcirc', 'xcirc', 'dagger', 'dagger', 'ddagger', 'Dagger', 'amalg', 'amalg', # Relations %ISOamsr %ISOtech 'leq', 'le', 'le', 'le', 'prec', 'pr', 'preceq', 'pre', 'll', 'Lt', 'subset', 'sub', 'subseteq', 'sube', 'sqsubset', 'sqsub', 'sqsubseteq', 'sqsube', 'in', 'isin', 'vdash', 'vdash', 'geq', 'ge', 'ge', 'ge', 'succ', 'sc', 'succeq', 'sce', 'gg', 'Gt', 'supset', 'sup', 'supseteq', 'supe', 'sqsupset', 'sqsup', 'sqsupseteq', 'sqsupe', 'ni', 'ni', 'dashv', 'dashv', 'owns', 'ni', 'equiv', 'equiv', 'sim', 'sim', 'simeq', 'sime', 'smallamalg', 'samalg', 'asymp', 'asymp', 'approx', 'ap', 'cong', 'cong', 'neq', 'ne', 'ne', 'ne', 'doteq', 'esdot', 'propto', 'prop', 'models', 'models', 'perp', 'perp', 'mid', 'mid', 'parallel', 'par', 'bowtie', 'bowtie', 'Join', '', 'smile', 'smile', 'frown', 'frown', 'vee', 'or', 'land', 'and', 'lor', 'or', # Arrows and pointers %ISOamsa %ISOnum 'leftarrow', 'larr', 'rightarrow', 'rarr', 'uparrow', 'uarr', 'downarrow', 'darr', 'Leftarrow', 'lArr', 'Rightarrow', 'rArr', 'Uparrow', 'uArr', 'Downarrow', 'dArr', 'longleftarrow', 'larr', 'longrightarrow', 'rarr', 'Longleftarrow', 'xlArr', 'Longrightarrow', 'xrArr', 'leftrightarrow', 'harr', 'Leftrightarrow', 'hArr', 'longleftrightarrow', 'xharr', 'Longleftrightarrow', 'xhArr', 'updownarrow', 'varr', 'Updownarrow', 'vArr', 'mapsto', 'map', 'longmapsto', 'map', 'hookleftarrow', 'larrhk', 'hookrightarrow', 'rarrhk', 'nearrow', 'nearr', 'searrow', 'drarr', 'swarrow', 'dlarr', 'nwarrow', 'nwarr', 'leftharpoonup', 'lharu', 'leftharpoondown', 'lhard', 'rightharpoonup', 'rharu', 'rightharpoondown', 'rhard', 'rightleftharpoons', 'rlhar2', 'leadsto', '', 'gets', 'larr', 'to', 'rarr', 'iff', 'iff', # Various other symbols %ISOpub %ISOamso %ISOnum %ISOtech 'aleph', 'aleph', 'hbar', 'planck', 'imath', 'inodot', 'jmath', 'jnodot', 'ell', 'ell', 'wp', 'weierp', 'Re', 'real', 'Im', 'image', 'beth', 'beth', 'gimel', 'gimel', 'daleth', 'daleth', 'emptyset', 'empty', 'nabla', 'nabla', 'surd', 'radic', 'top', 'top', 'bot', 'bottom', 'angle', 'ang', 'forall', 'forall', 'exists', 'exist', 'neg', 'not', 'flat', 'flat', 'natural', 'natur', 'sharp', 'sharp', 'partial', 'part', 'infty', 'infin', 'sphericalangle', 'angsph', 'varprime', 'vprime', 'sbs', 'sbsol', 'yen', 'yen', 'Box', '', 'Diamond', '', 'triangle', 'utri', 'clubsuit', 'clubs', 'diamondsuit', 'diams', 'heartsuit', 'hearts', 'spadesuit', 'spades', 'checkmark', 'check', 'maltese', 'malt', 'backslash', 'bsol', 'circledR', 'reg', 'centerdot', 'middot', 'prime', 'prime', 'square', 'square', # Integral type entities %ISOamsb 'sum', 'sum', 'prod', 'prod', 'coprod', 'coprod', 'int', 'int', 'oint', 'conint', # Delimiters %ISOamsc %ISOtech 'lfloor', 'lfloor', 'rfloor', 'rfloor', 'lceil', 'lceil', 'rceil', 'rceil', 'langle', 'lang', 'rangle', 'rang', 'lbrace', 'lcub', 'rbrace', 'rcub', 'lbrack', 'lsqb', 'rbrack', 'rsqb', 'Vert', 'Verbar', 'vert', 'vert', # AMS package # Greek letters 'digamma', 'gammad', 'varkappa', 'kappav', # Delimiters %ISOamsc 'ulcorner', 'ulcorn', 'urcorner', 'urcorn', 'llcorner', 'dlcorn', 'lrcorner', 'drcorn', 'leftparengtr', 'lpargt', 'rightparengtr', 'rpargt', # Arrows %ISOamsa 'dashrightarrow', '', 'dashleftarrow', '', 'leftleftarrows', 'larr2', 'leftrightarrows', 'lrarr2', 'Lleftarrow', 'lArr', 'twoheadleftarrow', 'Larr', 'leftarrowtail', 'larrtl', 'looparrowleft', 'larrlp', 'leftrightharpoons', 'lrhar2', 'curvearrowleft', 'cularr', 'circlearrowleft', 'olarr', 'Lsh', 'lsh', 'upuparrows', 'uarr2', 'upharpoonleft', 'uharl', 'downharpoonleft', 'dharl', 'multimap', 'mumap', 'leftrightsquigarrow', 'harrw', 'rightrightarrows', 'rarr2', 'rightleftarrows', 'rlarr2', 'Rrightarrow', 'rArr', 'twoheadrightarrow', 'Rarr', 'rightarrowtail', 'rarrtl', 'looparrowright', 'rarrlp', 'rightleftharpoons', 'rlhar2', 'curvearrowright', 'curarr', 'circlearrowright', 'orarr', 'Rsh', 'rsh', 'downdownarrows', 'darr2', 'upharpoonright', 'uharr', 'downharpoonright', 'dharr','rightsquigarrow', 'rarrw', # Negated arrows %ISOamsa 'nleftarrow', 'nlarr', 'nrightarrow', 'nrarr', 'nLeftarrow', 'nlArr', 'nRightarrow', 'nrArr', 'nleftrightarrow', 'nharr', 'nLeftrightarrow', 'nhArr', # Binary relations %ISOamsr %ISOamsb 'leqq', 'lE', 'leqslant', 'les', 'eqslantless', 'els', 'lesssim', 'lsim', 'lessapprox', 'lap', 'approxeq', 'ape', 'lessdot', 'ldot', 'lll', 'Ll', 'Ll', 'Ll', 'llless', 'Ll', 'lessgtr', 'lg', 'lesseqgtr', 'leg', 'lesseqqgtr', 'lEg', 'backcong', 'bcong', 'barwedge', 'barwed', 'doublebarwedge', 'Barwed', 'doublecap', 'Cap', 'doublecup', 'Cup', 'curlyvee', 'cuvee', 'curlywedge', 'cuwed', 'divideontimes', 'divonx', 'intercal', 'intcal', 'doteqdot', 'eDot', 'risingdotseq', 'erDot', 'Doteq', 'eDot', 'leftthreetimes', 'lthree', 'rightthreetimes', 'rthree', 'ltimes', 'ltimes', 'rtimes', 'rtimes', 'boxminus', 'minusb', 'boxplus', 'plusb', 'boxtimes', 'timesb', 'circledast', 'oast', 'circledcirc', 'ocirc', 'circleddash', 'odash', 'dotplus', 'plusdo', 'dotsquare', 'sdotb', 'smallsetminus', 'ssetmn', 'fallingdotseq', 'efDot', 'backsim', 'bsim', 'backsimeq', 'bsime', 'subseteqq', 'subE', 'Subset', 'Sub', 'curlypreceq', 'cupre', 'curlyeqprec', 'cuepr', 'precsim', 'prsim', 'precapprox', 'prap', 'vartriangleleft', 'vltri', 'trianglelefteq', 'ltrie', 'vDash', 'vDash', 'Vvdash', 'Vvdash', 'Vdash', 'Vdash', 'smallsmile', 'ssmile', 'smallfrown', 'sfrown', 'bumpeq', 'bumpe', 'Bumpeq', 'bump', 'coloneq', 'colone', 'eqcolon', 'ecolon', 'geqq', 'gE', 'geqslant', 'ges', 'eqslantgtr', 'egs', 'gtrsim', 'gsim', 'gtrapprox', 'gap', 'gtrdot', 'gsdot', 'ggg', 'Gg', 'Gg', 'Gg', 'gggtr', 'Gg', 'gtrless', 'gl', 'gtreqless', 'gel', 'gtreqqless', 'gEl', 'eqcirc', 'ecir', 'circeq', 'cire', 'triangleeq', 'trie', 'thicksim', 'thksim', 'thickapprox', 'thkap', 'supseteqq', 'supE', 'Supset', 'Sup', 'succcurlyeq', 'sccue', 'veebar', 'veebar', 'curlyeqsucc', 'cuesc', 'succsim', 'scsim', 'succapprox', 'scap', 'vartriangleright', 'vrtri', 'trianglerighteq', 'rtrie', 'shortmid', 'smid', 'shortparallel', 'spar', 'between', 'twixt', 'pitchfork', 'fork', 'bigstar', 'starf', 'varpropto', 'vprop', 'because', 'becaus', 'therefore', 'there4', 'backepsilon', 'bepsi', 'blacksquare', 'squf', 'lozenge', 'loz', 'blacklozenge', 'lozf', 'blacktriangle', 'utrif', 'blacktriangledown', 'dtrif', 'blacktriangleleft', 'ltrif', 'blacktriangleright', 'rtrif', # Negated binary relations %ISOamsn 'gnapprox', 'gnap', 'gneq', 'gne', 'gneqq', 'gnE', 'lnapprox', 'lnap', 'lneq', 'lne', 'lneqq', 'lnE', 'gnsim', 'gnsim', 'gvertneqq', 'gvnE', 'lnsim', 'lnsim', 'lvertneqq', 'lvnE', 'nsim', 'nsim', 'nsimeq', 'nsime', 'napprox', 'nap', 'ncong', 'ncong', 'nequiv', 'nequiv', 'ngeq', 'nge', 'ngeqq', 'ngE', 'ngeqslant', 'nges', 'ngtr', 'ngt', 'nleq', 'nle', 'nleqq', 'nlE', 'nleqslant', 'nles', 'nless', 'nlt', 'ntriangleleft', 'nltri', 'ntrianglelefteq', 'nltrie', 'ntriangleright', 'nrtri', 'ntrianglerighteq', 'nrtrie', 'nmid', 'nmid', 'nparallel', 'npar', 'nprec', 'npr', 'npreceq', 'npre', 'nsucc', 'nps', 'nsucceq', 'npse', 'nshortmid', 'nsmid', 'nshortparallel', 'nspar', 'nsubset', 'nsub', 'nsubseteq', 'nsube', 'nsubseteqq', 'nsubE', 'nsupset', 'nsup', 'nsupseteq', 'nsupe', 'nsupseteqq', 'nsupE', 'nvdash', 'nvdash', 'nvDash', 'nvDash', 'nVdash', 'nVdash', 'nVDash', 'nVDash', 'precnapprox', 'prnap', 'precneqq', 'prnE', 'precnsim', 'prnsim', 'succnapprox', 'scnap', 'succneqq', 'scnE', 'succnsim', 'scnsim', 'subsetneq', 'subne', 'subsetneqq', 'subnE', 'supsetneq', 'supne', 'supsetneqq', 'supnE', 'varsubsetneq', 'vsubne', 'varsubsetneqq', 'vsubnE', 'varsupsetneq', 'vsupne', 'varsupsetneqq', 'vsupnE', # Binary operators 'Cup', 'Cup', 'Cap', 'Cap', # miscellaneous %ISOamso 'hslash', 'planck', 'circledS', 'oS', 'nexists', 'nexist', 'varnothing', 'empty', 'measuredangle', 'angmsd', 'complement', 'comp', 'backprime', 'bprime', ); ## environments with alignment $array_env_rx = "array|cases|\\w*matrix"; ## from AMS-packages $array_env_rx .= "|\\w*align\\w*|split|gather|multline|(fl|x|xx)?align(at|ed)?"; $subAMS_array_env_rx = "\\w*align\\w*|split|gather|multline"; $sub_array_env_rx .= '|'.$subAMS_array_env_rx; ## Log-like Functions @mathfunctions = ('arccos', 'arcsin', 'arctan', 'arg', 'cos', 'cosh', 'cot', 'coth', 'csc', 'deg', 'dim', 'exp', 'hom', 'ker', 'lg', 'ln', 'log', 'sec', 'sin', 'sinh', 'tan', 'tanh', 'mod' ); @limitfunctions = ('det', 'gcd', 'inf', 'lim', 'liminf' , 'limsup', 'max', 'min', 'Pr', 'sup' ); foreach (@mathfunctions) { eval "sub do_math_cmd_$_\{\"$_\$_[\$[]\";}"; } foreach (@limitfunctions) { eval "sub do_math_cmd_$_\{ local(\$_) = \@_; s/^\\s*// unless ( \$math_mode eq \"inline\" ); \"$_\$_\";}"; } sub do_math_cmd_pmod { local($_) = @_; local($mod) = &get_next_token(); if ($NO_SIMPLE_MATH) { local($after) = $_; $mod = &process_math_toks($mode, $math_style, $face, $slevel, 0, $mod); join( '', "(mod $mod)", $after) } else {"(mod $mod)$_"} } sub do_math_cmd_bmod { local($_) = @_; local($mod) = ''; if ($NO_SIMPLE_MATH) { join( '', " mod " , $_) } else {"( mod )$_"} } sub do_math_cmd_circ { if ($NO_SIMPLE_MATH) { ("o","@_") } else { "o@_"} } ### Arrays sub do_env_array { local($_) = @_; if (($NO_SIMPLE_MATH)&&(!$math_mode)) { # if ($NO_SIMPLE_MATH) { # make an image $_ = &process_math_in_latex( $mode, $style, $slevel , "\\begin{array}". $_ . "\\end{array}"); # , "\\begin{array}". $_ ); return($_); } local($failed, $labels, $comment) = ('',''); local($attribs, $border); if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } local($saved) = $_; local($sbig,$ebig); ($sbig,$ebig) = ('','') if (($DISP_SCALE_FACTOR)&&($DISP_SCALE_FACTOR >= 1.2 ) &&($slevel == 0)&&(!($mode =~/inline/))); # $failed = 1 if ($NO_SIMPLE_MATH); # simplifies the next call # ($labels, $comment, $_) = &process_math_env($math_mode,$_); if (($failed)&&!($NO_SIMPLE_MATH)) { $_ = join ('', $labels, $comment , &process_undefined_environment("array", $id, $saved)); $_ = join('','2.0)? "$math_class" : '') ,'>', $labels, $comment, $_, '2.0)? " CLEAR=\"ALL\"" : '') , '>',"\n

"); if (($border||($attribs))&&($HTML_VERSION > 2.1 )) { $_ = join('',"
\n\n" , &make_table( $border, $attribs, '', '', '', $_ ) , "\n
"); } return ($_); } local($valign) = &get_next_optional_argument; if ( $valign =~ /^\s*b/ ) { $valign = " VALIGN=\"BOTTOM\"" } elsif ( $valign =~ /^\s*t/ ) { $valign = " VALIGN=\"TOP\"" } elsif (($NO_SIMPLE_MATH)&&($mode=~/inline/)) { $valign = "" } else { $valign = $mvalign }; local($colspec); $colspec = &missing_braces unless ( (s/$next_pair_pr_rx/$colspec = $2;''/e) ||(s/$next_pair_rx/$colspec = $2;''/e )); s/\n\s*\n/\n/g; # Remove empty lines (otherwise will have paragraphs!) local($i,@colspec,$char,$cols,$cell,$htmlcolspec,$frames,$rules); local(@rows,@cols,$border); local($colspan); $_ = &revert_array_envs($_); if ($NO_SIMPLE_MATH) { local($return) = ""; $env_id = ''; ($htmlcolspec,$frames,$rules,$cols,@colspec) = &translate_colspec($colspec, 'TD'); s/\\\\[ \t]*\[[^\]]*]/\\\\/g; # remove forced line-heights @rows = split(/\\\\/); $#rows-- if ( $rows[$#rows] =~ /^\s*$/ ); foreach (@rows) { $return .= "\n"; @cols = split(/$html_specials{'&'}/o); for ( $i = 0; $i <= $#colspec; $i++ ) { $colspec = $colspec[$i]; $colspan = 0; $cell = shift(@cols); # remove any \parbox commands, leaving the contents $cell =~ s/\\parbox[^<]*<<(\d*)>>([\w\W]*)<<\1>>/$1/g; if ($cell =~ /\\multicolumn/) { $id = $global{'max_id'}++; $cell = (($cell) ? &make_math($mode,'','', $cell) : "$cell"); } else { $id = $global{'max_id'}++; $cell = (($cell) ? &make_math($mode,'','', $cell) : "$cell"); } # remove leading/trailing space $cell =~ s/^\s*|\s*$//g; $cell = "\ " if ($cell eq ''); if ( $colspan ) { for ( $cellcount = 0; $colspan > 0; $colspan-- ) { $i++; $cellcount++; } $i--; $colspec =~ s/>$content_mark/ COLSPAN=$cellcount$&/; }; $colspec =~ s/$content_mark/${sbig}${cell}$ebig/; $return .= $colspec; }; $return .= ""; }; $_ = $return . "\n

"; if (($border||($attribs))&&($HTML_VERSION > 2.1 )) { $_ = join('',"
\n\n" , &make_table( $border, $attribs, '', '', '', $_ ) , "\n
"); } return ($_); } ($htmlcolspec,$frames,$rules,$cols,@colspec) = &translate_colspec($colspec, 'ITEM'); s/\\\\[ \t]*\[[^\]]*]/\\\\/g; # remove forced line-heights @rows = split(/\\\\/); $#rows-- if ( $rows[$#rows] =~ /^\s*$/ ); local($return) = "\n$htmlcolspec\n"; foreach (@rows) { $return .= ""; @cols = split(/$html_specials{'&'}/o); for ( $i = 0; $i <= $#colspec; $i++ ) { $colspec = $colspec[$i]; $colspan = 0; $cell = &make_math("", '', '', shift(@cols)); # May modify $colspan, $colspec if ( $colspan ) { for ( $cellcount = 0; $colspan > 0; $colspan-- ) { $colspec[$i++] =~ s/$content_mark/ COLSPAN=$cellcount$&/; }; $colspec =~ s/$content_mark/$cell/; $return .= $colspec; }; $return .= "\n"; }; $return .= "\n"; $failed = 1 if ($NO_SIMPLE_MATH); $return; } ### Delimiters $math_delimiters_rx = "^\\s*(\\[|\\(|\\\\{|\\\\lfloor|\\\\lceil|\\\\langle|\\/|\\||\\)|\\]|\\\\}|\\\\rfloor|\\\\rceil|\\\\rangle|\\\\backslash|\\\\\\||\\\\uparrow|\\\\downarrow|\\\\updownarrow|\\\\Uparrow|\\\\Downarrow|\\\\Updownarrow|\\.)"; %ord_brackets = ( 'le' , '{', 're', '}', 'lk', '[', 'rk', ']' ); ### Variable-sized operators $var_sized_ops_rx = "(sum|(co)?prod|(o|i+|idots)?int|big(cap|cup|vee|wedge|o(dot|times|plus)|uplus))"; $var_limits_rx = "(var(inj|proj)?lim(sup|inf)?)"; $arrow_over_ops_rx = "((ov|und)er(left|right)+arrow)"; sub do_math_cmd_left { local($_) = @_; s/$math_delimiters_rx//; $failed = 1 if ($NO_SIMPLE_MATH); "" . ( $1 && $1 ne "." ? "$1" : "" ) . $_ . ( /\\right/ ? "" : "" ); } sub do_math_cmd_right { local($_) = @_; s/$math_delimiters_rx//; if ( !($ref_before =~ //) ) { $ref_before = "" . $ref_before; }; $failed = 1 if ($NO_SIMPLE_MATH); ( $1 eq "." ? "" : "$1" ) . "$_"; } ### Multiline formulas sub do_env_eqnarray { local($_) = @_; local($math_mode, $failed, $labels, $comment, $doimage) = ("equation",'',''); local($attribs, $border); if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } local($eqnarray_warning) = "{eqnarray} does not have 3 columns, inserting blank cell"; local($saved) = $_; local($sbig,$ebig,$falign) = ('','','CENTER'); ($sbig,$ebig) = ('','') if (($DISP_SCALE_FACTOR)&&($DISP_SCALE_FACTOR >= 1.2 )); $failed = 1 if ($NO_SIMPLE_MATH); # simplifies the next call ($labels, $comment, $_) = &process_math_env($math_mode,$_); if (( $failed && !($NO_SIMPLE_MATH)) ||(/$htmlimage_rx|$htmlimage_pr_rx/)) { # ||((/$htmlimage_rx|$htmlimage_pr_rx/)&&($& =~/thumb/))) { # image of whole environment, no equation-numbers $failed = 1; $falign = (($EQN_TAGS =~ /L/)? 'LEFT' : 'RIGHT') unless $no_eqn_numbers; $_ = &process_undefined_environment( "eqnarray".(($no_eqn_numbers) ? "star" : '') , $id, $saved ); $_ = join('' , (($HTML_VERSION >2.0)? "

" : '') , $labels, $comment, $_ , (($HTML_VERSION >2.0)? "
\n

" : '') ); } elsif ($NO_SIMPLE_MATH) { $failed = 0; s/$htmlimage_rx/$doimage = $&;''/eo ; # force an image s/$htmlimage_pr_rx/$doimage .= $&;''/eo ; # force an image local($valign) = join('', " VALIGN=\"", ($NETSCAPE_HTML)? "BASELINE" : "MIDDLE", "\""); local($sarray, $srow, $slcell, $eccell, $srcell, $ercell, $erow, $earray); ($sarray, $eccell, $srcell, $erow, $earray, $sempty) = ( "\n\n" , "\n" , "", "\n", "\n" ); $sarray .= "ALIGN=\"CENTER\" WIDTH=\"100%\">"; $env_id = ''; local($seqno) = join('',"\n\n"); if ($EQN_TAGS =~ /L/) { # number on left ($srow, $slcell, $ercell) = ( "\n". $seqno , "\n" , "") , (($doimage)? '' : "\n") , (($labels)? $labels : "\n") , $comment, $sarray); foreach (@rows) { # displaymath $eqno = ' '; do { $global{'eqn_number'}++ ; $eqno = join('', $EQNO_START , &simplify(&translate_commands('\theequation')) , $EQNO_END ); } unless ((s/\\nonumber//)||($no_eqn_numbers)); $return .= $srow; $return .= $eqno if ($EQN_TAGS =~ /L/); $return .= $slcell; if (s/\\lefteqn//) { $return .= "\"LEFT\" COLSPAN=\"3\">"; $* =1; s/(^\s*|$html_specials{'&'}|\s*$)//g; $*=0; if (($doimage)||($failed)) { $_ = (($_)? &process_math_in_latex( "indisplay" , '', '', $doimage.$_ ):''); } else { $_ = &revert_array_envs($_); $_ = (($_) ? &make_math('display', '', '', $_) : "$_"); } if ($_) { $return .= join('', $sbig, $_, $ebig, $erow); } else { $return .= join('',"\ ", $erow); } next; } # columns to be set using math-modes @cols = split(/$html_specials{'&'}/o); # left column, set using \displaystyle $thismath = shift(@cols); $* =1; $thismath =~ s/(^\s*|\s*$)//g; $*=0; if (($doimage)||($failed)) { $thismath = (($thismath ne '')? &process_math_in_latex( "indisplay" , '', '', $doimage.$thismath ):''); } elsif ($thismath ne '') { $id = $global{'max_id'}++; $thismath = &revert_array_envs($thismath); $thismath = &make_math('displaymath', '', '', $thismath); } if ($thismath ne '') { $return .= join('',"\"RIGHT\">$sbig",$thismath,"$ebig"); } else { $return .= "\"RIGHT\">\ " } # center column, set using \textstyle $thismath = shift(@cols); if (!($#cols < 0)) { #print "\nEQNARRAY:$#cols : $thismath"; $* =1; $thismath =~ s/(^\s*|\s*$)//g; $*=0; if (($doimage)||($failed)) { $thismath = (($thismath ne '')? &process_math_in_latex( "indisplay" , 'text', '', $doimage.$thismath ):''); } elsif ($thismath ne '') { $id = $global{'max_id'}++; $thismath = &revert_array_envs($thismath); $thismath = &make_math('displaymath', '', '', $thismath); } if ($thismath ne '') { $return .= join('', $eccell, $sbig , $thismath, $ebig); } else { $return .= join('', $sempty,"\ ") } # right column, set using \displaystyle $thismath = shift(@cols); } else { $return .= join('', $sempty,"\ "); &write_warnings($eqnarray_warning); print "\n\n *** $eqnarray_warning \n"; } $* =1; $thismath =~ s/(^\s*|\s*$)//g; $*=0; if (($doimage)||($failed)) { $thismath = (($thismath ne '')? &process_math_in_latex( "indisplay" , '', '', $doimage.$thismath ):''); } elsif ($thismath ne '') { $id = $global{'max_id'}++; $thismath = &revert_array_envs($thismath); $thismath = &make_math('displaymath', '', '', $thismath); } if ($thismath ne '') { $return .= join('', $srcell, $sbig, $thismath, $ebig, $ercell); } else { $return .= join('', $sempty, "\ ", $ercell) } $return .= $eqno unless ($EQN_TAGS =~ /L/); $return .= $erow; } $_ = join('', $return , $earray, (($doimage)? '' : "" )); } else { $_ = join('', $comment, "$sbig" , $labels, "\n" , &do_env_array("$O$max_id${C}rcl$O$max_id$C$_") , "\n$ebig

" ) } if (($border||($attribs))&&($HTML_VERSION > 2.1 )) { join('',"
\n\n" , &make_table( $border, $attribs, '', '', '', $_ ) , "\n
"); } elsif ($failed &&($HTML_VERSION > 2.1 )) { local($fclass) = $math_class; $fclass =~ s/(ALIGN=\")[^"]*/$1$falign/; join('',"
\n\n" , $_ , "\n

") } else { join('', $_ , "\n

"); } } sub do_env_eqnarraystar { local($_) = @_; local($math_mode, $failed, $labels, $comment) = ("equation",'',''); $failed = (/$htmlimage_rx|$htmlimage_pr_rx/); # force an image local($attribs, $border); local($saved) = $_; local($sbig,$ebig); ($sbig,$ebig) = ('','') if (($DISP_SCALE_FACTOR)&&($DISP_SCALE_FACTOR >= 1.2 )); if (($NO_SIMPLE_MATH)||($failed)) { local($no_eqn_numbers) = 1; $_ = &do_env_eqnarray($_) unless ($failed); if ($failed) { if ($saved =~ s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } elsif ($saved =~ s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } $_ = join('', $labels # , &process_undefined_environment("eqnarraystar", $id, $saved)); , &process_undefined_environment("eqnarray*", $id, $saved)); } } else { if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } $saved = $_; ($labels, $comment, $_) = &process_math_env($math_mode,$_); if ($failed) { $_ = join('', $labels # , &process_undefined_environment("eqnarraystar", $id, $saved)); , &process_undefined_environment("eqnarray*", $id, $saved)); } else { $_ = join('', $comment, "$sbig", $labels , "\n" , &do_env_array("$O$max_id${C}rcl$O$max_id$C$_") , "\n$ebig

" ); } } if (($border||($attribs))&&($HTML_VERSION > 2.1 )) { $_ = &make_table( $border, $attribs, '', '', '', $_ ) } else { $_ } } sub do_math_cmd_nonumber { $_[$[]; }; ### Putting One Thing Above Another ## Over- and Underlining sub do_math_cmd_overline { local($_) = @_; local($over) = &get_next_token(1); if ($NO_SIMPLE_MATH) { local($supsub) = &get_supsub; local($after) = $_; ( &process_math_in_latex( $mode, $math_style, $slevel , "\\overline{$over}$supsub") , $after) } else {"$over$_" } } sub do_math_cmd_underline { local($_) = @_; local($under) = &get_next_token(1); if ($NO_SIMPLE_MATH) { local($supsub) = &get_supsub; local($after) = $_; ( &process_math_in_latex( $mode, $math_style, $slevel , "\\underline{$under}$supsub") , $after) } else { "$under$_" } } sub do_math_cmd_overbrace { local($_) = @_; local($over) = &get_next_token(1); if ($NO_SIMPLE_MATH) { local($supsub) = &get_supsub; local($after) = $_; ( &process_math_in_latex( $mode, $math_style, $slevel , "\\overbrace{$over}$supsub\\,") , $after) } else { "$over$_" } } sub do_math_cmd_underbrace { local($_) = @_; local($under) = &get_next_token(1); if ($NO_SIMPLE_MATH) { local($supsub) = &get_supsub; local($after) = $_; ( &process_math_in_latex( $mode, $math_style, $slevel , "\\underbrace{$under}$supsub\\,") , $after) } else { "$under$_" } } ## Accents sub do_math_cmd_vec { local($_) = @_; local($over) = &get_next_token(1); if ($NO_SIMPLE_MATH) { local($supsub) = &get_supsub; # \vec often makes the arrowhead fall outside its box # fix this by adding small space when at the end $supsub = "\\," unless ($supsub); local($after) = $_; ( &process_math_in_latex( $mode, $math_style, $slevel , "\\vec{$over}$supsub") , $after) } else { "$over$_" } } sub do_math_cmd_bar { local($_) = @_; local($over) = &get_next_token(1); if ($NO_SIMPLE_MATH) { local($supsub) = &get_supsub; local($after) = $_; ( &process_math_in_latex( $mode, $math_style, $slevel , "\\bar{$over}$supsub") , $after) } else { "$over$_" } } sub do_math_cmd_dot { local($_) = @_; local($over) = &get_next_token(1); if ($NO_SIMPLE_MATH) { local($supsub) = &get_supsub; local($after) = $_; ( &process_math_in_latex( $mode, $math_style, $slevel , "\\dot{$over}$supsub") , $after) } else { "$over$_" } } sub do_math_cmd_ddot { local($_) = @_; local($over) = &get_next_token(1); if ($NO_SIMPLE_MATH) { local($supsub) = &get_supsub; local($after) = $_; ( &process_math_in_latex( $mode, $math_style, $slevel , "\\ddot{$over}$supsub") , $after) } else { "$over$_" } } sub do_math_cmd_hat { local($_) = @_; local($over) = &get_next_token(1); if ($NO_SIMPLE_MATH) { local($supsub) = &get_supsub; local($after) = $_; ( &process_math_in_latex( $mode, $math_style, $slevel , "\\hat{$over}$supsub") , $after) } else { "$over$_" } } sub do_math_cmd_tilde { local($_) = @_; local($over) = &get_next_token(1); if ($NO_SIMPLE_MATH) { local($supsub) = &get_supsub; local($after) = $_; ( &process_math_in_latex( $mode, $math_style, $slevel , "\\tilde{$over}$supsub") , $after) } else { "$over$_" } } sub do_math_cmd_widehat { local($_) = @_; local($over) = &get_next_token(1); if ($NO_SIMPLE_MATH) { local($supsub) = &get_supsub; local($after) = $_; ( &process_math_in_latex( $mode, $math_style, $slevel , "\\widehat{$over}$supsub") , $after) } else { "$over$_" } } sub do_math_cmd_widetilde { local($_) = @_; local($over) = &get_next_token(1); if ($NO_SIMPLE_MATH) { local($supsub) = &get_supsub; local($after) = $_; ( &process_math_in_latex( $mode, $math_style, $slevel , "\\widetilde{$over}$supsub") , $after) } else { "$over$_" } } ## Stacking Symbols sub do_math_cmd_stackrel { local ($_) = @_; local($top,$bot); $top = &get_next_token(1); $bot = &get_next_token(1); if ($NO_SIMPLE_MATH) { local($after) = $_; ( &process_math_in_latex( $mode, $math_style, $slevel , "\\;\\stackrel{$top}{$bot}\\;") , $after) } else { "$2$top$_" } } # Kill $ref_before in case we're not in math mode. sub do_math_cmd_atop { local ($before) = $ref_before; $before =~ s/^[\s%]*//; $before =~ s/[\s%]*$//; $ref_before = ""; $failed = 1 if ($NO_MATH_MARKUP); "$before$_[$[]"; } sub do_math_cmd_choose { local ($before) = $ref_before; $before =~ s/^\s*//; $before =~ s/\s*$//; $ref_before = ""; $failed = 1 if ($NO_MATH_MARKUP); "$before$_[$[]"; } sub do_math_cmd_binom { &do_math_cmd_choose(@_) } sub do_math_cmd_mbox { local($_) = @_; local($cmd,$text,$after)=('mbox','',''); $text = &missing_braces unless ((s/$next_pair_pr_rx[\s%]*/$text = $2;''/eo) ||(s/$next_pair_rx[\s%]*/$text = $2;''/eo)); # incomplete macro replacement if ($text =~ /(^|[^\\<])#\d/) { return($_) } if ($NO_SIMPLE_MATH) { $after = $_; if (!($text)||($text =~ /^\s*$/)) { ("\  ", $after) } elsif (!($text =~ /tex2html_wrap_inline|^(($O|$OP)\d+($C|$CP))?\$|\$(($O|$OP)\d+($C|$CP))\4\$/)) { $text =~ s/$OP(\d+)$CP/$O$1$C/g; if ($text =~ /\$/) { $_ = $text; $text = &wrap_math_environment; } $text = &translate_environments("${O}1$C$text${O}1$C") if $text; $text = &translate_commands($text) if ($text =~ /\\/); $text =~ s/ $/;SPMnbsp;/; # preserve trailing spaces ($text, $after) } else { ( &process_math_in_latex( $mode, $math_style, $slevel , "\\mbox{$text}") , $after) } } else { "$text$_" } } sub do_math_cmd_display { $_[$[]; } sub do_math_cmd_text { $_[$[]; } sub do_math_cmd_script { $_[$[]; } sub do_math_cmd_scriptscript { $_[$[]; } # This is supposed to put the font back into math italics. # Since there is no HTML equivalent for reverting # to math italics we keep track of the open font tags in # the current context and close them. # *** POTENTIAL ERROR ****# # This will produce incorrect results in the exceptional # case where \mit is followed by another context # containing font tags of the type we are trying to close # e.g. {a \bf b \mit c {\bf d} e} will produce # a b c d e # i.e. it should move closing tags from the end sub do_math_cmd_mit { local($_, @open_font_tags) = @_; local($next); for $next (@open_font_tags) { $next = ($declarations{$next}); s/<\/$next>//; $_ = join('',"<\/$next>",$_); } $_; } $ams_aligned_envs_rx = "((\\w*align\\w*|gather\\w*|split|multline|array|cases)(\\*|star)?)"; $space_commands_rx = "(\\\\(q+uad|[,; ]|hs(kip|pace)(($O|$OP)\\d+($C|$CP))[^<]+\\4)|\\s)*"; sub translate_math_commands { local($mode,$style,$face,$slevel,$_) = @_; local($pre_text, $labels); if ($NO_MATH_PARSING) { s/\\\n/\\ \n/g; if ($_ =~ /$space_commands_rx\\(text|mbox)\b/) { $pre_text = $`; $_ = $& . $'; # Do not split if inside any kind of grouping local($pre_test,$use_all)=($pre_text,''); while ($pre_test =~ s/(($O|$OP)\d+($C|$CP))(.*)\1/$4/) {} $use_all = 1 if ($pre_test=~s/($O|$OP)\d+($C|$CP)//); if (!$use_all) { while ($pre_test =~ s/\\begin(($O|$OP)\d+($C|$CP))(.*)\\end\1/$4/){}; $use_all = 1 if ($pre_test=~s/\\(begin|end)($O|$OP)\d+($C|$CP)//); }; if (!$use_all) { local($gp_cnt) = 0; $pre_test =~ s/\\left\b/$gp_cnt++;''/eg; $pre_test =~ s/\\right\b/$gp_cnt--;''/eg; $use_all = 1 if $gp_cnt; }; if ($use_all) { $pre_text .= $_ ; $_ = '' }; } else { $pre_text = $_; $_ = ''; } ($pre_text,$labels) = &extract_labels($pre_text); local($savedRS) = $/; $/ = ''; $* = 1; # if ($pre_text =~ m/^((.|\n)*)\\begin\s*(($O|$OP)\d+($C|$CP))$ams_aligned_envs_rx\3/m) { if ($pre_text =~ m/^()\\begin\s*(($O|$OP)\d+($C|$CP))$ams_aligned_envs_rx\3/m) { local($env,$star,$orig,$cnt) = ($7,$8,$pre_text.$_,1); local($this_env,$pre_pre_text, $post_pre_text,$found) = ('', $1, $'.$_ , 1); $pre_text = $_ = ''; # local($savedRS) = $/; $/ = ''; $*=1; while ( $cnt && $found ) { $found = ''; if ($post_pre_text =~ /\\(begin|end)(($O|$OP)\d+($C|$CP))$env$star\2/s) { $pre_text .= $`; $found = $1; $this_env = $&; $post_pre_text = $'; } if ($found =~ /begin/) { $cnt++; $pre_text .= $this_env; } elsif ($found =~ /end/) { $cnt--; $pre_text .= $this_env if ($cnt > 0) ; } } $* = 0; $/ = $savedRS; $env .= 'star' if $star; local($env_cmd) = 'do_env_'.$env; # parse it further, when possible... if ((defined &$env_cmd) && !$cnt) { $_ = $post_pre_text . $_; $pre_text = join( '', $labels , &$env_cmd($pre_text) , (($_)? &translate_math_commands($mode ,$style,$face,$slevel,$_):'') ); return( $pre_pre_text . $pre_text ); } # ...else put it back inside a {displaymath} for an image if ($cnt) { $orig .= $_; $_ = ''; } local($math_env) = 'displaymath'; $math_env = $outer_math if ($outer_math =~ /^subequations/); $pre_text = join('', '\begin{',$math_env,'}' , $orig ,'\end{',$math_env,'}' ); local($after_undef) = $_; $pre_text = &process_undefined_environment( $math_env, ++$global{'max_id'}, $orig); $_ = $after_undef; } else { $pre_text = &process_math_in_latex($mode,$style,$slevel,$pre_text) if ($pre_text); } $* = 0; $/ = $savedRS; return($labels . $pre_text) unless ($_); local($post_text, $this_text, $which_text); if (/^$space_commands_rx\\(text|mbox)\b(($O|$OP)\d+($C|$CP))/){ local($end_text) = $8; $which_text = $7; $post_text = $'; $pre_text .= ";SPMnbsp; ;SPMnbsp;" if ($1); if ($post_text =~ /$end_text/) { $post_text = $'; $this_text = $`; if ($which_text =~ /mbox/) { $this_text = join('',$end_text,$this_text,$end_text); ($this_text) = &do_math_cmd_mbox($this_text); } else { $this_text = &translate_environments($this_text); $this_text = &translate_commands($this_text); } $post_text = &translate_math_commands( $mode ,$style,$face,$slevel,$post_text) if ($post_text); } $pre_text = join('', $pre_text, $this_text, $post_text); return($labels . $pre_text); } if ($pre_text) { $_ = join('', $labels , $pre_text , &translate_math_commands($mode,$style,$face,$slevel,$_)); } else { $_ = join('', $labels , $pre_text , &process_math_in_latex($mode,$style,$slevel,$_)); } return($_); } &replace_strange_accents; for (;;) { # For each opening bracket ... last unless (/$begin_cmd_rx/o); local($before, $contents, $br_id, $after, $pattern); ($before, $br_id, $after, $pattern) = ($`, $1, $', $&); local($end_cmd_rx) = &make_end_cmd_rx($br_id); if ($after =~ /$end_cmd_rx/) { # ... find the the matching closing one $NESTING_LEVEL++; ($contents, $after) = ($`, $'); $_ = join("", $before,"$OP$br_id$CP", $contents,"$OP$br_id$CP", $after); $NESTING_LEVEL--; } else { $pattern = &escape_rx_chars($pattern); s/$pattern//; print STDERR "\nCannot find matching bracket for $br_id"; } } # &parse_math_toks($mode,$style,$face,$slevel,1,$_); &process_math_toks($mode,$style,$face,$slevel,1,$_); } sub make_math_comment{ local($_) = @_; local($scomm,$ecomm)=("\$","\$"); return() if (/$image_mark/); do { $scomm = "\\begin{$env}\n"; $ecomm = "\n\\end{$env}"; } unless ($env =~/tex2html/); $_ = &revert_to_raw_tex; $* = 1; s/^\s+//; s/\s+$//; $* = 0; $_ = $scomm . $_ . $ecomm; return() if (length($_) < 12); $global{'verbatim_counter'}++; $verbatim{$global{'verbatim_counter'}} = $_; &write_mydb('verbatim_counter', $global{'verbatim_counter'}, $_ ); join('', $verbatim_mark, '#math' , $global{'verbatim_counter'},'#') } sub process_math_env { local($mode,$_) = @_; local($labels, $comment); ($_,$labels) = &extract_labels($_); # extract labels $comment = &make_math_comment($_); local($max_id) = ++$global{'max_id'}; if ($failed) { return($labels, $comment, $_) }; $_ = &protect_array_envs($_); if ($BOLD_MATH) { ($labels, $comment , join('','',&make_math($mode,'','',$_),'')) } else { ($labels, $comment, &make_math($mode,'','',$_)) } } sub process_math_toks { if ($NO_MATH_PARSING) { local($mode,$style,$face,$slevel,$math_outer,$_) = @_; if (/(aligned|gathered|alignedat|split)/) { #print "\n***SPECIAL AMS:\n$_\n"; } $_ = &process_math_in_latex($mode,$style,$slevel,$_); return($_); } &parse_math_toks(@_); } sub parse_math_toks { local($mode,$style,$face,$slevel,$math_outer,$_) = @_; local($pre,$keep,$this,$cmd,$tmp); local($lastclosespace, $joinspace) = (1,1); $face = "I" unless (($face)||($slevel)); # default text is italiced $face =~ s/math//; local($afterint) = 0; # device to detect integral d print "\$"; print STDERR "\nMATH_IN:$_" if ($VERBOSITY > 4); while ( /[\s%]*(\\([a-zA-Z]+|.)|$image_mark#[^#]+#|(<#\d*#>)|(<[^>]*>)(#math\d+#)?|\^|\_|&[a-zA-Z]+;|;SPM[a-z]+;|&)/ ) { $lastclosespace = 1; $joinspace=1; # $keep holds the results from processed tokens # $pre should be all simple letters and other characters $pre = $`; # $_ holds the tokens yet to come $_ = $'; # $this holds the current token $this = $1; if ($4) { # tags already processed from an earlier cycle # includes math-comment markers $this = $4.$5; $lastclosespace = 0; $joinspace=0; } elsif ($3) { # an opening brace local($br_idm) = $3; $_ = $br_idm.$_; if (s/$next_pair_pr_rx/$br_idm=$1; $this=$2;''/eo) { $this =~ s/^\s*//; $this =~ s/\s*$//; } else { s/$br_idm//; print "\n ** ignoring unmatched brace $br_idm in math **\n"; $this = ''; $br_idm = ''; } # if there is \atop.. or \over.. then make an image # Better would be to create a table after establishing # the minimum number of tokens involved... # ...but that's getting pretty complicated. if ($this =~ /\\(atop|over([^a-zA-Z]|withdelims))/) { print "."; print STDERR "$1" if ($VERBOSITY > 2); $this = "{".$this."}"; $this .= &get_supsub; $this = &process_math_in_latex($mode, $style, $slevel,$this); $lastclosespace = 0; } else { local($extra) = &get_supsub; # contents of $extra may require an image !! # revert the brace-pairs if ($extra =~ /{|}/) { &mark_string($extra); $extra =~ s/$O(\d+)$C/$OP$1$CP/g; } $this .= $extra; undef $extra; # otherwise the braces may delimit style-changes... do{ local(@save_open_tags) = @$open_tags_R; local($open_tags_R) = [ @save_open_tags ]; local($env_id) = $br_idm; $this = &parse_math_toks($mode,$style,$face,$slevel,0,$this); # $this .= &balance_tags(); undef $open_tags_R; undef @save_open_tags; }; # ...perhaps deliberate, to suppress space. $lastclosespace = 0; $joinspace=0; } } elsif (($2) && $new_command{$2}) { # macro-replacement required print "\nReplacing \\$2 " if ($VERBOSITY > 5); do { local($cmd,$after) = ($2,$_); $_ = &substitute_newcmd; print " with: $_\n" if ($VERBOSITY > 5); $_ .= $after; undef $cmd; undef $after; }; $this = ''; } elsif (($2) && ($2 =~/^latex$/)) { # discard the argument $this = &missing_braces unless ( (s/$next_pair_pr_rx\s*/$this = $2;''/eo) ||(s/$next_pair_rx\s*/$this = $2;''/eo)); $this = ''; } elsif (($2) && ($2 =~/(acute|breve|check|grave)$/)) { # accented characters, not implemented separately print "."; print STDERR "$1" if ($VERBOSITY > 2); $this .= join('', "{", &get_next_token(1), "}"); $this .= &get_supsub; $this = &process_math_in_latex($mode, $style, $slevel,$this); } elsif (($2) && ($2 =~/^end$/)) { s/^\s*(<[<#]\d+[#>]>)[^<>]*\1//o; $this = ''; } elsif (($2) && ($2 =~/^begin$/)) { # embedded environment; e.g. tex2html_wrap if (s/^\s*<([<#])(\d+)([#>])>(tex2html_(deferred|wrap(\w*)))<\1\2\3>//so) { $this = ''; } elsif (s/^\s*(<[<#](\d+)[#>]>)($array_env_rx)(\*|star)?\1//so) { print "."; print STDERR "$4$9" if ($VERBOSITY > 2); # make image, including any sup/sub-scripts local($id,$env,$star) = ($2,$3,$8); $this = "\\begin".$&; local ($saved) = $_; $_ = $'; # find the \end, including nested environments of same type. $* = 1; local($cnt, $thisbit, $which) = (1,'',''); while ( /\\(begin|end)(<#\d+#>)($env|$array_env_rx)(\*|star)?\2/s ) { $thisbit = $` . $&; $_ = $'; $which = $1; do { # mark rows/columns in nested arrays $thisbit =~ s/;SPMamp;/$array_col_mark/g; $thisbit =~ s/\\(\\|cr(cr)?(\b|$|\d|\W))/$array_row_mark$3/g; } if ($cnt > 1); $this .= $thisbit; if ($which =~ /begin/) {$cnt++} else {$cnt--}; last if (!$cnt); } $* = 0; # $this =~ s/\\cr(cr)?(\b|$|\d|\\|\W)/\\\\$2/g; local($env_cmd) = "do_env_$env".(($star)? "star" : ''); if ($cnt) { print "\n *** cannot find end of environment: $this "; &write_warnings("\n *** failed to find \\end for: $this "); $this = ''; $_ = $saved; # } elsif ($env =~ /^tex2html_wrap_(inline)?$/) { # $this =~ # s/^\\begin(($O|$OP)\d+($C|$CP))$env\1\s*|\\end(($O|$OP)\d+($C|$CP))$env\4\s*$//sg; # $_ = $this.$_; $this = ''; } elsif ($env =~ /^array/) { local($extra) = &get_supsub; if (($in_array)||($extra)||($pre)||($keep)) { $this .= $extra; $this = &process_math_in_latex($mode,$style,$slevel,$this); } else { $*=1; $star =~ s/\*/\\\*/o if ($star); $this =~ s/^\\begin(<#\d+#>)$env$star\1//; $this =~ s/\\end(<#\d+#>)$env$star\1\s*$//; $*=0; do { local($in_array) = 1; local($_) = $this; $this = &do_env_array($this); }; } } elsif (defined &$env_cmd) { $star =~ s/\*/\\\*/o if ($star); $this =~ s/^\\begin(<#\d+#>)$env$star\1//; $this =~ s/\\end(<#\d+#>)$env$star\1\s*$//; local($contents) = $_; $this = &$env_cmd($this); undef $contents; } else { $this .= &get_supsub; $this = &process_math_in_latex($mode,$style,$slevel,$this); }; undef $cnt; } else { #RRM: revert brace-processing, else translation loops s/$OP(\d+)$CP/$O$1$C/g; $this = ''; do { $_ = '\begin'.$_; $_ =~ s/^$begin_env_rx//; local($env, $mpat, $inner_math) = ($5, $&, $mode); &find_end_env($env,$this,$_); s/$O(\d+)$C/$OP$1$CP/g; local($br_id) = ++$global{'max_id'}; $this .= "\\end$O$br_id$C$env$O$br_id$C"; if ($env =~ /$ams_aligned_envs_rx/) { do { $NO_MATH_PARSING = 1; # $inner_math = ''; $this = &make_math($mode,$style,$face,$mpat.$this); $NO_MATH_PARSING = ''; }; } else { $this = &translate_environments($mpat.$this); $this = &translate_commands($this) if ($this =~ /\\/); s/$O(\d+)$C/$OP$1$CP/g; } undef $env; undef $mafter; undef $mpat; undef $inner_math; }; } } elsif (($2) && ($2 =~ /(\{|\}|\%|\|)/ )) { $this = $1; } elsif (($2) && ($2 =~ /\w+/)) { # macro or math-entity $cmd = $&; print "."; print STDERR "$cmd" if ($VERBOSITY > 2); local($mtmp, $ctmp, $wtmp) = ("do_math_cmd_$cmd","do_cmd_$cmd", "wrap_cmd_$cmd"); if ($cmd =~/color/) { do { local($color_env,$inside_math) = ($color_env,1); local(@save_open_tags) = @$open_tags_R; $open_tags_R = []; ($this, $_) = &$ctmp($_); $this = &parse_math_toks($mode,$style,$face,$slevel,1,$this); $open_tags_R = [ @save_open_tags ]; undef $color_env; undef $inside_math; undef @save_open_tags; }; } elsif ($cmd eq 'left') { #expandable delimiter: make an image $this = "\\$cmd"; local($blevel, $delim, $lfence, $rfence) = (1,'','',''); $delim = &get_next_token(); $lfence = $this . $delim; $this = ''; while (($blevel)&&(/(\\(left|right))([^a-zA-Z])/)) { $this .= $`.$1; $_ = $3.$'; if ($2 =~ /left/) { $blevel++ } else { $blevel-- } } $this =~ s/(\\right)$/$rfence=$1;''/e; local($mfence) = $this; local($fenced) = $this; $mfence =~ s/>\\par\\/>\\phantompar\\/g; # else \mathpalette fails $delim = &get_next_token(); $rfence .= $delim; if ($blevel) { print STDERR "\n *** unclosed \\left$delim starting:\n$this$_\n\n"; &write_warnings("\nunclosed \\left$delim found"); } undef $blevel; undef $delim; # make an image of the left-fence $this = &process_math_in_latex($mode,$style,$slevel , "$lfence\\vphantom{$mfence}\\right.") unless ($lfence eq '.'); #parse the math for the contents, as if in an array-env do { local($in_array) = 1; $infence = &parse_math_toks($mode,$style,$face,$slevel,1,$fenced); # and remove any paragraphing that may wrap the math contents. $infence =~ s/^]*>|]*>(\s*

\s*)?$//g; $this .= $infence; }; # make an image of the right-fence local($endthis) = "\\left.\\vphantom{$mfence}$rfence"; # include any super/sub scripts, to position them correctly local($rsub) = &get_supsub; $endthis .= $rsub; $this .= &process_math_in_latex($mode,$style,$slevel,$endthis) unless (($rfence =~ /\.$/) && !$rsub); $lastclosespace = 0; undef $endthis; undef $rsub; undef $infence; undef $in_array; } elsif ($cmd =~ /^brace(vert|[rl][ud])$/) { $this = $cmd; $this .= &get_supsub; $this = &process_math_in_latex($mode,$style,$slevel,"\\$this"); } elsif ($cmd =~ /(b|p)(m)?od$/) { local($pod) = $2; if ($cmd =~ /p/) { $this = &get_next_token(); $this = &parse_math_toks($mode,$style,$face,$slevel,1,$this); $this = "(".(($pod)? "mod " : '')."$this)"; } elsif (/^\s*\w/) { $this = " mod "; }else { $this = " mod" } } elsif ($cmd =~ /^(t|d)?frac$/) { ($this, $_) = &do_math_cmd_frac($_); } elsif ($cmd =~ /^(cases|matrix)$/) { $this = &missing_braces unless ( (s/$next_pair_pr_rx\s*/$this = $&;''/eo) ||(s/$next_pair_rx\s*/$this = $&;''/eo)); $this .= &get_supsub; $this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this"); } elsif ($cmd =~ /^(under|over|side)set$/) { # from AMS-math packages $this = &missing_braces unless ( (s/$next_pair_pr_rx\s*/$this = $&;''/eo) ||(s/$next_pair_rx\s*/$this = $&;''/eo)); $this .= &get_next_token(); # $this .= &missing_braces unless ( # (s/$next_pair_pr_rx\s*/$this .= $&;''/eo) # ||(s/$next_pair_rx\s*/$this .= $&;''/eo)); if ($cmd =~ /side/) { s/\s*\\\w+/$this .= $&;''/e; $this .= &get_supsub; } $this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this"); } elsif ($cmd =~ /^raisebox$/) { $this = &missing_braces unless ( (s/$next_pair_pr_rx\s*/$this = $&;''/eo) ||(s/$next_pair_rx\s*/$this = $&;''/eo)); local($arg, $pat) = &get_next_optional_argument; $this .= $pat; ($arg, $pat) = &get_next_optional_argument; $this .= $pat; $this .= &missing_braces unless ( (s/$next_pair_pr_rx\s*/$this .= $&;''/eo) ||(s/$next_pair_rx\s*/$this .= $&;''/eo)); undef $arg; undef $pat; $this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this"); } elsif ($cmd =~ /^choose|binom$/) { $this = &missing_braces unless ( (s/$next_pair_pr_rx\s*/$this = $&;''/eo) ||(s/$next_pair_rx\s*/$this = $&;''/eo)); $this .= &missing_braces unless ( (s/$next_pair_pr_rx\s*/$this .= $&;''/eo) ||(s/$next_pair_rx\s*/$this .= $&;''/eo)); $this .= &get_supsub; $this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this"); } elsif ($cmd =~ /^$var_sized_ops_rx|$var_limits_rx$/) { # entities generally come out too small for these $this = $cmd . &get_supsub; $this = &process_math_in_latex($mode,$style,$slevel,"\\$this"); $lastclosespace = 0; if ($cmd =~ /^(o|i+|idots)?int$/) { $afterint++; } } elsif (defined &$mtmp) { if ( grep(/\b$cmd\b/, @mathfunctions) || grep(/\b$cmd\b/, @limitfunctions)) { # it's a named function, to be set in upright text. $this = "$cmd"; local($orig) = $_; local($supsub) = &get_supsub; if ($supsub =~ /^\\limits/) { undef $orig; # let LaTeX handle the vertical alignment $this = &process_math_in_latex($mode,$style,$slevel , "\\$cmd$supsub" ); } elsif (($supsub)&&(grep(/\b$cmd\b/, @limitfunctions))) { undef $orig; # vertical alignment is implicit, use LaTeX $this = &process_math_in_latex($mode,$style,$slevel , "\\$cmd$supsub" ); } elsif ($supsub) { # contents of $supsub may require an image !! # parse the sup/subscripts $_ = $orig; undef $orig; } elsif (/^\s*\w/) { # ...else just put in the name + a space. $this .= "\ "; undef $orig; } else { # ...else just put in the name, no space needed. undef $orig; } undef $supsub; } elsif ($cmd =~ /^(circ)$/) { if ($_ =~ /^$/) {$this = "\○"} # ...\degrees else { $this = " \○ " } # ... as a binary relation } elsif ($cmd =~ /^text$/) { $this = &missing_braces unless ( (s/$next_pair_pr_rx\s*/$this = $2;''/eo) ||(s/$next_pair_rx\s*/$this = $2;''/eo)); $this =~ s/$OP/$O/og; $this =~ s/$CP/$C/og; $this = &translate_environments($this); $this = &translate_commands($this) if ($this =~ /\\/); } elsif ($cmd =~ /^h?phantom$/) { $this = &missing_braces unless ( (s/$next_pair_pr_rx\s*/$this = $2;''/eo) ||(s/$next_pair_rx\s*/$this = $2;''/eo)); #reduce all control sequences to a single character. $this =~ s/\\\w+/A/g; $this =~ s/\\./A/g; #approximate width with hard-spaces. $this = ";SPMnbsp;" x length($this); } elsif ($cmd =~ /^${var_sized_ops_rx}$/) { # entities generally come out too small for these $this = $cmd . &get_supsub; $this = &process_math_in_latex($mode,$style,$slevel,"\\$this"); $lastclosespace = 0; if ($cmd =~ /^o?int$/) { $afterint++; } } else { # do what comes naturally ... ($this, $_) = &$mtmp($_); s/^\s+//; # if not a box and doesn't return a pair, then add it to $_ # the result should be separated off in subsequent cycles. if (($this)&&(! $_)&&(!$cmd =~ /box/)) { $_= $this; $this ='' }; } } elsif (($mathentities{$cmd})||($latexsyms{$cmd})) { $ent = ($mathentities{$cmd} || $latexsyms{$cmd}); do { local($cset) = "${CHARSET}_character_map{$ent}"; $cset =~ s/\-/_/go; local($char); eval "\$char = \$$cset"; do { $cset = "${CHARSET}_character_map{$cmd}"; $cset =~ s/\-/_/go; eval "\$char = \$$cset"; $ent = $cmd if ($char); } unless ($char); $this = ($char ? $char : ''); undef($char); }; if ($this) { # do we want the character-code ... if ($USE_ENTITY_NAMES) { # ...or the entity ? $this = ";SPM$ent;"; } if ($greekentities{$cmd}) { # italicise greek symbols $this = "$this"; } } elsif ($cmd =~ /^(en|l?dots|gt|lt|times|div|mid|vert|parallel|ast)$/) { # standard entity $this = &get_supsub; if ($this) { $this = &process_math_in_latex($mode,$style,$slevel ,"\\$cmd$this" ); } else { $this = "\&$cmd;"; } } elsif ($cmd =~ /^(l|r)brac(k|e)$/) { $this = $ord_brackets{$1.$2}; } elsif ($cmd =~ /^cdot(s)?$/) { $this = join(''," \.",(($1)? "\.\." : '')," <\/SUP>"); } elsif ($cmd =~ /^l?dot(s)?$/) { $this = "\. ".(($1)? "\.\." : '')." "; } elsif ($cmd =~ /^backslash$/) { $this = "\\"; } elsif ($mathnomacros{$cmd}) { # standard entity, no-macro needed $cmd = $mathnomacros{$cmd}; $this = &get_supsub; if ($this) { $this = &process_math_in_latex($mode,$style,$slevel ,"\\textrm{$cmd}$this" ); } else { $this = "$cmd"; } } else { if ($cmd =~ /^int$/) { $afterint++; } # need an image $this = &get_supsub; $this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this" ); # relations, known to need more space $this = " $this " if ($cmd =~ /$binary_ops_rx|$binary_rels_rx|$arrow_rels_rx/); } } elsif (defined &$wtmp) { if ($cmd =~ /^(math(bb|cal|sf|sfsl)|cal)$/) { # not accessible !! # make images of these, including any sup/sub-scripts $this = &missing_braces unless ( (s/$next_pair_pr_rx\s*/$this = $2;''/e) ||(s/$next_pair_rx\s*/$this = $2;''/e)); $this = "\{".$this."\}"; # $this .= &get_supsub; $this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this" ); } elsif (defined &$ctmp) { # do what comes naturally ... ($this, $_) = &$ctmp($_); if (($this =~/\\/)||!($_)) {$_= $this; $this ='' }; } else { # make an image of all of it # $this = &missing_braces # unless ((s/$next_pair_pr_rx\s*//o)&&($this = "{$2}")); # $this .= &get_supsub; $this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$_" ); $_ = ''; } } elsif ($cmd =~ /big+[lrm]?$/i ) { s/\s*(\\(\W|[a-zA-Z]+)|\W)/$this=$1;''/eo; $this .= &get_supsub; $this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this" ); $lastclosespace = 0; $joinspace=0; } elsif ($cmd =~ /big(\w+)/ ) { local($tmpname) = $1; if (($mathentities{$tmpname})||($latexsyms{$tmpname})) { # big version standard entity $this = &get_supsub; $this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this" ); } else { # need an image $this = &get_supsub; $this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this" ); # relations, known to need more space $this = " $this " if ($tmpname =~ /$binary_ops_rx|$binary_rels_rx|$arrow_rels_rx/); } } elsif ($cmd =~ /begin$/) { local ($contents, $before, $br_id, $env, $after, $pattern); if ( s/^$begin_env_rx//o ) { local ($contents, $before, $br_id, $env, $after, $senv); ($before, $br_id, $env, $after, $senv) = ($`, $1, $2, $', $&); } else { print "\n *** badly formed $cmd *** "; } if (&find_end_env($env,$contents,$after)) { local($eenv) = "\\end$O$br_id$C"; $this = &translate_environments($senv.$contents.$eenv); } else { print "\n *** badly formed environment in math ***" } $_ = $after; } elsif ($cmd =~ /^not$/) { $this = &get_next_token(); $this = " ".&process_math_in_latex($mode,$style,$slevel,"\\$cmd$this" ); } elsif ($cmd =~ /(display|text|(script)+)style$/) { if ($1 =~ /scriptscript/) { $this = ""; # $slevel = 2; $this = ""; $pre .= ""; $_ .= ""; } elsif ($1 =~ /script/) { $this = ""; # $slevel = 1; $this = ""; $pre .= ""; $_ .= ""; } elsif ($slevel) { if ($1 =~ /display/) { $mode = "display" }# ; $slevel = 0 } elsif ($1 =~ /text/) { $mode = "inline" }# ; $slevel = 0 } $this = ""; # &process_math_in_latex($mode,$style,0,$_); $pre .= ""; $_ .= ""; } elsif ($1 =~ /display/) { $mode = "display"; $this = ''; # $slevel = 0; $this = ''; } elsif ($1 =~ /text/) { $mode = "inline"; $this = ''; # $slevel = 0; $this = ''; } } elsif (defined &$ctmp) { if ($cmd =~ /(bm|boldsymbol|(text|math)?(rm|tt|bf|it))$/) { # simulate these with ordinary fonts $this = &missing_braces unless ((s/$next_pair_pr_rx\s*/$this = $2;''/oe) ||(s/$next_pair_rx\s*/$this = $2;''/oe)); $this = &parse_math_toks($mode,$style ,$cmd,$slevel,$math_outer,$this); if ($cmd =~ /tt/) { $this =~ s/<(\/)?tt>/<$1TT>/g } elsif ($cmd =~ /bf|bm|boldsymbol/) { $this =~ s/<(\/)?($cmd|bf)>/<$1B>/g; } elsif ($cmd =~ /it/) { $this =~ s/<(\/)?($cmd|it)>/<$1I>/g } elsif ($cmd =~ /rm/) { $this =~ s/<(\/)?($cmd|rm)>//g } $this =~ s/\s+$//; # remove trailing space } elsif ($cmd =~ /^text$/) { $this = &missing_braces unless ((s/$next_pair_pr_rx\s*/$this = $2;''/oe) ||(s/$next_pair_rx\s*/$this = $2;''/oe)); $this = &translate_environments($this); $this = &translate_commands($this); } elsif ($cmd =~ /^math(op(en)?|ord|bin|rel|punct|close)/io) { # explicit math-class local($mtype,$orig,$supsub) = ($1,''); # get the contents $this = &missing_braces unless ( (s/$next_pair_pr_rx\s*/$this = $2;''/oe) ||(s/$next_pair_rx\s*/$this = $2;''/oe)); # see if there are sup/sub-scripts local($orig) = $_; local($supsub) = &get_supsub; if (($mtype =~/^op$/i) && ($supsub =~ /^\\limits/)) { # need an image for the vertical alignment undef $orig; do { $this = "${O}0$P$this${O}0$P"; &make_unique($this); }; $this = " ". &process_math_in_latex($mode,$style ,$slevel,"\\$cmd$this$supsub" ); } elsif (($mtype =~/^close$/i) && ($supsub)) { # need an image for the sup/sub placement undef $orig; do { $this = "${O}0$P$this${O}0$P"; &make_unique($this); }; $this = " ". &process_math_in_latex($mode,$style ,$slevel,"\\$cmd$this$supsub" ); } else { $_ = $orig; undef $orig; $this = &parse_math_toks($mode,$style ,'',$slevel,'',$this); $this =~ s/^\s*|\s*$//go; $this = " ".$this unless ($mstyle =~ /ord/i); $this .= " " if (!($supsub)&&($mstyle =~ /bin|rel|punct/i)); } undef $supsub; } elsif ($cmd =~ /^operatorname(\*|star|withlimits)?$/) { do { local($has_limits); $has_limits = 1 if ((s/^\*//)||($cmd=~/limits/)); $this = &missing_braces unless ((s/$next_pair_pr_rx\s*/$this = $2;''/oe) ||(s/$next_pair_rx\s*/$this = $2;''/oe)); local($this_cmd) = "<#0#>".$this."<#0#>"; local($cmd_name) = $this; local($pre_subp) = $_; local($cmd_supsub) = &get_supsub; if (($cmd_supsub)&&($has_limits)) { $this_cmd .= $cmd_supsub; $this = &process_math_in_latex($mode,$style,$slevel , "\\$cmd$this_cmd" ); } else { $_ = $pre_subp; $this = &parse_math_toks($mode,$style, "mathrm" ,$slevel, $math_outer, $cmd_name ); $this =~ s/<(\/)?rm>//g; } } } elsif ($cmd =~ /qopname/) { do{ $this = &missing_braces unless ((s/$next_pair_pr_rx\s*/$this = $2;''/oe) ||(s/$next_pair_rx\s*/$this = $2;''/oe)); local($this_cmd) = "<#0#>".$this."<#0#>"; $this = &missing_braces unless ((s/$next_pair_pr_rx\s*/$this = $2;''/oe) ||(s/$next_pair_rx\s*/$this = $2;''/oe)); $this_cmd .= "<#1#>".$this."<#1#>"; local($has_limits) = $this; $this = &missing_braces unless ((s/$next_pair_pr_rx\s*/$this = $2;''/oe) ||(s/$next_pair_rx\s*/$this = $2;''/oe)); $this_cmd .= "<#2#>".$this."<#2#>"; local($cmd_name) = $this; local($pre_subp) = $_; local($cmd_supsub) = &get_supsub; if (($cmd_supsub)&&!($has_limits =~ /^o$/)) { $this_cmd .= $cmd_supsub; $this = &process_math_in_latex($mode,$style,$slevel , "\\$cmd$this_cmd" ); } else { $_ = $pre_subp; $this = &parse_math_toks($mode,$style, "mathrm" ,$slevel, $math_outer, $cmd_name ); $this =~ s/<(\/)?rm>//g; } } } elsif ($cmd =~ /^(math|cal$)/io) { # catches \mathcal \mathsf \mathbb etc. and \cal $this = &missing_braces unless ( (s/$next_pair_pr_rx\s*/$this = $2;''/e) ||(s/$next_pair_rx\s*/$this = $2;''/e)); $this = "<#2#>".$this."<#2#>"; # $this .= &get_supsub; $this = &process_math_in_latex($mode,$style,$slevel , "\\$cmd $this" ); } elsif ($cmd =~ /(\w*)space/) { $this = "\ "; if (($1 =~ /h/)&&((s/$next_pair_pr_rx\s*//) ||(s/$next_pair_rx\s*//))) { $this = " \  " } } else { # do what comes naturally ... ($this, $_) = &$ctmp($_); if (($this =~/\\/)||!($_)) {$_= $this; $this ='' }; } } elsif ($newcommand{$cmd}) { $_ = &replace_new_command($cmd); } elsif ($cmd =~ /strut$/) { # ignore it print "\nignoring \\$cmd "; } elsif ($cmd =~ /^[vh]rule$/) { # ignore it $this = "$cmd"; do{ local($which,$len,$pxs,%dims); while (s/^\s*(height|width|depth)/$which=$1;''/e) { $this .= " ".$&; s/^\s*(\d+\.?\d*\w*)//; $this .= $&; ($pxs,$len) = &convert_length($1); $dims{$which} = $pxs; } if ($dims{'width'} == 0 || ($dims{'height'}+$dims{'depth'} == 0)) { print "\nignoring \\$cmd "; $this = ''; } else { $this = &process_math_in_latex($mode,$style,$slevel,"\\$this"); } }; } elsif ($cmd =~ /^$arrow_over_ops_rx$/) { $this = &missing_braces unless ( (s/$next_pair_pr_rx\s*/$this = $&;''/oe) ||(s/$next_pair_rx\s*/$this = $&;''/oe)); $this .= &get_supsub; $this = &process_math_in_latex($mode,$style,$slevel, "\\$cmd$this" ); } else { # Unknown: send it to LaTeX and hope for the best. &write_warnings("\nUnknown math command: \\$cmd , image needed."); $this = &get_supsub; $this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this" ); } } elsif ($this =~ /^\&(\w+)(#(\w+))?;/) { # math-entity code $cmd = $3; print "."; print STDERR "$cmd" if ($VERBOSITY > 2); do { $this = &get_supsub; $this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this" ) } if ($cmd); $this = " $this " if ($cmd =~ /$binary_ops_rx|$binary_rels_rx|$arrow_rels_rx/); } elsif ($this =~ /^\s*((\^)|\_)/) { # super/sub-script print "$1"; print STDERR "$2" if ($VERBOSITY > 2); $slevel++; local($BP) = (($2) ? "P" : "B"); $tmp = ""; $this = &get_next_token(1); if ($this =~ /$array_env_rx/) { $this = &process_math_in_latex($mode,$style,$slevel ,(($BP =~/P/)? '^':'_')."{$this}" ); } else { $this = &parse_math_toks($mode,$style,$face,$slevel,1,$this); } $this =~ s/^\s+//; $this =~ s/\s+$//; $this = join('', $tmp, $this, ""); $slevel--; $lastclosespace = 0; } elsif ($this =~ /^;SPM([a-z]+)/) { $this = " $this " if ($this =~ /;SPM(gt|lt|amp);/); } else { # just append it; e.g. images, etc. } $pre =~ s/\s+//g; #remove all spaces... if ($pre) { # put space back around numbers # $pre =~ s/([\d\.,]+)($|\W)/"$1".(($2)? " $2" :'')/eg; # $pre =~ s/([^\s\.,\(\[\/\w])(\d+)/$1 $2/g; #...italiced alphabetics, except if sup/subscripts if ($face eq "I") { $pre =~ s/([a-zA-Z][a-zA-Z\']*)/<$face>$1<\/$face>/go unless ($slevel); # ... but not inside <...> tags $pre =~ s/(<\/?)<$face>([a-zA-Z][a-zA-Z\']*)<\/$face>>/$1$2>/go; } else { # but all alphanumerics, with a special style $pre =~ s/(([\.\,]?\w[\w\']*)+)/<$face>$1<\/$face>/go } # but don't split multipliers from multiplicands $pre =~ s/(\d) )([\(\)\/])\s*/$1 $2/g; # ...and sometimes don't want spaces at the end $pre =~ s/([\w>\!\)\]\|])\s+$/$1/; # # ensure a space after last closing bracket, without sub/sub # $pre =~ s/([\)\]\|])$/$1 / if ($lastclosespace); $pre =~ s/\s+/ /g; } # remove redundant tags $this =~ s/<\/SU\1>//g; $this =~ s/<\/SU(P|B)>//g; # append processed tokens, forbidding some spaces; e.g. "> <". if ($pre) { if (( $keep =~/>\s*$/ )&&( $pre =~ /^\s*[<\(\{\[\w]/ )) { $keep =~ s/\s+$//; $pre =~ s/^\s+//; } if (( $keep =~/\w\s*$/ )&&( $pre =~ /^\s*[<\(\{[]/ )) { $keep =~ s/\s+$//; $pre =~ s/^\s+//; } # if (($pre =~/>\s*$/)&&($this =~ /^\s*\s*$/)&&($this =~ /^\s*([<\([\w])/)) { # $keep =~ s/\s+$//; $this =~ s/^\s+//; # } print STDERR "\nMATH:${math_outer}:${keep}:${pre}:${this}:" if ($VERBOSITY > 4); $keep .= $pre . $this; } # the leftovers should be all simple characters also. s/\s*//g; if ($_) { # s/([\d\.,]+)($|\W)/"$1".(($2)? " $2" :'')/eg; # s/([^\s\.,\(\[\/\w])(\d+)/$1 $2/g; if ($face eq "I") { s/([a-zA-Z][a-zA-Z\']*)/$1<\/I>/go unless ($slevel); # ...but not inside <...> tags s/(<\/?)([a-zA-Z\']+)<\/I>>/$1$2>/go; } elsif ($face) { s/(([\.\,]?\w[\w\']*)+)/<$face>$1<\/$face>/go } s/(\d+)<\/I>/$1/go unless ($slevel); s/(\d) )([\(\)\/])\s*/$1 $2/g; # ensure a space after some final characters, but not all # suppress this by enclosing the whole expression in {}s # s/([\)\]\|\.,!>\w])$/$1 /; # Why ? # $_ .= " " if ($math_outer); s/ +$//; # ignore trailing spaces } elsif ($math_outer) { # final space unless ending with or $keep .=" " unless (($keep =~/SU[BP]>$/)||(!$joinspace)); } # don't allow this space: "> <" if (($keep =~/>\s*$/)&&($_ =~ /^\s* 4); $keep .= $_; # # italiced superscripts can be too close to some letters... (what a hack!) # $keep =~ s/([a-zA-Z]<\/I>)\s*/$1 /g unless ($face =~ /it/); # $keep =~ s/([a-zA-Z\d]<\/it>)\s*/$1 /g if ($face =~ /it/); # # ...but nested superscripts are OK # $keep =~ s/([a-zA-Z]<\/(I|it)> <\2>[^<]+<\/\2>)( |\s)+/$1/g; # $keep =~ s/\s*( )+\s*/ /g; $keep =~ s/\s(\s)\s*/\1/g; $keep =~ s/^(\s*[\+\-]) ([\w\d])/$1$2/o; # unary plus/minus, not binary # $keep =~ s/([\,\:\|])(|\w)/$1 $2/g; # space after punctuation $keep =~ s/([\,\|])(|\w)/$1 $2/g; # space after punctuation # recognise an integral's differential; e.g. dx if (($afterint)&&($keep =~ s/(;SPM(thin|nb)sp;|~)\s*d/$1d/g)) { $afterint--; $keep =~ s/<\/I>// } $keep; } # the next token is either {...} or \ or an entity. sub get_next_token { local($strict) = @_; local($this,$cmd)=('',"^ or \_ "); do { s/$next_token_rx/$this = $&;''/eo; if ($strict &&(length($this) > 1)&&($this =~ /^\\/)) { local($tmp) = 'do_cmd_'.$'; if ((defined &$tmp)||($this =~ /^\\(math|text)/)) { $_ = $this .' '. $_; $this = &missing_braces(); } } } unless ( (s/$next_pair_pr_rx/$this = $2;''/eo) ||(s/$next_pair_rx/$this = $2;''/eo)); s/^$comment_mark\d+//o; $this =~ s/^\s*//o; if ($this =~ /^(\&|;)$/) { s/^([a-zA-Z]+;(#\w+;)?)/$this.=$1;''/eo; } elsif ($this eq '') { s/^\s*([&;][a-zA-Z]+;)/$this =$1;''/eo; } $this; } # This extracts sup/sub-scripts that follow immediately. # It alters $_ in the caller. # ...this is meant for code to be passed to LaTeX sub get_supsub { local($supsub,$supb,$which,$getit) = ('','',''); $supsub = "\\limits" if (s/^[\s%]*(\\limits|\&limits\;)//); while (s/^[\s%]*(\^|_|\'|\\prime|\\begin(($O|$OP)\d+($C|$CP))(Sb|Sp)\2)/$supb=$1;''/eo ) { $which .= $supb; if ($supb =~ /\^|\_/) { $getit = &get_next_token(1); $supsub .= join('', $supb,"\{",$getit,"\}") unless ($getit eq ''); } elsif ($5) { $supsub .= $1; $which .= (($5 =~ /b/) ? '_' : '^'); local($multisub_type) = $5; $* = 1; s/\\end(($O|$OP)\d+($C|$CP))$multisub_type\1/$supsub .= $`.$&;''/e; $* = 0; } else { $supsub .= "\{^\\prime\}" } } # include dummy sup/sub-scripts to enhance the vertical spacing # when not a nested sup/subscript do { $supsub .= "_{}" unless ($which =~ /\_|\\prime|\'/); $supsub .= "^{}" unless ($which =~ /\^|\'|\\prime/ ); } unless (($slevel)||(!$which)); $supsub =~ s/^\\limits$//; $supsub; } # These regular expressions help decide the type of a math-entity, # so that extra white space may be inserted, as desirable or necessary. #$binary_ops_rx = "(pm|mp|times|plus|minus|div|ast|star|circ|dot|triangle\\w|cap|cup|vee|wedge|bullet|diamond\$|wr\$|oslash|amalg|dagger|lhd|rhd)"; $binary_ops_rx = "(times|plus|minus|div|circ|dot|cap|cup|vee|wedge|wr\$|amalg|lhd|rhd)"; $binary_rels_rx = "(eq|prec|succ|\^ll\$|\^gg\$|subset|supset|\^in\$|\^ni\$|dash|sim|approx|cong|asymp|prop|models|perp|\^mid\$|parallel|bowtie|Join|smile|frown)"; $arrow_rels_rx = "(arrow|harpoon|mapsto|leadsto)"; &ignore_commands( <<_IGNORED_CMDS_); allowbreak mathord mathbin mathrel mathop mathopen mathclose mathpunct mathalpha mathrm mathbf mathtt mathit mathbb mathcal cal mathsf smash _IGNORED_CMDS_ # Commands which need to be passed, ALONG WITH THEIR ARGUMENTS, to TeX. &process_commands_inline_in_tex( <<_LATEX_CMDS_); #mathbb # {} #mathcal # {} #mathsf # {} _LATEX_CMDS_ 1;