Remove dead texvc code from the math extension

In T74240 support for LaTeX based rendering of the <math/>-tags was
removed. This change eliminates the unused code from the repository.

Bug: T195871
Change-Id: Ic57d83fa49f090b574ce8b82fd2ebc84a5350318
This commit is contained in:
Moritz Schubotz (physikerwelt) 2018-05-19 20:43:04 +02:00
parent 8879b5b7a1
commit 4156f1c9b7
No known key found for this signature in database
GPG Key ID: 73D26C61BAB32E94
44 changed files with 11 additions and 3966 deletions

View File

@ -1,117 +0,0 @@
<?php
/**
* MediaWiki math extension
*
* @copyright 2002-2015 Tomasz Wegrzanowski, Brion Vibber, Moritz Schubotz,
* and other MediaWiki contributors
* @license GPL-2.0-or-later
* @author Moritz Schubotz
*/
use MediaWiki\Logger\LoggerFactory;
class MathInputCheckTexvc extends MathInputCheck {
/**
* Converts an error returned by texvc to a localized exception
*
* @param string $texvcResult error result returned by texvc
* @param bool|MathRenderer $errorRenderer
* @return string
*/
public function convertTexvcError( $texvcResult, $errorRenderer = false ) {
$texvcStatus = substr( $texvcResult, 0, 1 );
$errDetails = htmlspecialchars( substr( $texvcResult, 1 ) );
if ( $errorRenderer === false ) {
$errorRenderer = new MathSource( $this->inputTeX );
}
switch ( $texvcStatus ) {
case 'E':
$errMsg = $errorRenderer->getError( 'math_lexing_error' );
break;
case 'S':
$errMsg = $errorRenderer->getError( 'math_syntax_error' );
break;
case 'F':
$errMsg = $errorRenderer->getError( 'math_unknown_function', $errDetails );
break;
default:
$errMsg = $errorRenderer->getError( 'math_unknown_error' );
}
return $errMsg;
}
/**
* @return bool
*/
public function isValid() {
$us = $this;
$checkWork = new PoolCounterWorkViaCallback( 'MathTexvc-check', "", [
'doWork' => function () use ( $us ) {
return $us->doValidCheck();
}
] );
return $checkWork->execute();
}
/**
* @return bool
*/
public function doValidCheck() {
global $wgMathTexvcCheckExecutable;
if ( $wgMathTexvcCheckExecutable === false ) {
$texvcCheckExecutable = __DIR__ . '/texvccheck/texvccheck';
} else {
$texvcCheckExecutable = $wgMathTexvcCheckExecutable;
}
if ( !is_executable( $texvcCheckExecutable ) ) {
$msg = 'Missing "texvccheck" executable. Please see math/README to configure.';
trigger_error( $msg, E_USER_NOTICE );
LoggerFactory::getInstance( 'Math' )->error( $msg );
return true;
}
$cmd = $texvcCheckExecutable . ' ' . wfEscapeShellArg( $this->inputTeX );
if ( wfIsWindows() ) {
# Invoke it within cygwin sh, because texvc expects sh features in its default shell
$cmd = 'sh -c ' . wfEscapeShellArg( $cmd );
}
LoggerFactory::getInstance( 'Math' )->debug( "TeX check command: $cmd" );
if ( strlen( $cmd ) > SHELL_MAX_ARG_STRLEN ) {
LoggerFactory::getInstance( 'Math' )->error(
"User input exceeded SHELL_MAX_ARG_STRLEN." );
return $this->convertTexvcError( '' );
}
$contents = wfShellExec( $cmd );
LoggerFactory::getInstance( 'Math' )->debug( "TeX check result: $contents\n---" );
if ( strlen( $contents ) === 0 ) {
LoggerFactory::getInstance( 'Math' )->warning( 'TeX check output was empty.' );
$this->lastError = $this->convertTexvcError( $contents );
return false;
}
$retval = substr( $contents, 0, 1 );
if ( $retval !== '+' ) {
$this->lastError = $this->convertTexvcError( $contents );
LoggerFactory::getInstance( 'Math' )->warning( 'checkTex failed: ' . $this->lastError );
return false;
} else {
$this->validTeX = substr( $contents, 1 );
$this->isValid = true;
LoggerFactory::getInstance( 'Math' )->debug(
'checkTex successful tex is now: ' . $this->validTeX );
return true;
}
}
}

View File

@ -1,493 +0,0 @@
<?php
/**
* MediaWiki math extension
*
* @copyright 2002-2012 Tomasz Wegrzanowski, Brion Vibber, Moritz Schubotz,
* and other MediaWiki contributors
* @license GPL-2.0-or-later
*
* Contains the driver function for the texvc program
* @file
*/
use MediaWiki\Logger\LoggerFactory;
use Wikimedia\Rdbms\Blob;
/**
* Takes LaTeX fragments, sends them to a helper program (texvc) for rendering
* to rasterized PNG and HTML and MathML approximations. An appropriate
* rendering form is picked and returned.
*
* @author Tomasz Wegrzanowski
* @author Brion Vibber
* @author Moritz Schubotz
* @deprecated will be deleted in one of the next versions without further notice
*/
class MathTexvc extends MathRenderer {
private $hash = '';
private $html = '';
private $conservativeness = 0;
const CONSERVATIVE = 2;
const MODERATE = 1;
const LIBERAL = 0;
const MW_TEXVC_SUCCESS = -1;
/**
* Gets an array that matches the variables of the class to the database columns
* @return array
*/
public function dbOutArray() {
$out = [];
$dbr = wfGetDB( DB_REPLICA );
$outmd5_sql = $dbr->encodeBlob( pack( 'H32', $this->hash ) );
if ( $outmd5_sql instanceof Blob ) {
$outmd5_sql = $outmd5_sql->fetch();
}
$out['math_outputhash'] = $outmd5_sql;
$out['math_html_conservativeness'] = $this->conservativeness;
$out['math_html'] = $this->html;
$out['math_mathml'] = utf8_encode( $this->getMathml() );
$out['math_inputhash'] = $this->getInputHash();
LoggerFactory::getInstance( 'Math' )->debug( 'Store Hashpath of image' .
bin2hex( $outmd5_sql ) );
return $out;
}
protected function dbInArray() {
return [ 'math_inputhash', 'math_outputhash',
'math_html_conservativeness', 'math_html', 'math_mathml' ];
}
/**
* @param stdClass $rpage
* @return bool
*/
protected function initializeFromDatabaseRow( $rpage ) {
parent::initializeFromDatabaseRow( $rpage );
// get deprecated fields
if ( $rpage->math_outputhash ) {
$dbr = wfGetDB( DB_REPLICA );
$xhash = unpack( 'H32md5',
$dbr->decodeBlob( $rpage->math_outputhash ) . " " );
$this->hash = $xhash['md5'];
LoggerFactory::getInstance( 'Math' )->debug( 'Hashpath of PNG-File:' .
bin2hex( $this->hash ) );
$this->conservativeness = $rpage->math_html_conservativeness;
$this->html = $rpage->math_html;
return true;
} else {
return false;
}
}
/**
* Renders TeX using texvc
*
* @return string rendered TeK
*/
public function render() {
if ( !$this->readCache() ) { // cache miss
$result = $this->callTexvc();
if ( $result === self::MW_TEXVC_SUCCESS ) {
return true;
} else {
$this->lastError = $result;
return false;
}
}
return true;
}
/**
* Gets path to store hashes in
*
* @return string Storage directory
*/
public function getHashPath() {
$path = $this->getBackend()->getRootStoragePath() .
'/math-render/' . $this->getHashSubPath();
LoggerFactory::getInstance( 'Math' )->debug(
"TeX: getHashPath, hash is: {$this->getHash()}, path is: $path" );
return $path;
}
/**
* Gets relative directory for this specific hash
*
* @return string Relative directory
*/
public function getHashSubPath() {
return substr( $this->getHash(), 0, 1 )
. '/' . substr( $this->getHash(), 1, 1 )
. '/' . substr( $this->getHash(), 2, 1 );
}
/**
* Gets URL for math image
*
* @return string image URL
*/
public function getMathImageUrl() {
global $wgMathPath;
$dir = $this->getHashSubPath();
return "$wgMathPath/$dir/{$this->getHash()}.png";
}
/**
* Gets img tag for math image
*
* @return string img HTML
*/
public function getMathImageHTML() {
$url = $this->getMathImageUrl();
$attributes = [
// the former class name was 'tex'
// for backwards compatibility we keep that classname
'class' => 'mwe-math-fallback-image-inline tex',
'alt' => $this->getTex()
];
if ( $this->getMathStyle() === 'display' ) {
// if DisplayStyle is true, the equation will be centered in a new line
$attributes[ 'class' ] = 'mwe-math-fallback-image-display tex';
}
return Xml::element( 'img',
$this->getAttributes(
'img',
$attributes,
[
'src' => $url
]
)
);
}
/**
* Converts an error returned by texvc to a localized exception
*
* @param string $texvcResult error result returned by texvc
* @return string
*/
public function convertTexvcError( $texvcResult ) {
$errorConverter = new MathInputCheckTexvc();
return $errorConverter->convertTexvcError( $texvcResult, $this );
}
/**
* Does the actual call to texvc
*
* @return int|string MW_TEXVC_SUCCESS or error string
*/
public function callTexvc() {
global $wgTexvc, $wgTexvcBackgroundColor, $wgHooks;
if ( $wgTexvc === false ) {
$texvc = __DIR__ . '/math/texvc';
} else {
$texvc = $wgTexvc;
}
$tmpDir = wfTempDir();
if ( !is_executable( $texvc ) ) {
LoggerFactory::getInstance( 'Math' )->error(
"$texvc does not exist or is not executable." );
return $this->getError( 'math_notexvc' );
}
$escapedTmpDir = wfEscapeShellArg( $tmpDir );
$cmd = $texvc . ' ' .
$escapedTmpDir . ' ' .
$escapedTmpDir . ' ' .
wfEscapeShellArg( $this->getUserInputTex() ) . ' ' .
wfEscapeShellArg( 'UTF-8' ) . ' ' .
wfEscapeShellArg( $wgTexvcBackgroundColor );
if ( wfIsWindows() ) {
# Invoke it within cygwin sh, because texvc expects sh features in its default shell
$cmd = 'sh -c ' . wfEscapeShellArg( $cmd );
}
LoggerFactory::getInstance( 'Math' )->debug( "TeX: $cmd" );
LoggerFactory::getInstance( 'Math' )->debug( "Executing '$cmd'." );
$retval = null;
if ( strlen( $cmd ) > SHELL_MAX_ARG_STRLEN ) {
LoggerFactory::getInstance( 'Math' )->error(
"User input exceeded SHELL_MAX_ARG_STRLEN." );
return $this->getError( 'math_unknown_error' );
}
$contents = wfShellExec( $cmd, $retval );
LoggerFactory::getInstance( 'Math' )->debug( "TeX output:\n $contents\n---" );
if ( strlen( $contents ) == 0 ) {
if ( !file_exists( $tmpDir ) || !is_writable( $tmpDir ) ) {
LoggerFactory::getInstance( 'Math' )->error(
"TeX output directory $tmpDir is missing or not writable" );
return $this->getError( 'math_bad_tmpdir' );
} else {
LoggerFactory::getInstance( 'Math' )->error(
"TeX command '$cmd' returned no output and status code $retval." );
return $this->getError( 'math_unknown_error' );
}
}
$tempFsFile = new TempFSFile( "$tmpDir/{$this->getHash()}.png" );
$tempFsFile->autocollect(); // destroy file when $tempFsFile leaves scope
$retval = substr( $contents, 0, 1 );
$errmsg = '';
if ( ( $retval == 'C' ) || ( $retval == 'M' ) || ( $retval == 'L' ) ) {
if ( $retval == 'C' ) {
$this->setConservativeness( self::CONSERVATIVE );
} elseif ( $retval == 'M' ) {
$this->setConservativeness( self::MODERATE );
} else {
$this->setConservativeness( self::LIBERAL );
}
$outdata = substr( $contents, 33 );
$i = strpos( $outdata, "\000" );
$this->setHtml( substr( $outdata, 0, $i ) );
$this->setMathml( substr( $outdata, $i + 1 ) );
} elseif ( ( $retval == 'c' ) || ( $retval == 'm' ) || ( $retval == 'l' ) ) {
$this->setHtml( substr( $contents, 33 ) );
if ( $retval == 'c' ) {
$this->setConservativeness( self::CONSERVATIVE );
} elseif ( $retval == 'm' ) {
$this->setConservativeness( self::MODERATE );
} else {
$this->setConservativeness( self::LIBERAL );
}
$this->setMathml( null );
} elseif ( $retval == 'X' ) {
$this->setHtml( null );
$this->setMathml( substr( $contents, 33 ) );
$this->setConservativeness( self::LIBERAL );
} elseif ( $retval == '+' ) {
$this->setHtml( null );
$this->setMathml( null );
$this->setConservativeness( self::LIBERAL );
} else {
$errmsg = $this->convertTexvcError( $contents );
}
if ( !$errmsg ) {
$newHash = substr( $contents, 1, 32 );
if ( $this->hash !== $newHash ) {
// DB needs update in writeCache() (bug 60997)
$this->isInDatabase();
}
$this->setHash( $newHash );
}
// Avoid PHP 7.1 warning from passing $this by reference
$renderer = $this;
Hooks::run( 'MathAfterTexvc', [ &$renderer, &$errmsg ] );
if ( $errmsg ) {
return $errmsg;
} elseif ( !preg_match( "/^[a-f0-9]{32}$/", $this->getHash() ) ) {
return $this->getError( 'math_unknown_error' );
} elseif ( !file_exists( "$tmpDir/{$this->getHash()}.png" ) ) {
return $this->getError( 'math_image_error' );
} elseif ( filesize( "$tmpDir/{$this->getHash()}.png" ) == 0 ) {
return $this->getError( 'math_image_error' );
}
$hashpath = $this->getHashPath(); // final storage directory
$backend = $this->getBackend();
# Create any containers/directories as needed...
if ( !$backend->prepare( [ 'dir' => $hashpath ] )->isOK() ) {
return $this->getError( 'math_output_error' );
}
// Store the file at the final storage path...
// Bug 56769: buffer the writes and do them at the end.
if ( !isset( $wgHooks['ParserAfterParse']['FlushMathBackend'] ) ) {
$backend->mathBufferedWrites = [];
$wgHooks['ParserAfterParse']['FlushMathBackend'] = function () use ( $backend ) {
global $wgHooks;
unset( $wgHooks['ParserAfterParse']['FlushMathBackend'] );
$backend->doQuickOperations( $backend->mathBufferedWrites );
unset( $backend->mathBufferedWrites );
};
}
$backend->mathBufferedWrites[] = [
'op' => 'store',
'src' => "$tmpDir/{$this->getHash()}.png",
'dst' => "$hashpath/{$this->getHash()}.png",
'ref' => $tempFsFile // keep file alive
];
return self::MW_TEXVC_SUCCESS;
}
/**
* Gets file backend
*
* @return FileBackend appropriate file backend
*/
public function getBackend() {
global $wgMathFileBackend, $wgMathDirectory;
if ( $wgMathFileBackend ) {
return FileBackendGroup::singleton()->get( $wgMathFileBackend );
} else {
static $backend = null;
if ( !$backend ) {
$backend = new FSFileBackend( [
'name' => 'math-backend',
'wikiId' => wfWikiID(),
'lockManager' => new NullLockManager( [] ),
'containerPaths' => [ 'math-render' => $wgMathDirectory ],
'fileMode' => 0777,
'obResetFunc' => 'wfResetOutputBuffers',
'streamMimeFunc' => [ 'StreamFile', 'contentTypeFromPath' ]
] );
}
return $backend;
}
}
/**
* Does the HTML rendering
*
* @return string HTML string
*/
public function getHtmlOutput() {
return $this->getMathImageHTML();
}
/**
* Overrides base class. Writes to database, and if configured, squid.
* @return bool
*/
public function writeCache() {
global $wgUseSquid;
$updated = parent::writeCache();
// If we're replacing an older version of the image, make sure it's current.
if ( $updated && $wgUseSquid ) {
$urls = [ $this->getMathImageUrl() ];
$u = new CdnCacheUpdate( $urls );
$u->doUpdate();
}
return $updated;
}
/**
* Reads the rendering information from the database. If configured, checks whether files exist
*
* @return bool true if retrieved, false otherwise
*/
public function readCache() {
global $wgMathCheckFiles;
if ( $this->isInDatabase() ) {
if ( !$wgMathCheckFiles ) {
// Short-circuit the file existence & migration checks
return true;
}
$filename = $this->getHashPath() . "/{$this->getHash()}.png"; // final storage path
$backend = $this->getBackend();
if ( $backend->fileExists( [ 'src' => $filename ] ) ) {
if ( $backend->getFileSize( [ 'src' => $filename ] ) == 0 ) {
// Some horrible error corrupted stuff :(
$backend->quickDelete( [ 'src' => $filename ] );
} else {
return true; // cache hit
}
}
}
return false;
}
public function getPng() {
global $wgHooks;
// Workaround for bugfix for Bug 56769
if ( isset( $wgHooks['ParserAfterParse']['FlushMathBackend'] ) ) {
// XXX: save any pending files so the read below works
call_user_func( $wgHooks['ParserAfterParse']['FlushMathBackend'] );
}
$backend = $this->getBackend();
return $backend->getFileContents(
[ 'src' => $this->getHashPath() . "/" . $this->getHash() . '.png' ]
);
}
public function isInDatabase() {
$return = parent::isInDatabase();
if ( $this->hash && $return ) {
return true;
} else {
return false;
}
}
/**
* Get the hash calculated by texvc
*
* @return string hash
*/
public function getHash() {
return $this->hash;
}
/**
* @param string $hash
*/
public function setHash( $hash ) {
$this->changed = true;
$this->hash = $hash;
}
/**
* Returns the html-representation of the mathematical formula.
* @return string
*/
public function getHtml() {
return $this->html;
}
/**
* @param string $html
*/
public function setHtml( $html ) {
$this->changed = true;
$this->html = $html;
}
/**
* Gets the so called 'conservativeness' calculated by texvc
*
* @return int
*/
public function getConservativeness() {
return $this->conservativeness;
}
/**
* @param int $conservativeness
*/
public function setConservativeness( $conservativeness ) {
$this->changed = true;
$this->conservativeness = $conservativeness;
}
protected function getMathTableName() {
return 'math';
}
public function setOutputHash( $hash ) {
$this->hash = $hash;
}
/**
* Skip tex check for texvc rendering mode.
* Checking the tex code in texvc mode just adds a dependency to the
* texvccheck binary which does not improve security since the same
* checks are performed by texvc anyhow. Especially given the fact that
* texvccheck was derived from texvc.
* @return bool
*/
public function checkTeX() {
return true;
}
}

View File

@ -1,11 +0,0 @@
--
-- Used by the math module to keep track
-- of previously-rendered items.
--
CREATE TABLE /*$wgDBprefix*/math (
math_inputhash varbinary(16) NOT NULL PRIMARY KEY,
math_outputhash varbinary(16) NOT NULL,
math_html_conservativeness tinyint NOT NULL,
math_html NVARCHAR(MAX),
math_mathml NVARCHAR(MAX),
);

View File

@ -1,21 +0,0 @@
--
-- Used by the math module to keep track
-- of previously-rendered items.
--
CREATE TABLE /*_*/math (
-- Binary MD5 hash of the latex fragment, used as an identifier key.
math_inputhash varbinary(16) NOT NULL PRIMARY KEY,
-- Not sure what this is, exactly...
math_outputhash varbinary(16) NOT NULL,
-- texvc reports how well it thinks the HTML conversion worked;
-- if it's a low level the PNG rendering may be preferred.
math_html_conservativeness tinyint NOT NULL,
-- HTML output from texvc, if any
math_html text,
-- MathML output from texvc, or from LaTeXML
math_mathml text
) /*$wgDBTableOptions*/;

View File

@ -1,8 +0,0 @@
CREATE TABLE &mw_prefix.math (
math_inputhash VARCHAR2(32) NOT NULL,
math_outputhash VARCHAR2(32) NOT NULL,
math_html_conservativeness NUMBER NOT NULL,
math_html CLOB,
math_mathml CLOB
);
CREATE UNIQUE INDEX &mw_prefix.math_u01 ON &mw_prefix.math (math_inputhash);

View File

@ -1,7 +0,0 @@
CREATE TABLE math (
math_inputhash BYTEA NOT NULL UNIQUE,
math_outputhash BYTEA NOT NULL,
math_html_conservativeness SMALLINT NOT NULL,
math_html TEXT,
math_mathml TEXT
);

View File

@ -1,21 +0,0 @@
--
-- Used by the math module to keep track
-- of previously-rendered items.
--
CREATE TABLE /*_*/math (
-- Binary MD5 hash of the latex fragment, used as an identifier key.
math_inputhash varbinary(16) NOT NULL PRIMARY KEY,
-- Not sure what this is, exactly...
math_outputhash varbinary(16) NOT NULL,
-- texvc reports how well it thinks the HTML conversion worked;
-- if it's a low level the PNG rendering may be preferred.
math_html_conservativeness tinyint NOT NULL,
-- HTML output from texvc, if any
math_html text,
-- MathML output from texvc, or from LaTeXML
math_mathml text
) /*$wgDBTableOptions*/;

View File

@ -18,13 +18,11 @@
"MathHooks": "src/MathHooks.php",
"MathRenderer": "src/MathRenderer.php",
"MathRestbaseInterface": "src/MathRestbaseInterface.php",
"MathTexvc": "MathTexvc.php",
"MathSource": "src/MathSource.php",
"MathMathML": "src/MathMathML.php",
"MathMathMLCli": "src/MathMathMLCli.php",
"MathLaTeXML": "MathLaTeXML.php",
"MathInputCheck": "src/MathInputCheck.php",
"MathInputCheckTexvc": "MathInputCheckTexvc.php",
"MathInputCheckRestbase": "src/MathInputCheckRestbase.php",
"SpecialMathShowImage": "src/SpecialMathShowImage.php",
"SpecialMathStatus": "src/SpecialMathStatus.php",

10
math/.gitignore vendored
View File

@ -1,10 +0,0 @@
# Compiled source
*.cmi
*.cmx
*.o
parser.mli
# The binaries
texvc
texvc_test
texvc_tex

View File

@ -1 +0,0 @@
Deny from all

View File

@ -1,87 +0,0 @@
.PHONY: clean all
OBJ=render_info.cmo tex.cmo texutil.cmo parser.cmo lexer.cmo texvc.cmo \
render_info.cmx tex.cmx texutil.cmx parser.cmx lexer.cmx texvc.cmx \
lexer.cmi parser.cmi render_info.cmi tex.cmi texutil.cmi texvc.cmi \
lexer.o parser.o render_info.o tex.o texutil.o texvc.o \
lexer.ml parser.ml parser.mli texvc texvc.bc texvc_test.cmo \
texvc_test.cmx texvc_test.cmi texvc_test.o texvc_test util.o \
util.cmo util.cmx util.cmi texvc_cgi.cmi texvc_cgi texvc_cgi.cmo \
render.o render.cmi render.cmo render.cmx texvc_tex.cmx \
texvc_tex.o texvc_tex.cmi texvc_tex html.cmi html.cmo html.cmx \
html.o mathml.cmi mathml.cmo mathml.cmx mathml.o
CGIPATH=-I /usr/lib/ocaml/cgi -I /usr/lib/ocaml/netstring -I /usr/lib/ocaml/pcre
COMMON_NATIVE_OBJ =util.cmx parser.cmx html.cmx mathml.cmx texutil.cmx lexer.cmx
COMMON_BYTECODE_OBJ=util.cmo parser.cmo html.cmo mathml.cmo texutil.cmo lexer.cmo
all: texvc texvc_test texvc_tex
cgi: texvc_cgi.cmo texvc_cgi
clean:
rm -f $(OBJ)
# Native versions
texvc: $(COMMON_NATIVE_OBJ) render.cmx texvc.cmx
ocamlopt -o $@ unix.cmxa $^
texvc_test: $(COMMON_NATIVE_OBJ) lexer.cmx texvc_test.cmx
ocamlopt -o $@ $^
texvc_tex: $(COMMON_NATIVE_OBJ) texvc_tex.cmx
ocamlopt -o $@ $^
# Bytecode version
texvc.bc: $(COMMON_BYTECODE_OBJ) render.cmo texvc.cmo
ocamlc -o $@ unix.cma $^
# CGI related targets:
texvc_cgi.cmo: texvc_cgi.ml
ocamlc -c $(CGIPATH) $<
texvc_cgi: util.cmo parser.cmo texutil.cmo render.cmo lexer.cmo texvc_cgi.cmo
ocamlc -o $@ unix.cma $(CGIPATH) pcre.cma netstring.cma cgi.cma $^
chmod g-w $@
#
# Pattern rules
#
# .ml source .mli interface
# .cmi compiled interface
# .cmo object .cma library object
# .cmx object file .cmxa library object file
%.ml: %.mll
ocamllex $<
%.mli %.ml: %.mly
ocamlyacc $<
%.cmo: %.ml
ocamlc -c $<
%.cmx: %.ml
ocamlopt -c $<
%.cmi: %.mli
ocamlc -c $<
# Various dependencies
html.cmo: render_info.cmi tex.cmi util.cmo html.cmi
html.cmx: render_info.cmi tex.cmi util.cmx html.cmi
html.cmi: tex.cmi
lexer.cmo: parser.cmi render_info.cmi tex.cmi texutil.cmi
lexer.cmx: parser.cmx render_info.cmi tex.cmi texutil.cmx
mathml.cmo: tex.cmi mathml.cmi
mathml.cmx: tex.cmi mathml.cmi
mathml.cmi: tex.cmi
parser.cmo: render_info.cmi tex.cmi parser.cmi
parser.cmx: render_info.cmi tex.cmi parser.cmi
parser.cmi: render_info.cmi tex.cmi
render.cmo: texutil.cmi util.cmo
render.cmx: texutil.cmx util.cmx
tex.cmi: render_info.cmi
texutil.cmo: html.cmi parser.cmi render_info.cmi tex.cmi util.cmo texutil.cmi
texutil.cmx: html.cmx parser.cmx render_info.cmi tex.cmi util.cmx texutil.cmi
texutil.cmi: parser.cmi tex.cmi
texvc.cmo: html.cmi lexer.cmo mathml.cmi parser.cmi render.cmo texutil.cmi util.cmo
texvc.cmx: html.cmx lexer.cmx mathml.cmx parser.cmx render.cmx texutil.cmx util.cmx
texvc_cgi.cmo: lexer.cmo parser.cmi render.cmo texutil.cmi util.cmo
texvc_cgi.cmx: lexer.cmx parser.cmx render.cmx texutil.cmx util.cmx
texvc_test.cmo: html.cmi lexer.cmo parser.cmi texutil.cmi util.cmo
texvc_test.cmx: html.cmx lexer.cmx parser.cmx texutil.cmx util.cmx
texvc_tex.cmo: lexer.cmo parser.cmi texutil.cmi util.cmo
texvc_tex.cmx: lexer.cmx parser.cmx texutil.cmx util.cmx

View File

@ -1,123 +0,0 @@
== About texvc ==
texvc takes LaTeX-compatible equations and produces formatted output in HTML,
MathML, and (via LaTeX/dvipng) rasterized PNG images.
Input data is parsed and scrutinized for safety, and the output includes an
estimate of whether the code is simple enough that HTML rendering will look
acceptable.
The program was written by Tomasz Wegrzanowski for use with MediaWiki; it's
included as part of the MediaWiki package (http://www.mediawiki.org) and is
under the GPL license.
Please report bugs at: https://bugzilla.wikimedia.org/
with "MediaWiki extensions" as product and "Math" as component.
== Setup ==
=== Requirements ===
OCaml 3.06 or later is required to compile texvc; this can be acquired from
http://caml.inria.fr/ if your system doesn't have it available.
The makefile requires GNU make.
Rasterization is done via LaTeX, dvipng. These need to be installed and in
the PATH: latex, dvipng
AMS* packages for LaTeX also need to be installed. Without AMS* some equations
will render correctly while others won't render. Most distributions of TeX
already contain AMS*. In Debian/Ubuntu you need to install tetex-extra.
To work properly with rendering non-ASCII Unicode characters, a supplemental TeX
package is needed (cjk-latex in Debian)
In Ubuntu Precise, all dependencies can be installed using:
$ sudo apt-get install build-essential dvipng ocaml \
texlive-fonts-recommended texlive-lang-greek texlive-latex-recommended
=== Installation ===
Run 'make' (or 'gmake' if GNU make is not your default make). This should
produce the texvc executable.
By default, MediaWiki will search in this directory for texvc, if you moved it elsewhere,
you'll have to modify $wgTexvc and set it to the path of the texvc executable.
== Usage ==
Normally texvc is called from MediaWiki's Math.php modules and everything
Just Works. It can be run manually for testing or for use in another app.
=== Command-line parameters ===
texvc <temp directory> <output directory> <TeX code> <encoding> <color>
Be sure to properly quote the TeX code!
Example:
texvc /home/wiki/tmp /home/wiki/math "y=x+2" iso-8859-1 "rgb 1.0 1.0 1.0"
=== Output format ===
Status codes and HTML/MathML transformations are returned on stdout.
A rasterized PNG file will be written to the output directory, named
for the MD5 hash code.
texvc output format is like this:
+%5 ok, but not html or mathml
c%5%h ok, conservative html, no mathml
m%5%h ok, moderate html, no mathml
l%5%h ok, liberal html, no mathml
C%5%h\0%m ok, conservative html, with mathml
M%5%h\0%m ok, moderate html, with mathml
L%5%h\0%m ok, liberal html, with mathml
X%5%m ok, no html, with mathml
S syntax error
E lexing error
F%s unknown function %s
- other error
\0 - null character
%5 - md5, 32 hex characters
%h - html code, without \0 characters
%m - mathml code, without \0 characters
== Troubleshooting ==
Unfortunately, many error conditions with rasterization are not well reported.
texvc will return as though everything is successful, and the only obvious
sign of problems for the user is a big X on a wiki page where an equation
should be.
Try running texvc from the command line to ensure that the software it relies
upon is all set up.
Ensure that the temporary and math directories exist and can be written to by
the user account the web server runs under; if you don't control the server,
you may have to make them world-writable.
If some equations render correctly while others don't, you probably don't have
AMS* packages for LaTeX installed. Most distributions of TeX come with AMS*.
In Debian/Ubuntu AMS* is in tetex-extra package.
To check if that is the problem you can try those two equations:
x + y
x \implies y
The first uses only standard LaTeX, while the second uses symbol \implies from AMS*.
If the first renders, but the second doesn't, you need to install AMS*.
== Hacking ==
Before you start hacking on the math package its good to know the workflow,
which is basically:
1. texvc gets called by Math/Math.body.php (check out the line beginning with "$cmd")
2. texvc does its magic, which is basically to check for invalid latex code.
3. texvc takes the user input if valid and creates a latex file containing it, see
get_preface in texutil.ml
4. dvipng(1) gets called to create a .png file
See render.ml for this process (commenting out the removal of
the temporary file is useful for debugging).

View File

@ -1,3 +0,0 @@
* It would be better if PNGs were transparent
* CJK support
* Documentation, in particular about instalation of Latex support for Unicode

View File

@ -1,144 +0,0 @@
open Render_info
open Tex
open Util
exception Too_difficult_for_html
type context = CTX_NORMAL | CTX_IT | CTX_RM
type conservativeness_t = CONSERVATIVE | MODERATE | LIBERAL
let conservativeness = ref CONSERVATIVE
let html_liberal () = conservativeness := LIBERAL
let html_moderate () = if !conservativeness = CONSERVATIVE then conservativeness := MODERATE else ()
let new_ctx = function
FONTFORCE_IT -> CTX_IT
| FONTFORCE_RM -> CTX_RM
let font_render lit = function
(_, FONT_UFH) -> lit
| (_, FONT_UF) -> lit
| (CTX_IT,FONT_RTI) -> raise Too_difficult_for_html
| (_, FONT_RTI) -> lit
| (CTX_IT,FONT_RM) -> "<i>"^lit^"</i>"
| (_, FONT_RM) -> lit
| (CTX_RM,FONT_IT) -> lit
| (_, FONT_IT) -> "<i>"^lit^"</i>"
let rec html_render_flat ctx = function
TEX_LITERAL (HTMLABLE (ft,_,sh))::r -> (html_liberal (); (font_render sh (ctx,ft))^html_render_flat ctx r)
| TEX_LITERAL (HTMLABLEC(ft,_,sh))::r -> (font_render sh (ctx,ft))^html_render_flat ctx r
| TEX_LITERAL (MHTMLABLEC(ft,_,sh,_,_))::r -> (font_render sh (ctx,ft))^html_render_flat ctx r
| TEX_LITERAL (HTMLABLEM(ft,_,sh))::r -> (html_moderate(); (font_render sh (ctx,ft))^html_render_flat ctx r)
| TEX_LITERAL (HTMLABLE_BIG (_,sh))::r -> (html_liberal (); sh^html_render_flat ctx r)
| TEX_FUN1hl (_,(f1,f2),a)::r -> f1^(html_render_flat ctx [a])^f2^html_render_flat ctx r
| TEX_FUN1hf (_,ff,a)::r -> (html_render_flat (new_ctx ff) [a])^html_render_flat ctx r
| TEX_DECLh (_,ff,a)::r -> (html_render_flat (new_ctx ff) a)^html_render_flat ctx r
| TEX_CURLY ls::r -> html_render_flat ctx (ls @ r)
| TEX_DQ (a,b)::r -> (html_liberal ();
let bs = html_render_flat ctx [b] in match html_render_size ctx a with
true, s -> raise Too_difficult_for_html
| false, s -> s^"<sub>"^bs^"</sub>")^html_render_flat ctx r
| TEX_UQ (a,b)::r -> (html_liberal ();
let bs = html_render_flat ctx [b] in match html_render_size ctx a with
true, s -> raise Too_difficult_for_html
| false, s -> s^"<sup>"^bs^"</sup>")^html_render_flat ctx r
| TEX_FQ (a,b,c)::r -> (html_liberal ();
(let bs = html_render_flat ctx [b] in let cs = html_render_flat ctx [c] in
match html_render_size ctx a with
true, s -> raise Too_difficult_for_html
| false, s -> s^"<sub>"^bs^"</sub><sup>"^cs^"</sup>")^html_render_flat ctx r)
| TEX_DQN (a)::r -> (html_liberal ();
let bs = html_render_flat ctx [a] in "<sub>"^bs^"</sub>")^html_render_flat ctx r
| TEX_UQN (a)::r -> (html_liberal ();
let bs = html_render_flat ctx [a] in "<sup>"^bs^"</sup>")^html_render_flat ctx r
| TEX_FQN (a,b)::r -> (html_liberal ();
(let bs = html_render_flat ctx [a] in let cs = html_render_flat ctx [b] in "<sub>"^bs^"</sub><sup>"^cs^"</sup>")^html_render_flat ctx r)
| TEX_BOX (_,s)::r -> s^html_render_flat ctx r
| TEX_LITERAL (TEX_ONLY _)::_ -> raise Too_difficult_for_html
| TEX_FUN1 _::_ -> raise Too_difficult_for_html
| TEX_FUN1nb _::_ -> raise Too_difficult_for_html
| TEX_FUN2 _::_ -> raise Too_difficult_for_html
| TEX_FUN2nb _::_ -> raise Too_difficult_for_html
| TEX_FUN2h _::_ -> raise Too_difficult_for_html
| TEX_FUN2sq _::_ -> raise Too_difficult_for_html
| TEX_INFIX _::_ -> raise Too_difficult_for_html
| TEX_INFIXh _::_ -> raise Too_difficult_for_html
| TEX_MATRIX _::_ -> raise Too_difficult_for_html
| TEX_LR _::_ -> raise Too_difficult_for_html
| TEX_BIG _::_ -> raise Too_difficult_for_html
| [] -> ""
and html_render_size ctx = function
TEX_LITERAL (HTMLABLE_BIG (_,sh)) -> true,sh
| x -> false,html_render_flat ctx [x]
let rec html_render_deep ctx = function
TEX_LITERAL (HTMLABLE (ft,_,sh))::r -> (html_liberal (); ("",(font_render sh (ctx,ft)),"")::html_render_deep ctx r)
| TEX_LITERAL (HTMLABLEM(ft,_,sh))::r -> (html_moderate(); ("",(font_render sh (ctx,ft)),"")::html_render_deep ctx r)
| TEX_LITERAL (HTMLABLEC(ft,_,sh))::r -> ("",(font_render sh (ctx,ft)),"")::html_render_deep ctx r
| TEX_LITERAL (MHTMLABLEC(ft,_,sh,_,_))::r -> ("",(font_render sh (ctx,ft)),"")::html_render_deep ctx r
| TEX_LITERAL (HTMLABLE_BIG (_,sh))::r -> (html_liberal (); ("",sh,"")::html_render_deep ctx r)
| TEX_FUN2h (_,f,a,b)::r -> (html_liberal (); (f a b)::html_render_deep ctx r)
| TEX_INFIXh (_,f,a,b)::r -> (html_liberal (); (f a b)::html_render_deep ctx r)
| TEX_CURLY ls::r -> html_render_deep ctx (ls @ r)
| TEX_DQ (a,b)::r -> (let bs = html_render_flat ctx [b] in match html_render_size ctx a with
true, s -> "","<span style='font-size: x-large; font-family: serif;'>"^s^"</span>",bs
| false, s -> "",(s^"<sub>"^bs^"</sub>"),"")::html_render_deep ctx r
| TEX_UQ (a,b)::r -> (let bs = html_render_flat ctx [b] in match html_render_size ctx a with
true, s -> bs,"<span style='font-size: x-large; font-family: serif;'>"^s^"</span>",""
| false, s -> "",(s^"<sup>"^bs^"</sup>"),"")::html_render_deep ctx r
| TEX_FQ (a,b,c)::r -> (html_liberal ();
(let bs = html_render_flat ctx [b] in let cs = html_render_flat ctx [c] in
match html_render_size ctx a with
true, s -> (cs,"<span style='font-size: x-large; font-family: serif;'>"^s^"</span>",bs)
| false, s -> ("",(s^"<sub>"^bs^"</sub><sup>"^cs^"</sup>"),""))::html_render_deep ctx r)
| TEX_DQN (a)::r -> (let bs = html_render_flat ctx [a] in "",("<sub>"^bs^"</sub>"),"")::html_render_deep ctx r
| TEX_UQN (a)::r -> (let bs = html_render_flat ctx [a] in "",("<sup>"^bs^"</sup>"),"")::html_render_deep ctx r
| TEX_FQN (a,b)::r -> (html_liberal ();
(let bs = html_render_flat ctx [a] in let cs = html_render_flat ctx [b] in
("",("<sub>"^bs^"</sub><sup>"^cs^"</sup>"),""))::html_render_deep ctx r)
| TEX_FUN1hl (_,(f1,f2),a)::r -> ("",f1,"")::(html_render_deep ctx [a]) @ ("",f2,"")::html_render_deep ctx r
| TEX_FUN1hf (_,ff,a)::r -> (html_render_deep (new_ctx ff) [a]) @ html_render_deep ctx r
| TEX_DECLh (_,ff,a)::r -> (html_render_deep (new_ctx ff) a) @ html_render_deep ctx r
| TEX_BOX (_,s)::r -> ("",s,"")::html_render_deep ctx r
| TEX_LITERAL (TEX_ONLY _)::_ -> raise Too_difficult_for_html
| TEX_FUN1 _::_ -> raise Too_difficult_for_html
| TEX_FUN1nb _::_ -> raise Too_difficult_for_html
| TEX_FUN2 _::_ -> raise Too_difficult_for_html
| TEX_FUN2nb _::_ -> raise Too_difficult_for_html
| TEX_FUN2sq _::_ -> raise Too_difficult_for_html
| TEX_INFIX _::_ -> raise Too_difficult_for_html
| TEX_MATRIX _::_ -> raise Too_difficult_for_html
| TEX_LR _::_ -> raise Too_difficult_for_html
| TEX_BIG _::_ -> raise Too_difficult_for_html
| [] -> []
let rec html_render_table = function
sf,u,d,("",a,"")::("",b,"")::r -> html_render_table (sf,u,d,(("",a^b,"")::r))
| sf,u,d,(("",a,"") as c)::r -> html_render_table (c::sf,u,d,r)
| sf,u,d,((_,a,"") as c)::r -> html_render_table (c::sf,true,d,r)
| sf,u,d,(("",a,_) as c)::r -> html_render_table (c::sf,u,true,r)
| sf,u,d,((_,a,_) as c)::r -> html_render_table (c::sf,true,true,r)
| sf,false,false,[] -> mapjoin (function (u,m,d) -> m) (List.rev sf)
| sf,true,false,[] -> let ustr,mstr = List.fold_left (fun (us,ms) (u,m,d) -> (us^"<td>"^u^"</td>",ms^"<td>"^u^"</td>"))
("","") (List.rev sf) in
"\n<table>\n" ^
"\t\t<tr style='text-align: center; vertical-align: bottom;'>" ^ ustr ^ "</tr>\n" ^
"\t\t<tr style='text-align: center;'>" ^ mstr ^ "</tr>\n" ^
"</table>\n"
| sf,false,true,[] -> let mstr,dstr = List.fold_left (fun (ms,ds) (u,m,d) -> (ms^"<td>"^m^"</td>",ds^"<td>"^d^"</td>"))
("","") (List.rev sf) in
"\n<table>\n" ^
"\t\t<tr style='text-align: center;'>" ^ mstr ^ "</tr>\n" ^
"\t\t<tr style='text-align: center; vertical-align: top;'>" ^ dstr ^ "</tr>\n" ^
"</table>\n"
| sf,true,true,[] -> let ustr,mstr,dstr = List.fold_left (fun (us,ms,ds) (u,m,d) ->
(us^"<td>"^u^"</td>",ms^"<td>"^m^"</td>",ds^"<td>"^d^"</td>")) ("","","") (List.rev sf) in
"\n<table>\n" ^
"\t\t<tr style='text-align: center; vertical-align: bottom;'>" ^ ustr ^ "</tr>\n" ^
"\t\t<tr style='text-align: center;'>" ^ mstr ^ "</tr>\n" ^
"\t\t<tr style='text-align: center; vertical-align: top;'>" ^ dstr ^ "</tr>\n" ^
"</table>\n"
let html_render tree = html_render_table ([],false,false,html_render_deep CTX_NORMAL tree)
let render tree = try Some (html_render tree) with _ -> None

View File

@ -1,5 +0,0 @@
val render : Tex.t list -> string option
val html_render : Tex.t list -> string
type conservativeness_t = CONSERVATIVE | MODERATE | LIBERAL
val conservativeness : conservativeness_t ref

View File

@ -1,124 +0,0 @@
{
open Parser
open Render_info
open Tex
}
let space = [' ' '\t' '\n' '\r']
let alpha = ['a'-'z' 'A'-'Z']
let literal_id = ['a'-'z' 'A'-'Z']
let literal_mn = ['0'-'9']
let literal_uf_lt = [',' ':' ';' '?' '!' '\'']
let delimiter_uf_lt = ['(' ')' '.']
let literal_uf_op = ['+' '-' '*' '=']
let delimiter_uf_op = ['/' '|']
let boxchars = ['0'-'9' 'a'-'z' 'A'-'Z' '+' '-' '*' ',' '=' '(' ')' ':' '/' ';' '?' '.' '!' '\'' '`' ' ' '\128'-'\255']
let aboxchars = ['0'-'9' 'a'-'z' 'A'-'Z' '+' '-' '*' ',' '=' '(' ')' ':' '/' ';' '?' '.' '!' '\'' '`' ' ']
let latex_function_names = "arccos" | "arcsin" | "arctan" | "arg" | "cos" | "cosh" | "cot" | "coth" | "csc"| "deg" | "det" | "dim" | "exp" | "gcd" | "hom" | "inf" | "ker" | "lg" | "lim" | "liminf" | "limsup" | "ln" | "log" | "max" | "min" | "Pr" | "sec" | "sin" | "sinh" | "sup" | "tan" | "tanh"
let mediawiki_function_names = "arccot" | "arcsec" | "arccsc" | "sgn" | "sen"
rule token = parse
space + { token lexbuf }
| "\\text" space * '{' aboxchars + '}'
{ Texutil.tex_use_ams (); let str = Lexing.lexeme lexbuf in
let n = String.index str '{' + 1 in
BOX ("\\text", String.sub str n (String.length str - n - 1)) }
| "\\mbox" space * '{' aboxchars + '}'
{ let str = Lexing.lexeme lexbuf in
let n = String.index str '{' + 1 in
BOX ("\\mbox", String.sub str n (String.length str - n - 1)) }
| "\\hbox" space * '{' aboxchars + '}'
{ let str = Lexing.lexeme lexbuf in
let n = String.index str '{' + 1 in
BOX ("\\hbox", String.sub str n (String.length str - n - 1)) }
| "\\vbox" space * '{' aboxchars + '}'
{ let str = Lexing.lexeme lexbuf in
let n = String.index str '{' + 1 in
BOX ("\\vbox", String.sub str n (String.length str - n - 1)) }
| "\\text" space * '{' boxchars + '}'
{ Texutil.tex_use_ams (); let str = Lexing.lexeme lexbuf in
let n = String.index str '{' + 1 in
Texutil.tex_use_nonascii();
BOX ("\\text", String.sub str n (String.length str - n - 1)) }
| "\\mbox" space * '{' boxchars + '}'
{ let str = Lexing.lexeme lexbuf in
let n = String.index str '{' + 1 in
Texutil.tex_use_nonascii();
BOX ("\\mbox", String.sub str n (String.length str - n - 1)) }
| "\\hbox" space * '{' boxchars + '}'
{ let str = Lexing.lexeme lexbuf in
let n = String.index str '{' + 1 in
Texutil.tex_use_nonascii();
BOX ("\\hbox", String.sub str n (String.length str - n - 1)) }
| "\\vbox" space * '{' boxchars + '}'
{ let str = Lexing.lexeme lexbuf in
let n = String.index str '{' + 1 in
Texutil.tex_use_nonascii();
BOX ("\\vbox", String.sub str n (String.length str - n - 1)) }
| literal_id { let str = Lexing.lexeme lexbuf in LITERAL (MHTMLABLEC (FONT_IT, str,str,MI,str)) }
| literal_mn { let str = Lexing.lexeme lexbuf in LITERAL (MHTMLABLEC (FONT_RM, str,str,MN,str)) }
| literal_uf_lt { let str = Lexing.lexeme lexbuf in LITERAL (HTMLABLEC (FONT_UFH, str,str)) }
| delimiter_uf_lt { let str = Lexing.lexeme lexbuf in DELIMITER (HTMLABLEC (FONT_UFH, str,str)) }
| "-" { let str = Lexing.lexeme lexbuf in LITERAL (MHTMLABLEC (FONT_UFH,"-"," &minus; ",MO,str))}
| literal_uf_op { let str = Lexing.lexeme lexbuf in LITERAL (MHTMLABLEC (FONT_UFH, str," "^str^" ",MO,str)) }
| delimiter_uf_op { let str = Lexing.lexeme lexbuf in DELIMITER (MHTMLABLEC (FONT_UFH, str," "^str^" ",MO,str)) }
| "\\operatorname" { Texutil.tex_use_ams(); FUN_AR1nb "\\operatorname" }
| "\\sqrt" space * "[" { FUN_AR1opt "\\sqrt" }
| "\\xleftarrow" space * "[" { Texutil.tex_use_ams(); FUN_AR1opt "\\xleftarrow" }
| "\\xrightarrow" space * "[" { Texutil.tex_use_ams(); FUN_AR1opt "\\xrightarrow" }
| "\\" (latex_function_names as name) space * "(" { LITERAL (HTMLABLEC(FONT_UFH,"\\" ^ name ^ "(", name ^ "(")) }
| "\\" (latex_function_names as name) space * "[" { LITERAL (HTMLABLEC(FONT_UFH,"\\" ^ name ^ "[", name ^ "[")) }
| "\\" (latex_function_names as name) space * "\\{" { LITERAL (HTMLABLEC(FONT_UFH,"\\" ^ name ^ "\\{", name ^ "{")) }
| "\\" (latex_function_names as name) space * { LITERAL (HTMLABLEC(FONT_UFH,"\\" ^ name ^ " ", name ^ "&nbsp;")) }
| "\\" (mediawiki_function_names as name) space * "(" { (Texutil.tex_use_ams(); LITERAL (HTMLABLEC(FONT_UFH,"\\operatorname{" ^ name ^ "}(", name^ "("))) }
| "\\" (mediawiki_function_names as name) space * "[" { (Texutil.tex_use_ams(); LITERAL (HTMLABLEC(FONT_UFH,"\\operatorname{" ^ name ^ "}[", name^ "["))) }
| "\\" (mediawiki_function_names as name) space * "\\{" { (Texutil.tex_use_ams(); LITERAL (HTMLABLEC(FONT_UFH,"\\operatorname{" ^ name ^ "}\\{", name^ "{"))) }
| "\\" (mediawiki_function_names as name) space * { (Texutil.tex_use_ams(); LITERAL (HTMLABLEC(FONT_UFH,"\\operatorname{" ^ name ^ "} ", name ^ "&nbsp;"))) }
| "\\" alpha + { Texutil.find (Lexing.lexeme lexbuf) }
| "\\," { LITERAL (HTMLABLE (FONT_UF, "\\,","&nbsp;")) }
| "\\ " { LITERAL (HTMLABLE (FONT_UF, "\\ ","&nbsp;")) }
| "\\;" { LITERAL (HTMLABLE (FONT_UF, "\\;","&nbsp;")) }
| "\\!" { LITERAL (TEX_ONLY "\\!") }
| "\\{" { DELIMITER (HTMLABLEC(FONT_UFH,"\\{","{")) }
| "\\}" { DELIMITER (HTMLABLEC(FONT_UFH,"\\}","}")) }
| "\\|" { DELIMITER (HTMLABLE (FONT_UFH,"\\|","||")) }
| "\\_" { LITERAL (HTMLABLEC(FONT_UFH,"\\_","_")) }
| "\\#" { LITERAL (HTMLABLE (FONT_UFH,"\\#","#")) }
| "\\%" { LITERAL (HTMLABLE (FONT_UFH,"\\%","%")) }
| "\\$" { LITERAL (HTMLABLE (FONT_UFH,"\\$","$")) }
| "\\&" { LITERAL (HTMLABLEC (FONT_RM,"\\&","&amp;")) }
| "&" { NEXT_CELL }
| "\\\\" { NEXT_ROW }
| "\\begin{matrix}" { Texutil.tex_use_ams(); BEGIN__MATRIX }
| "\\end{matrix}" { END__MATRIX }
| "\\begin{pmatrix}" { Texutil.tex_use_ams(); BEGIN_PMATRIX }
| "\\end{pmatrix}" { END_PMATRIX }
| "\\begin{bmatrix}" { Texutil.tex_use_ams(); BEGIN_BMATRIX }
| "\\end{bmatrix}" { END_BMATRIX }
| "\\begin{Bmatrix}" { Texutil.tex_use_ams(); BEGIN_BBMATRIX }
| "\\end{Bmatrix}" { END_BBMATRIX }
| "\\begin{vmatrix}" { Texutil.tex_use_ams(); BEGIN_VMATRIX }
| "\\end{vmatrix}" { END_VMATRIX }
| "\\begin{Vmatrix}" { Texutil.tex_use_ams(); BEGIN_VVMATRIX }
| "\\end{Vmatrix}" { END_VVMATRIX }
| "\\begin{array}" { Texutil.tex_use_ams(); BEGIN_ARRAY }
| "\\end{array}" { END_ARRAY }
| "\\begin{align}" { Texutil.tex_use_ams(); BEGIN_ALIGN }
| "\\end{align}" { END_ALIGN }
| "\\begin{alignat}" { Texutil.tex_use_ams(); BEGIN_ALIGNAT }
| "\\end{alignat}" { END_ALIGNAT }
| "\\begin{smallmatrix}" { Texutil.tex_use_ams(); BEGIN_SMALLMATRIX }
| "\\end{smallmatrix}" { END_SMALLMATRIX }
| "\\begin{cases}" { Texutil.tex_use_ams(); BEGIN_CASES }
| "\\end{cases}" { END_CASES }
| '>' { LITERAL (HTMLABLEC(FONT_UFH,">"," &gt; ")) }
| '<' { LITERAL (HTMLABLEC(FONT_UFH,"<"," &lt; ")) }
| '%' { LITERAL (HTMLABLEC(FONT_UFH,"\\%","%")) }
| '$' { LITERAL (HTMLABLEC(FONT_UFH,"\\$","$")) }
| '~' { LITERAL (HTMLABLE (FONT_UF, "~","&nbsp;")) }
| '[' { DELIMITER (HTMLABLEC(FONT_UFH,"[","[")) }
| ']' { SQ_CLOSE }
| '{' { CURLY_OPEN }
| '}' { CURLY_CLOSE }
| '^' { SUP }
| '_' { SUB }
| eof { EOF }

View File

@ -1,20 +0,0 @@
open Tex
open Render_info
type t = TREE_MN of string | TREE_MO of string | TREE_MI of string
let rec make_mathml_tree = function
TREE_MN a::otr,TEX_LITERAL(MHTMLABLEC(_,_,_,MN,b))::itr -> make_mathml_tree(TREE_MN (a^b)::otr,itr)
| otr,TEX_LITERAL(MHTMLABLEC(_,_,_,MN,a))::itr -> make_mathml_tree(TREE_MN a::otr,itr)
| otr,TEX_LITERAL(MHTMLABLEC(_,_,_,MO,a))::itr -> make_mathml_tree(TREE_MO a::otr,itr)
| otr,TEX_LITERAL(MHTMLABLEC(_,_,_,MI,a))::itr -> make_mathml_tree(TREE_MI a::otr,itr)
| otr,TEX_CURLY(crl)::itr -> make_mathml_tree(otr,crl@itr)
| otr,[] -> List.rev otr
| _ -> failwith "failed to render mathml"
let render_mathml_tree = function
TREE_MN s -> "<mn>"^s^"</mn>"
| TREE_MI s -> "<mi>"^s^"</mi>"
| TREE_MO s -> "<mo>"^s^"</mo>"
let render tree = try Some (Util.mapjoin render_mathml_tree (make_mathml_tree ([],tree))) with _ -> None

View File

@ -1 +0,0 @@
val render : Tex.t list -> string option

View File

@ -1,119 +0,0 @@
%{
open Tex
open Render_info
let sq_close_ri = HTMLABLEC(FONT_UFH,"]", "]")
%}
%token <Render_info.t> LITERAL DELIMITER
%token <string> FUN_AR2 FUN_INFIX FUN_AR1 DECL FUN_AR1nb FUN_AR1opt BIG FUN_AR2nb
%token <string*string> BOX
%token <string*(string*string)> FUN_AR1hl
%token <string*Render_info.font_force> FUN_AR1hf DECLh
%token <string*(Tex.t->Tex.t->string*string*string)> FUN_AR2h
%token <string*(Tex.t list->Tex.t list->string*string*string)> FUN_INFIXh
%token EOF CURLY_OPEN CURLY_CLOSE SUB SUP SQ_CLOSE NEXT_CELL NEXT_ROW
%token BEGIN__MATRIX BEGIN_PMATRIX BEGIN_BMATRIX BEGIN_BBMATRIX BEGIN_VMATRIX BEGIN_VVMATRIX BEGIN_CASES BEGIN_ARRAY BEGIN_ALIGN BEGIN_ALIGNAT BEGIN_SMALLMATRIX
%token END__MATRIX END_PMATRIX END_BMATRIX END_BBMATRIX END_VMATRIX END_VVMATRIX END_CASES END_ARRAY END_ALIGN END_ALIGNAT END_SMALLMATRIX
%token LEFT RIGHT
%type <Tex.t list> tex_expr
%start tex_expr
%%
tex_expr:
expr EOF { $1 }
| ne_expr FUN_INFIX ne_expr EOF
{ [TEX_INFIX($2,$1,$3)] }
| ne_expr FUN_INFIXh ne_expr EOF
{ let t,h=$2 in [TEX_INFIXh(t,h,$1,$3)] }
expr:
/* */ { [] }
| ne_expr { $1 }
ne_expr:
lit_aq expr { $1 :: $2 }
| litsq_aq expr { $1 :: $2 }
| DECLh expr { let t,h = $1 in [TEX_DECLh(t,h,$2)] }
litsq_aq:
litsq_zq { $1 }
| litsq_dq { let base,downi = $1 in TEX_DQ(base,downi) }
| litsq_uq { let base,upi = $1 in TEX_UQ(base,upi)}
| litsq_fq { $1 }
litsq_fq:
litsq_dq SUP lit { let base,downi = $1 in TEX_FQ(base,downi,$3) }
| litsq_uq SUB lit { let base,upi = $1 in TEX_FQ(base,$3,upi) }
litsq_uq:
litsq_zq SUP lit { $1,$3 }
litsq_dq:
litsq_zq SUB lit { $1,$3 }
litsq_zq:
SQ_CLOSE { TEX_LITERAL sq_close_ri }
expr_nosqc:
/* */ { [] }
| lit_aq expr_nosqc { $1 :: $2 }
lit_aq:
lit { $1 }
| lit_dq { let base,downi = $1 in TEX_DQ(base,downi) }
| lit_uq { let base,upi = $1 in TEX_UQ(base,upi)}
| lit_dqn { TEX_DQN($1) }
| lit_uqn { TEX_UQN($1) }
| lit_fq { $1 }
lit_fq:
lit_dq SUP lit { let base,downi = $1 in TEX_FQ(base,downi,$3) }
| lit_uq SUB lit { let base,upi = $1 in TEX_FQ(base,$3,upi) }
| lit_dqn SUP lit { TEX_FQN($1, $3) }
lit_uq:
lit SUP lit { $1,$3 }
lit_dq:
lit SUB lit { $1,$3 }
lit_uqn:
SUP lit { $2 }
lit_dqn:
SUB lit { $2 }
left:
LEFT DELIMITER { $2 }
| LEFT SQ_CLOSE { sq_close_ri }
right:
RIGHT DELIMITER { $2 }
| RIGHT SQ_CLOSE { sq_close_ri }
lit:
LITERAL { TEX_LITERAL $1 }
| DELIMITER { TEX_LITERAL $1 }
| BIG DELIMITER { TEX_BIG ($1,$2) }
| BIG SQ_CLOSE { TEX_BIG ($1,sq_close_ri) }
| left expr right { TEX_LR ($1,$3,$2) }
| FUN_AR1 lit { TEX_FUN1($1,$2) }
| FUN_AR1nb lit { TEX_FUN1nb($1,$2) }
| FUN_AR1hl lit { let t,h=$1 in TEX_FUN1hl(t,h,$2) }
| FUN_AR1hf lit { let t,h=$1 in TEX_FUN1hf(t,h,$2) }
| FUN_AR1opt expr_nosqc SQ_CLOSE lit { TEX_FUN2sq($1,TEX_CURLY $2,$4) }
| FUN_AR2 lit lit { TEX_FUN2($1,$2,$3) }
| FUN_AR2nb lit lit { TEX_FUN2nb($1,$2,$3) }
| FUN_AR2h lit lit { let t,h=$1 in TEX_FUN2h(t,h,$2,$3) }
| BOX { let bt,s = $1 in TEX_BOX (bt,s) }
| CURLY_OPEN expr CURLY_CLOSE
{ TEX_CURLY $2 }
| CURLY_OPEN ne_expr FUN_INFIX ne_expr CURLY_CLOSE
{ TEX_INFIX($3,$2,$4) }
| CURLY_OPEN ne_expr FUN_INFIXh ne_expr CURLY_CLOSE
{ let t,h=$3 in TEX_INFIXh(t,h,$2,$4) }
| BEGIN__MATRIX matrix END__MATRIX { TEX_MATRIX ("matrix", $2) }
| BEGIN_PMATRIX matrix END_PMATRIX { TEX_MATRIX ("pmatrix", $2) }
| BEGIN_BMATRIX matrix END_BMATRIX { TEX_MATRIX ("bmatrix", $2) }
| BEGIN_BBMATRIX matrix END_BBMATRIX { TEX_MATRIX ("Bmatrix", $2) }
| BEGIN_VMATRIX matrix END_VMATRIX { TEX_MATRIX ("vmatrix", $2) }
| BEGIN_VVMATRIX matrix END_VVMATRIX { TEX_MATRIX ("Vmatrix", $2) }
| BEGIN_ARRAY matrix END_ARRAY { TEX_MATRIX ("array", $2) }
| BEGIN_ALIGN matrix END_ALIGN { TEX_MATRIX ("aligned", $2) }
| BEGIN_ALIGNAT matrix END_ALIGNAT { TEX_MATRIX ("alignedat", $2) }
| BEGIN_SMALLMATRIX matrix END_SMALLMATRIX { TEX_MATRIX ("smallmatrix", $2) }
| BEGIN_CASES matrix END_CASES { TEX_MATRIX ("cases", $2) }
matrix:
line { [$1] }
| line NEXT_ROW matrix { $1::$3 }
line:
expr { [$1] }
| expr NEXT_CELL line { $1::$3 }
;;

View File

@ -1,58 +0,0 @@
(* vim: set sw=8 ts=8 et: *)
let cmd_dvips tmpprefix = "dvips -q -R -E " ^ tmpprefix ^ ".dvi -f >" ^ tmpprefix ^ ".ps"
let cmd_latex tmpprefix = "latex " ^ tmpprefix ^ ".tex >/dev/null"
(* Putting -transparent white in converts arguments will sort-of give you transperancy *)
let cmd_convert tmpprefix finalpath = "convert -quality 100 -density 120 " ^ tmpprefix ^ ".ps " ^ finalpath ^ " >/dev/null 2>/dev/null"
(* Putting -bg Transparent in dvipng's arguments will give full-alpha transparency *)
(* Note that IE have problems with such PNGs and need an additional javascript snippet *)
(* Putting -bg transparent in dvipng's arguments will give binary transparency *)
let cmd_dvipng tmpprefix finalpath backcolor = "dvipng -bg \'" ^ backcolor ^ "\' -gamma 1.5 -D 120 -T tight --strict " ^ tmpprefix ^ ".dvi -o " ^ finalpath ^ " >/dev/null 2>/dev/null"
exception ExternalCommandFailure of string
let render tmppath finalpath outtex md5 backcolor =
let tmpprefix0 = (string_of_int (Unix.getpid ()))^"_"^md5 in
let tmpprefix = (tmppath^"/"^tmpprefix0) in
let unlink_all () =
begin
(* Commenting this block out will aid in debugging *)
Sys.remove (tmpprefix ^ ".dvi");
Sys.remove (tmpprefix ^ ".aux");
Sys.remove (tmpprefix ^ ".log");
Sys.remove (tmpprefix ^ ".tex");
if Sys.file_exists (tmpprefix ^ ".ps")
then Sys.remove (tmpprefix ^ ".ps");
end in
let f = (Util.open_out_unless_exists (tmpprefix ^ ".tex")) in
begin
(* Assemble final output in file 'f' *)
output_string f (Texutil.get_preface ());
output_string f outtex;
output_string f (Texutil.get_footer ());
close_out f;
(* TODO: document *)
if Util.run_in_other_directory tmppath (cmd_latex tmpprefix0) != 0
then (
unlink_all (); raise (ExternalCommandFailure "latex")
) else if (Sys.command (cmd_dvipng tmpprefix (finalpath^"/"^md5^".png") backcolor) != 0)
then (
if (Sys.command (cmd_dvips tmpprefix) != 0)
then (
unlink_all ();
raise (ExternalCommandFailure "dvips")
) else if (Sys.command (cmd_convert tmpprefix (finalpath^"/"^md5^".png")) != 0)
then (
unlink_all ();
raise (ExternalCommandFailure "convert")
) else (
unlink_all ()
)
) else (
unlink_all ()
)
end

View File

@ -1,20 +0,0 @@
type font_force =
FONTFORCE_IT
| FONTFORCE_RM
type font_class =
FONT_IT (* IT default, may be forced to be RM *)
| FONT_RM (* RM default, may be forced to be IT *)
| FONT_UF (* not affected by IT/RM setting *)
| FONT_RTI (* RM - any, IT - not available in HTML *)
| FONT_UFH (* in TeX UF, in HTML RM *)
type math_class =
MN
| MI
| MO
type t =
HTMLABLEC of font_class * string * string
| HTMLABLEM of font_class * string * string
| HTMLABLE of font_class * string * string
| MHTMLABLEC of font_class * string * string * math_class * string
| HTMLABLE_BIG of string * string
| TEX_ONLY of string

View File

@ -1,24 +0,0 @@
type t =
TEX_LITERAL of Render_info.t
| TEX_CURLY of t list
| TEX_FQ of t * t * t
| TEX_DQ of t * t
| TEX_UQ of t * t
| TEX_FQN of t * t
| TEX_DQN of t
| TEX_UQN of t
| TEX_LR of Render_info.t * Render_info.t * t list
| TEX_BOX of string * string
| TEX_BIG of string * Render_info.t
| TEX_FUN1 of string * t
| TEX_FUN1nb of string * t
| TEX_FUN2 of string * t * t
| TEX_FUN2nb of string * t * t
| TEX_INFIX of string * t list * t list
| TEX_FUN2sq of string * t * t
| TEX_FUN1hl of string * (string * string) * t
| TEX_FUN1hf of string * Render_info.font_force * t
| TEX_FUN2h of string * (t -> t -> string * string * string) * t * t
| TEX_INFIXh of string * (t list -> t list -> string * string * string) * t list * t list
| TEX_MATRIX of string * t list list list
| TEX_DECLh of string * Render_info.font_force * t list

View File

@ -1,751 +0,0 @@
(* vim: set sw=8 ts=8 et: *)
open Parser
open Render_info
open Tex
open Util
let tex_part = function
HTMLABLE (_,t,_) -> t
| HTMLABLEM (_,t,_) -> t
| HTMLABLEC (_,t,_) -> t
| MHTMLABLEC (_,t,_,_,_) -> t
| HTMLABLE_BIG (t,_) -> t
| TEX_ONLY t -> t
let rec render_tex = function
TEX_FQ (a,b,c) -> (render_tex a) ^ "_{" ^ (render_tex b) ^ "}^{" ^ (render_tex c) ^ "}"
| TEX_DQ (a,b) -> (render_tex a) ^ "_{" ^ (render_tex b) ^ "}"
| TEX_UQ (a,b) -> (render_tex a) ^ "^{" ^ (render_tex b) ^ "}"
| TEX_FQN (a,b) -> "_{" ^ (render_tex a) ^ "}^{" ^ (render_tex b) ^ "}"
| TEX_DQN (a) -> "_{" ^ (render_tex a) ^ "}"
| TEX_UQN (a) -> "^{" ^ (render_tex a) ^ "}"
| TEX_LITERAL s -> tex_part s
| TEX_FUN1 (f,a) -> "{" ^ f ^ " " ^ (render_tex a) ^ "}"
| TEX_FUN1nb (f,a) -> f ^ " " ^ (render_tex a)
| TEX_FUN1hl (f,_,a) -> "{" ^ f ^ " " ^ (render_tex a) ^ "}"
| TEX_FUN1hf (f,_,a) -> "{" ^ f ^ " " ^ (render_tex a) ^ "}"
| TEX_DECLh (f,_,a) -> "{" ^ f ^ "{" ^ (mapjoin render_tex a) ^ "}}"
| TEX_FUN2 (f,a,b) -> "{" ^ f ^ " " ^ (render_tex a) ^ (render_tex b) ^ "}"
| TEX_FUN2nb (f,a,b) -> f ^ (render_tex a) ^ (render_tex b)
| TEX_FUN2h (f,_,a,b) -> "{" ^ f ^ " " ^ (render_tex a) ^ (render_tex b) ^ "}"
| TEX_FUN2sq (f,a,b) -> "{" ^ f ^ "[ " ^ (render_tex a) ^ "]" ^ (render_tex b) ^ "}"
| TEX_CURLY (tl) -> "{" ^ (mapjoin render_tex tl) ^ "}"
| TEX_INFIX (s,ll,rl) -> "{" ^ (mapjoin render_tex ll) ^ " " ^ s ^ "" ^ (mapjoin render_tex rl) ^ "}"
| TEX_INFIXh (s,_,ll,rl) -> "{" ^ (mapjoin render_tex ll) ^ " " ^ s ^ "" ^ (mapjoin render_tex rl) ^ "}"
| TEX_BOX (bt,s) -> "{"^bt^"{" ^ s ^ "}}"
| TEX_BIG (bt,d) -> "{"^bt^(tex_part d)^"}"
| TEX_MATRIX (t,rows) -> "{\\begin{"^t^"}"^(mapjoine "\\\\" (mapjoine "&" (mapjoin render_tex)) rows)^"\\end{"^t^"}}"
| TEX_LR (l,r,tl) -> "\\left "^(tex_part l)^(mapjoin render_tex tl)^"\\right "^(tex_part r)
(* Dynamic loading*)
type encoding_t = LATIN1 | LATIN2 | UTF8
(* module properties *)
let modules_ams = ref false
let modules_nonascii = ref false
let modules_encoding = ref UTF8
let modules_color = ref false
let modules_teubner = ref false
let modules_euro = ref false
(* wrappers to easily set / reset module properties *)
let tex_use_ams () = modules_ams := true
let tex_use_nonascii () = modules_nonascii := true
let tex_use_color () = modules_color := true
let tex_use_teubner () = modules_teubner := true
let tex_use_euro () = modules_euro := true
let tex_mod_reset () = (
modules_ams := false;
modules_nonascii := false;
modules_encoding := UTF8;
modules_color := false;
modules_teubner := false;
modules_euro := false;
)
(* Return TeX fragment for one of the encodings in (UTF8,LATIN1,LATIN2) *)
let get_encoding = function
UTF8 -> "\\usepackage{ucs}\n\\usepackage[utf8]{inputenc}\n"
| LATIN1 -> "\\usepackage[latin1]{inputenc}\n"
| LATIN2 -> "\\usepackage[latin2]{inputenc}\n"
(* TeX fragment inserted before the output *)
let get_preface () = "\\nonstopmode\n\\documentclass[12pt]{article}\n" ^
(if !modules_nonascii then get_encoding !modules_encoding else "") ^
(if !modules_ams then "\\usepackage{amsmath}\n\\usepackage{amsfonts}\n\\usepackage{amssymb}\n" else "") ^
(if !modules_color then "\\usepackage[dvips,usenames]{color}\n" else "") ^
(if !modules_teubner then "\\usepackage[greek]{babel}\n\\usepackage{teubner}\n" else "") ^
(if !modules_euro then "\\usepackage{eurosym}\n" else "") ^
"\\usepackage{cancel}\n\\pagestyle{empty}\n\\begin{document}\n$$\n"
(* TeX fragment appended after the content *)
let get_footer () = "\n$$\n\\end{document}\n"
(* Default to UTF8 *)
let set_encoding = function
"ISO-8859-1" -> modules_encoding := LATIN1
| "iso-8859-1" -> modules_encoding := LATIN1
| "ISO-8859-2" -> modules_encoding := LATIN2
| _ -> modules_encoding := UTF8
(* Turn that into hash table lookup *)
exception Illegal_tex_function of string
let find = function
"\\alpha" -> LITERAL (HTMLABLEC (FONT_UF, "\\alpha ", "&alpha;"))
| "\\Alpha" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
"\\mathrm{A}", "&Alpha;")))
| "\\beta" -> LITERAL (HTMLABLEC (FONT_UF, "\\beta ", "&beta;"))
| "\\Beta" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
"\\mathrm{B}", "&Beta;")))
| "\\gamma" -> LITERAL (HTMLABLEC (FONT_UF, "\\gamma ", "&gamma;"))
| "\\Gamma" -> LITERAL (HTMLABLEC (FONT_UF, "\\Gamma ", "&Gamma;"))
| "\\delta" -> LITERAL (HTMLABLEC (FONT_UF, "\\delta ", "&delta;"))
| "\\Delta" -> LITERAL (HTMLABLEC (FONT_UF, "\\Delta ", "&Delta;"))
| "\\epsilon" -> LITERAL (TEX_ONLY "\\epsilon ")
| "\\Epsilon" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
"\\mathrm{E}", "&Epsilon;")))
| "\\varepsilon" -> LITERAL (HTMLABLEC (FONT_UF, "\\varepsilon ", "&epsilon;"))
| "\\zeta" -> LITERAL (HTMLABLEC (FONT_UF, "\\zeta ", "&zeta;"))
| "\\Zeta" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
"\\mathrm{Z}", "&Zeta;")))
| "\\eta" -> LITERAL (HTMLABLEC (FONT_UF, "\\eta ", "&eta;"))
| "\\Eta" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
"\\mathrm{H}", "&Eta;")))
| "\\theta" -> LITERAL (HTMLABLEC (FONT_UF, "\\theta ", "&theta;"))
| "\\Theta" -> LITERAL (HTMLABLEC (FONT_UF, "\\Theta ", "&Theta;"))
| "\\vartheta" -> LITERAL (HTMLABLE (FONT_UF, "\\vartheta ", "&thetasym;"))
| "\\thetasym" -> LITERAL (HTMLABLE (FONT_UF, "\\vartheta ", "&thetasym;"))
| "\\iota" -> LITERAL (HTMLABLEC (FONT_UF, "\\iota ", "&iota;"))
| "\\Iota" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
"\\mathrm{I}", "&Iota;")))
| "\\kappa" -> LITERAL (HTMLABLEC (FONT_UF, "\\kappa ", "&kappa;"))
| "\\Kappa" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
"\\mathrm{K}", "&Kappa;")))
| "\\lambda" -> LITERAL (HTMLABLEC (FONT_UF, "\\lambda ", "&lambda;"))
| "\\Lambda" -> LITERAL (HTMLABLEC (FONT_UF, "\\Lambda ", "&Lambda;"))
| "\\mu" -> LITERAL (HTMLABLEC (FONT_UF, "\\mu ", "&mu;"))
| "\\Mu" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
"\\mathrm{M}", "&Mu;")))
| "\\nu" -> LITERAL (HTMLABLEC (FONT_UF, "\\nu ", "&nu;"))
| "\\Nu" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
"\\mathrm{N}", "&Nu;")))
| "\\omicron" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
"\\mathrm{o}", "&omicron;")))
| "\\Omicron" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
"\\mathrm{O}", "&Omicron;")))
| "\\pi" -> LITERAL (HTMLABLEC (FONT_UF, "\\pi ", "&pi;"))
| "\\Pi" -> LITERAL (HTMLABLEC (FONT_UF, "\\Pi ", "&Pi;"))
| "\\varpi" -> LITERAL (TEX_ONLY "\\varpi ")
| "\\rho" -> LITERAL (HTMLABLEC (FONT_UF, "\\rho ", "&rho;"))
| "\\Rho" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
"\\mathrm{P}", "&Rho;")))
| "\\varrho" -> LITERAL (TEX_ONLY "\\varrho ")
| "\\sim" -> LITERAL (HTMLABLEC (FONT_UF, "\\sim ", "&sim;"))
| "\\sigma" -> LITERAL (HTMLABLEC (FONT_UF, "\\sigma ", "&sigma;"))
| "\\Sigma" -> LITERAL (HTMLABLEC (FONT_UF, "\\Sigma ", "&Sigma;"))
| "\\varsigma" -> LITERAL (TEX_ONLY "\\varsigma ")
| "\\tau" -> LITERAL (HTMLABLEC (FONT_UF, "\\tau ", "&tau;"))
| "\\Tau" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
"\\mathrm{T}", "&Tau;")))
| "\\upsilon" -> LITERAL (HTMLABLEC (FONT_UF, "\\upsilon ", "&upsilon;"))
| "\\Upsilon" -> LITERAL (HTMLABLEC (FONT_UF, "\\Upsilon ", "&Upsilon;"))
| "\\phi" -> LITERAL (HTMLABLEC (FONT_UF, "\\phi ", "&#981;"))
| "\\Phi" -> LITERAL (HTMLABLEC (FONT_UF, "\\Phi ", "&Phi;"))
| "\\varphi" -> LITERAL (HTMLABLEC (FONT_UF, "\\varphi ", "&phi;"))
| "\\chi" -> LITERAL (HTMLABLEC (FONT_UF, "\\chi ", "&chi;"))
| "\\Chi" -> (tex_use_ams (); LITERAL (HTMLABLEC (FONT_UF,
"\\mathrm{X}", "&Chi;")))
| "\\psi" -> LITERAL (HTMLABLEC (FONT_UF, "\\psi ", "&psi;"))
| "\\Psi" -> LITERAL (HTMLABLEC (FONT_UF, "\\Psi ", "&Psi;"))
| "\\omega" -> LITERAL (HTMLABLEC (FONT_UF, "\\omega ", "&omega;"))
| "\\Omega" -> LITERAL (HTMLABLEC (FONT_UF, "\\Omega ", "&Omega;"))
| "\\xi" -> LITERAL (HTMLABLEC (FONT_UF, "\\xi ", "&xi;"))
| "\\Xi" -> LITERAL (HTMLABLEC (FONT_UF, "\\Xi ", "&Xi;"))
| "\\aleph" -> LITERAL (HTMLABLE (FONT_UF, "\\aleph ", "&alefsym;"))
| "\\alef" -> LITERAL (HTMLABLE (FONT_UF, "\\aleph ", "&alefsym;"))
| "\\alefsym" -> LITERAL (HTMLABLE (FONT_UF, "\\aleph ", "&alefsym;"))
| "\\larr" -> LITERAL (HTMLABLEM (FONT_UF, "\\leftarrow ", "&larr;"))
| "\\leftarrow" -> LITERAL (HTMLABLEM (FONT_UF, "\\leftarrow ", "&larr;"))
| "\\rarr" -> LITERAL (HTMLABLEM (FONT_UF, "\\rightarrow ", "&rarr;"))
| "\\to" -> LITERAL (HTMLABLEM (FONT_UF, "\\to ", "&rarr;"))
| "\\gets" -> LITERAL (HTMLABLEM (FONT_UF, "\\gets ", "&larr;"))
| "\\rightarrow" -> LITERAL (HTMLABLEM (FONT_UF, "\\rightarrow ", "&rarr;"))
| "\\longleftarrow" -> LITERAL (HTMLABLE (FONT_UF, "\\longleftarrow ", "&larr;"))
| "\\longrightarrow" -> LITERAL (HTMLABLE (FONT_UF, "\\longrightarrow ", "&rarr;"))
| "\\Larr" -> LITERAL (HTMLABLE (FONT_UF, "\\Leftarrow ", "&lArr;"))
| "\\lArr" -> LITERAL (HTMLABLE (FONT_UF, "\\Leftarrow ", "&lArr;"))
| "\\Leftarrow" -> LITERAL (HTMLABLE (FONT_UF, "\\Leftarrow ", "&lArr;"))
| "\\Rarr" -> LITERAL (HTMLABLE (FONT_UF, "\\Rightarrow ", "&rArr;"))
| "\\rArr" -> LITERAL (HTMLABLE (FONT_UF, "\\Rightarrow ", "&rArr;"))
| "\\Rightarrow" -> LITERAL (HTMLABLEM (FONT_UF, "\\Rightarrow ", "&rArr;"))
| "\\mapsto" -> LITERAL (HTMLABLE (FONT_UF, "\\mapsto ", "&rarr;"))
| "\\longmapsto" -> LITERAL (HTMLABLE (FONT_UF, "\\longmapsto ", "&rarr;"))
| "\\Longleftarrow" -> LITERAL (HTMLABLE (FONT_UF, "\\Longleftarrow ", "&lArr;"))
| "\\Longrightarrow" -> LITERAL (HTMLABLE (FONT_UF, "\\Longrightarrow ", "&rArr;"))
| "\\uarr" -> DELIMITER (HTMLABLEM (FONT_UF, "\\uparrow ", "&uarr;"))
| "\\uparrow" -> DELIMITER (HTMLABLEM (FONT_UF, "\\uparrow ", "&uarr;"))
| "\\uArr" -> DELIMITER (HTMLABLE (FONT_UF, "\\Uparrow ", "&uArr;"))
| "\\Uarr" -> DELIMITER (HTMLABLE (FONT_UF, "\\Uparrow ", "&uArr;"))
| "\\Uparrow" -> DELIMITER (HTMLABLE (FONT_UF, "\\Uparrow ", "&uArr;"))
| "\\darr" -> DELIMITER (HTMLABLEM (FONT_UF, "\\downarrow ", "&darr;"))
| "\\downarrow" -> DELIMITER (HTMLABLEM (FONT_UF, "\\downarrow ", "&darr;"))
| "\\dArr" -> DELIMITER (HTMLABLE (FONT_UF, "\\Downarrow ", "&dArr;"))
| "\\Darr" -> DELIMITER (HTMLABLE (FONT_UF, "\\Downarrow ", "&dArr;"))
| "\\Downarrow" -> DELIMITER (HTMLABLE (FONT_UF, "\\Downarrow ", "&dArr;"))
| "\\updownarrow" -> DELIMITER (TEX_ONLY "\\updownarrow ")
| "\\Updownarrow" -> DELIMITER (TEX_ONLY "\\Updownarrow ")
| "\\ulcorner" -> (tex_use_ams (); DELIMITER (TEX_ONLY "\\ulcorner "))
| "\\urcorner" -> (tex_use_ams (); DELIMITER (TEX_ONLY "\\urcorner "))
| "\\llcorner" -> (tex_use_ams (); DELIMITER (TEX_ONLY "\\llcorner "))
| "\\lrcorner" -> (tex_use_ams (); DELIMITER (TEX_ONLY "\\lrcorner "))
| "\\twoheadleftarrow" -> (tex_use_ams (); DELIMITER (TEX_ONLY "\\twoheadleftarrow "))
| "\\twoheadrightarrow" -> (tex_use_ams (); DELIMITER (TEX_ONLY "\\twoheadrightarrow "))
| "\\xleftarrow" -> (tex_use_ams (); FUN_AR1 "\\xleftarrow ")
| "\\xrightarrow" -> (tex_use_ams (); FUN_AR1 "\\xrightarrow ")
| "\\rightleftharpoons" -> DELIMITER (TEX_ONLY "\\rightleftharpoons ")
| "\\leftrightarrow" -> LITERAL (HTMLABLE (FONT_UF, "\\leftrightarrow ", "&harr;"))
| "\\lrarr" -> LITERAL (HTMLABLE (FONT_UF, "\\leftrightarrow ", "&harr;"))
| "\\harr" -> LITERAL (HTMLABLE (FONT_UF, "\\leftrightarrow ", "&harr;"))
| "\\Leftrightarrow" -> LITERAL (HTMLABLE (FONT_UF, "\\Leftrightarrow ", "&hArr;"))
| "\\Lrarr" -> LITERAL (HTMLABLE (FONT_UF, "\\Leftrightarrow ", "&hArr;"))
| "\\Harr" -> LITERAL (HTMLABLE (FONT_UF, "\\Leftrightarrow ", "&hArr;"))
| "\\lrArr" -> LITERAL (HTMLABLE (FONT_UF, "\\Leftrightarrow ", "&hArr;"))
| "\\hAar" -> LITERAL (HTMLABLE (FONT_UF, "\\Leftrightarrow ", "&hArr;"))
| "\\longleftrightarrow"->LITERAL (HTMLABLE (FONT_UF, "\\longleftrightarrow ", "&harr;"))
| "\\Longleftrightarrow"->LITERAL (HTMLABLE (FONT_UF, "\\Longleftrightarrow ", "&harr;"))
| "\\iff" -> LITERAL (HTMLABLE (FONT_UF, "\\iff ", "&harr;"))
| "\\ll" -> LITERAL (TEX_ONLY "\\ll ")
| "\\gg" -> LITERAL (TEX_ONLY "\\gg ")
| "\\div" -> LITERAL (TEX_ONLY "\\div ")
| "\\searrow" -> LITERAL (TEX_ONLY "\\searrow ")
| "\\nearrow" -> LITERAL (TEX_ONLY "\\nearrow ")
| "\\swarrow" -> LITERAL (TEX_ONLY "\\swarrow ")
| "\\nwarrow" -> LITERAL (TEX_ONLY "\\nwarrow ")
| "\\simeq" -> LITERAL (TEX_ONLY "\\simeq ")
| "\\ast" -> LITERAL (TEX_ONLY "\\ast ")
| "\\star" -> LITERAL (TEX_ONLY "\\star ")
| "\\ell" -> LITERAL (TEX_ONLY "\\ell ")
| "\\P" -> LITERAL (TEX_ONLY "\\P ")
| "\\smile" -> LITERAL (TEX_ONLY "\\smile ")
| "\\frown" -> LITERAL (TEX_ONLY "\\frown ")
| "\\bigcap" -> LITERAL (TEX_ONLY "\\bigcap ")
| "\\bigodot" -> LITERAL (TEX_ONLY "\\bigodot ")
| "\\bigcup" -> LITERAL (TEX_ONLY "\\bigcup ")
| "\\bigotimes" -> LITERAL (TEX_ONLY "\\bigotimes ")
| "\\coprod" -> LITERAL (TEX_ONLY "\\coprod ")
| "\\bigsqcup" -> LITERAL (TEX_ONLY "\\bigsqcup ")
| "\\bigoplus" -> LITERAL (TEX_ONLY "\\bigoplus ")
| "\\bigvee" -> LITERAL (TEX_ONLY "\\bigvee ")
| "\\biguplus" -> LITERAL (TEX_ONLY "\\biguplus ")
| "\\oint" -> LITERAL (TEX_ONLY "\\oint ")
| "\\bigwedge" -> LITERAL (TEX_ONLY "\\bigwedge ")
| "\\models" -> LITERAL (TEX_ONLY "\\models ")
| "\\vdash" -> LITERAL (TEX_ONLY "\\vdash ")
| "\\triangle" -> LITERAL (TEX_ONLY "\\triangle ")
| "\\bowtie" -> LITERAL (TEX_ONLY "\\bowtie ")
| "\\wr" -> LITERAL (TEX_ONLY "\\wr ")
| "\\triangleleft" -> LITERAL (TEX_ONLY "\\triangleleft ")
| "\\triangleright" -> LITERAL (TEX_ONLY "\\triangleright ")
| "\\textvisiblespace" -> LITERAL (TEX_ONLY "\\mbox{\\textvisiblespace}")
| "\\circ" -> LITERAL (TEX_ONLY "\\circ ")
| "\\hbar" -> LITERAL (TEX_ONLY "\\hbar ")
| "\\imath" -> LITERAL (TEX_ONLY "\\imath ")
| "\\jmath" -> LITERAL (TEX_ONLY "\\jmath ")
| "\\lnot" -> LITERAL (TEX_ONLY "\\lnot ")
| "\\hookrightarrow" -> LITERAL (TEX_ONLY "\\hookrightarrow ")
| "\\hookleftarrow" -> LITERAL (TEX_ONLY "\\hookleftarrow ")
| "\\mp" -> LITERAL (TEX_ONLY "\\mp ")
| "\\approx" -> LITERAL (HTMLABLE (FONT_UF, "\\approx ", "&asymp;"))
| "\\propto" -> LITERAL (TEX_ONLY "\\propto ")
| "\\flat" -> LITERAL (TEX_ONLY "\\flat ")
| "\\sharp" -> LITERAL (TEX_ONLY "\\sharp ")
| "\\natural" -> LITERAL (TEX_ONLY "\\natural ")
| "\\int" -> LITERAL (HTMLABLE_BIG ("\\int ", "&int;"))
| "\\sum" -> LITERAL (HTMLABLE_BIG ("\\sum ", "&sum;"))
| "\\prod" -> LITERAL (HTMLABLE_BIG ("\\prod ", "&prod;"))
| "\\vdots" -> LITERAL (TEX_ONLY "\\vdots ")
| "\\limits" -> LITERAL (TEX_ONLY "\\limits ")
| "\\nolimits" -> LITERAL (TEX_ONLY "\\nolimits ")
| "\\top" -> LITERAL (TEX_ONLY "\\top ")
| "\\bullet" -> LITERAL (HTMLABLE (FONT_UFH, "\\bullet ", "&bull;"))
| "\\bull" -> LITERAL (HTMLABLE (FONT_UFH, "\\bullet ", "&bull;"))
| "\\angle" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\angle ", "&ang;")))
| "\\dagger" -> LITERAL (HTMLABLEM(FONT_UFH, "\\dagger ", "&dagger;"))
| "\\ddagger" -> LITERAL (HTMLABLEM(FONT_UFH, "\\ddagger ", "&Dagger;"))
| "\\Dagger" -> LITERAL (HTMLABLEM(FONT_UFH, "\\ddagger ", "&Dagger;"))
| "\\colon" -> LITERAL (HTMLABLEC(FONT_UFH, "\\colon ", ":"))
| "\\Vert" -> DELIMITER (HTMLABLEM(FONT_UFH, "\\Vert ", "||"))
| "\\vert" -> DELIMITER (HTMLABLEM(FONT_UFH, "\\vert ", "|"))
| "\\wp" -> LITERAL (HTMLABLE (FONT_UF, "\\wp ", "&weierp;"))
| "\\weierp" -> LITERAL (HTMLABLE (FONT_UF, "\\wp ", "&weierp;"))
| "\\wedge" -> LITERAL (HTMLABLE (FONT_UF, "\\wedge ", "&and;"))
| "\\and" -> LITERAL (HTMLABLE (FONT_UF, "\\land ", "&and;"))
| "\\land" -> LITERAL (HTMLABLE (FONT_UF, "\\land ", "&and;"))
| "\\vee" -> LITERAL (HTMLABLE (FONT_UF, "\\vee ", "&or;"))
| "\\or" -> LITERAL (HTMLABLE (FONT_UF, "\\lor ", "&or;"))
| "\\lor" -> LITERAL (HTMLABLE (FONT_UF, "\\lor ", "&or;"))
| "\\sub" -> LITERAL (HTMLABLE (FONT_UF, "\\subset ", "&sub;"))
| "\\supe" -> LITERAL (HTMLABLE (FONT_UF, "\\supseteq ", "&supe;"))
| "\\sube" -> LITERAL (HTMLABLE (FONT_UF, "\\subseteq ", "&sube;"))
| "\\supset" -> LITERAL (HTMLABLE (FONT_UF, "\\supset ", "&sup;"))
| "\\subset" -> LITERAL (HTMLABLE (FONT_UF, "\\subset ", "&sub;"))
| "\\supseteq" -> LITERAL (HTMLABLE (FONT_UF, "\\supseteq ", "&supe;"))
| "\\subseteq" -> LITERAL (HTMLABLE (FONT_UF, "\\subseteq ", "&sube;"))
| "\\sqsupset" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sqsupset "))
| "\\sqsubset" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sqsubset "))
| "\\sqsupseteq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sqsupseteq "))
| "\\sqsubseteq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sqsubseteq "))
| "\\perp" -> LITERAL (HTMLABLE (FONT_UF, "\\perp ", "&perp;"))
| "\\bot" -> LITERAL (HTMLABLE (FONT_UF, "\\bot ", "&perp;"))
| "\\lfloor" -> DELIMITER (HTMLABLE (FONT_UF, "\\lfloor ", "&lfloor;"))
| "\\rfloor" -> DELIMITER (HTMLABLE (FONT_UF, "\\rfloor ", "&rfloor;"))
| "\\lceil" -> DELIMITER (HTMLABLE (FONT_UF, "\\lceil ", "&lceil;"))
| "\\rceil" -> DELIMITER (HTMLABLE (FONT_UF, "\\rceil ", "&rceil;"))
| "\\lbrace" -> DELIMITER (HTMLABLEC(FONT_UFH, "\\lbrace ", "{"))
| "\\rbrace" -> DELIMITER (HTMLABLEC(FONT_UFH, "\\rbrace ", "}"))
| "\\infty" -> LITERAL (HTMLABLEM(FONT_UF, "\\infty ", "&infin;"))
| "\\infin" -> LITERAL (HTMLABLEM(FONT_UF, "\\infty ", "&infin;"))
| "\\isin" -> LITERAL (HTMLABLE (FONT_UF, "\\in ", "&isin;"))
| "\\in" -> LITERAL (HTMLABLE (FONT_UF, "\\in ", "&isin;"))
| "\\ni" -> LITERAL (HTMLABLE (FONT_UF, "\\ni ", "&ni;"))
| "\\notin" -> LITERAL (HTMLABLE (FONT_UF, "\\notin ", "&notin;"))
| "\\smallsetminus" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\smallsetminus "))
| "\\And" -> (tex_use_ams (); LITERAL (HTMLABLEM(FONT_UFH, "\\And ", "&nbsp;&amp;&nbsp;")))
| "\\forall" -> LITERAL (HTMLABLE (FONT_UFH, "\\forall ", "&forall;"))
| "\\exists" -> LITERAL (HTMLABLE (FONT_UFH, "\\exists ", "&exist;"))
| "\\exist" -> LITERAL (HTMLABLE (FONT_UFH, "\\exists ", "&exist;"))
| "\\equiv" -> LITERAL (HTMLABLEM(FONT_UFH, "\\equiv ", "&equiv;"))
| "\\ne" -> LITERAL (HTMLABLEM(FONT_UFH, "\\neq ", "&ne;"))
| "\\neq" -> LITERAL (HTMLABLEM(FONT_UFH, "\\neq ", "&ne;"))
| "\\Re" -> LITERAL (HTMLABLE (FONT_UF, "\\Re ", "&real;"))
| "\\real" -> LITERAL (HTMLABLE (FONT_UF, "\\Re ", "&real;"))
| "\\Im" -> LITERAL (HTMLABLE (FONT_UF, "\\Im ", "&image;"))
| "\\image" -> LITERAL (HTMLABLE (FONT_UF, "\\Im ", "&image;"))
| "\\prime" -> LITERAL (HTMLABLE (FONT_UFH,"\\prime ", "&prime;"))
| "\\backslash" -> DELIMITER (HTMLABLEM(FONT_UFH,"\\backslash ", "\\"))
| "\\setminus" -> LITERAL (HTMLABLEM(FONT_UFH,"\\setminus ", "\\"))
| "\\times" -> LITERAL (HTMLABLEM(FONT_UFH,"\\times ", "&times;"))
| "\\pm" -> LITERAL (HTMLABLEM(FONT_UFH,"\\pm ", "&plusmn;"))
| "\\plusmn" -> LITERAL (HTMLABLEM(FONT_UFH,"\\pm ", "&plusmn;"))
| "\\cdot" -> LITERAL (HTMLABLE (FONT_UFH,"\\cdot ", "&sdot;"))
| "\\AA" -> LITERAL (HTMLABLE (FONT_UFH,"\\mbox{\\AA}", "&Aring;"))
| "\\cdots" -> LITERAL (HTMLABLE (FONT_UFH,"\\cdots ", "&sdot;&sdot;&sdot;"))
| "\\sdot" -> LITERAL (HTMLABLE (FONT_UFH,"\\cdot ", "&sdot;"))
| "\\oplus" -> LITERAL (HTMLABLE (FONT_UF, "\\oplus ", "&oplus;"))
| "\\otimes" -> LITERAL (HTMLABLE (FONT_UF, "\\otimes ", "&otimes;"))
| "\\cap" -> LITERAL (HTMLABLEM(FONT_UF, "\\cap ", "&cap;"))
| "\\cup" -> LITERAL (HTMLABLE (FONT_UF, "\\cup ", "&cup;"))
| "\\uplus" -> LITERAL (TEX_ONLY "\\uplus ")
| "\\sqcap" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sqcap "))
| "\\sqcup" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sqcup "))
| "\\empty" -> LITERAL (HTMLABLE (FONT_UF, "\\emptyset ", "&empty;"))
| "\\emptyset" -> LITERAL (HTMLABLE (FONT_UF, "\\emptyset ", "&empty;"))
| "\\O" -> LITERAL (HTMLABLE (FONT_UF, "\\emptyset ", "&empty;"))
| "\\S" -> LITERAL (HTMLABLEM(FONT_UFH,"\\S ", "&sect;"))
| "\\sect" -> LITERAL (HTMLABLEM(FONT_UFH,"\\S ", "&sect;"))
| "\\nabla" -> LITERAL (HTMLABLE (FONT_UF, "\\nabla ", "&nabla;"))
| "\\geq" -> LITERAL (HTMLABLE (FONT_UFH,"\\geq ", "&ge;"))
| "\\ge" -> LITERAL (HTMLABLE (FONT_UFH,"\\geq ", "&ge;"))
| "\\leq" -> LITERAL (HTMLABLE (FONT_UFH,"\\leq ", "&le;"))
| "\\le" -> LITERAL (HTMLABLE (FONT_UFH,"\\leq ", "&le;"))
| "\\cong" -> LITERAL (HTMLABLE (FONT_UF, "\\cong ", "&cong;"))
| "\\ang" -> LITERAL (HTMLABLE (FONT_UF, "\\angle ", "&ang;"))
| "\\part" -> LITERAL (HTMLABLEM(FONT_UF, "\\partial ", "&part;"))
| "\\partial" -> LITERAL (HTMLABLEM(FONT_UF, "\\partial ", "&part;"))
| "\\ldots" -> LITERAL (HTMLABLEM(FONT_UFH,"\\ldots ", "..."))
| "\\dots" -> LITERAL (HTMLABLEM(FONT_UFH,"\\dots ", "..."))
| "\\quad" -> LITERAL (HTMLABLE (FONT_UF, "\\quad ","&nbsp;&nbsp;"))
| "\\qquad" -> LITERAL (HTMLABLE (FONT_UF, "\\qquad ","&nbsp;&nbsp;&nbsp;&nbsp;"))
| "\\mid" -> LITERAL (HTMLABLEM(FONT_UFH,"\\mid ", " | "))
| "\\neg" -> LITERAL (HTMLABLEM(FONT_UFH,"\\neg ", "&not;"))
| "\\langle" -> DELIMITER (HTMLABLE (FONT_UFH,"\\langle ","&lang;"))
| "\\rangle" -> DELIMITER (HTMLABLE (FONT_UFH,"\\rangle ","&rang;"))
| "\\lang" -> DELIMITER (HTMLABLE (FONT_UFH,"\\langle ","&lang;"))
| "\\rang" -> DELIMITER (HTMLABLE (FONT_UFH,"\\rangle ","&rang;"))
| "\\lbrack" -> DELIMITER (HTMLABLEC(FONT_UFH,"[","["))
| "\\rbrack" -> DELIMITER (HTMLABLEC(FONT_UFH,"]","]"))
| "\\surd" -> LITERAL (TEX_ONLY "\\surd ")
| "\\ddots" -> LITERAL (TEX_ONLY "\\ddots ")
| "\\clubs" -> LITERAL (TEX_ONLY "\\clubsuit ")
| "\\clubsuit" -> LITERAL (TEX_ONLY "\\clubsuit ")
| "\\spades" -> LITERAL (TEX_ONLY "\\spadesuit ")
| "\\spadesuit" -> LITERAL (TEX_ONLY "\\spadesuit ")
| "\\hearts" -> LITERAL (TEX_ONLY "\\heartsuit ")
| "\\heartsuit" -> LITERAL (TEX_ONLY "\\heartsuit ")
| "\\diamonds" -> LITERAL (TEX_ONLY "\\diamondsuit ")
| "\\diamond" -> LITERAL (TEX_ONLY "\\diamond ")
| "\\bigtriangleup" -> LITERAL (TEX_ONLY "\\bigtriangleup ")
| "\\bigtriangledown" -> LITERAL (TEX_ONLY "\\bigtriangledown ")
| "\\diamondsuit" -> LITERAL (TEX_ONLY "\\diamondsuit ")
| "\\ominus" -> LITERAL (TEX_ONLY "\\ominus ")
| "\\oslash" -> LITERAL (TEX_ONLY "\\oslash ")
| "\\odot" -> LITERAL (TEX_ONLY "\\odot ")
| "\\bigcirc" -> LITERAL (TEX_ONLY "\\bigcirc ")
| "\\amalg" -> LITERAL (TEX_ONLY "\\amalg ")
| "\\prec" -> LITERAL (TEX_ONLY "\\prec ")
| "\\succ" -> LITERAL (TEX_ONLY "\\succ ")
| "\\preceq" -> LITERAL (TEX_ONLY "\\preceq ")
| "\\succeq" -> LITERAL (TEX_ONLY "\\succeq ")
| "\\dashv" -> LITERAL (TEX_ONLY "\\dashv ")
| "\\asymp" -> LITERAL (TEX_ONLY "\\asymp ")
| "\\doteq" -> LITERAL (TEX_ONLY "\\doteq ")
| "\\parallel" -> LITERAL (TEX_ONLY "\\parallel ")
| "\\euro" -> (tex_use_euro (); LITERAL (HTMLABLEC (FONT_UF, "\\mbox{\\euro}", "&euro;")))
| "\\geneuro" -> (tex_use_euro (); LITERAL (TEX_ONLY "\\mbox{\\geneuro}"))
| "\\geneuronarrow" -> (tex_use_euro (); LITERAL (TEX_ONLY "\\mbox{\\geneuronarrow}"))
| "\\geneurowide" -> (tex_use_euro (); LITERAL (TEX_ONLY "\\mbox{\\geneurowide}"))
| "\\officialeuro" -> (tex_use_euro (); LITERAL (TEX_ONLY "\\mbox{\\officialeuro}"))
| "\\Coppa" -> (tex_use_teubner (); LITERAL (HTMLABLE (FONT_UF, "\\mbox{\\Coppa}", "&#984;")))
| "\\coppa" -> (tex_use_teubner (); LITERAL (HTMLABLE (FONT_UF, "\\mbox{\\coppa}", "&#985;")))
| "\\varcoppa" -> (tex_use_teubner (); LITERAL (HTMLABLE (FONT_UF, "\\mbox{\\coppa}", "&#985;")))
| "\\Digamma" -> (tex_use_teubner (); LITERAL (HTMLABLE (FONT_UF, "\\mbox{\\Digamma}", "&#988;")))
| "\\Koppa" -> (tex_use_teubner (); LITERAL (HTMLABLE (FONT_UF, "\\mbox{\\Koppa}", "&#984;")))
| "\\koppa" -> (tex_use_teubner (); LITERAL (HTMLABLE (FONT_UF, "\\mbox{\\koppa}", "&#991;")))
| "\\Sampi" -> (tex_use_teubner (); LITERAL (TEX_ONLY "\\mbox{\\Sampi}"))
| "\\sampi" -> (tex_use_teubner (); LITERAL (HTMLABLE (FONT_UF, "\\mbox{\\sampi}", "&#993;")))
| "\\Stigma" -> (tex_use_teubner (); LITERAL (TEX_ONLY "\\mbox{\\Stigma}"))
| "\\stigma" -> (tex_use_teubner (); LITERAL (HTMLABLE (FONT_UF, "\\mbox{\\stigma}", "&#987;")))
| "\\varstigma" -> (tex_use_teubner (); LITERAL (TEX_ONLY "\\mbox{\\varstigma}"))
| "\\implies" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\implies ", "&rArr;")))
| "\\mod" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mod ", "mod")))
| "\\Diamond" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\Diamond ", "&loz;")))
| "\\dotsb" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\dotsb ", "&sdot;&sdot;&sdot;")))
| "\\dotsc" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\dotsc ", "...")))
| "\\dotsi" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\dotsi ", "&sdot;&sdot;&sdot;")))
| "\\dotsm" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\dotsm ", "&sdot;&sdot;&sdot;")))
| "\\dotso" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\dotso ", "...")))
| "\\reals" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{R}", "&#8477;")))
| "\\Reals" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{R}", "&#8477;")))
| "\\R" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{R}", "&#8477;")))
| "\\C" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{C}", "&#8450;")))
| "\\cnums" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{C}", "&#8450;")))
| "\\Complex" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{C}", "&#8450;")))
| "\\Z" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{Z}", "&#8484;")))
| "\\natnums" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{N}", "&#8469;")))
| "\\N" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{N}", "&#8469;")))
| "\\Q" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{Q}", "&#8474;")))
| "\\H" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{H}", "&#8461;")))
| "\\lVert" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\lVert ", "||")))
| "\\rVert" -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\rVert ", "||")))
| "\\nmid" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nmid "))
| "\\lesssim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lesssim "))
| "\\ngeq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ngeq "))
| "\\smallsmile" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\smallsmile "))
| "\\smallfrown" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\smallfrown "))
| "\\nleftarrow" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nleftarrow "))
| "\\nrightarrow" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nrightarrow "))
| "\\trianglelefteq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\trianglelefteq "))
| "\\trianglerighteq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\trianglerighteq "))
| "\\square" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\square "))
| "\\checkmark" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\checkmark "))
| "\\supsetneq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\supsetneq "))
| "\\subsetneq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\subsetneq "))
| "\\Box" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Box "))
| "\\nleq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nleq "))
| "\\upharpoonright" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\upharpoonright "))
| "\\restriction" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\upharpoonright "))
| "\\upharpoonleft" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\upharpoonleft "))
| "\\downharpoonright" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\downharpoonright "))
| "\\downharpoonleft" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\downharpoonleft "))
| "\\rightharpoonup" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\rightharpoonup "))
| "\\rightharpoondown" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\rightharpoondown "))
| "\\leftharpoonup" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\leftharpoonup "))
| "\\leftharpoondown" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\leftharpoondown "))
| "\\nless" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nless "))
| "\\Vdash" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Vdash "))
| "\\vDash" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\vDash "))
| "\\varkappa" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varkappa "))
| "\\digamma" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\digamma "))
| "\\beth" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\beth "))
| "\\daleth" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\daleth "))
| "\\gimel" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gimel "))
| "\\complement" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\complement "))
| "\\eth" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\eth "))
| "\\hslash" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\hslash "))
| "\\mho" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\mho "))
| "\\Finv" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Finv "))
| "\\Game" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Game "))
| "\\varlimsup" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varlimsup "))
| "\\varliminf" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varliminf "))
| "\\varinjlim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varinjlim "))
| "\\varprojlim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varprojlim "))
| "\\injlim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\injlim "))
| "\\projlim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\projlim "))
| "\\iint" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\iint "))
| "\\iiint" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\iiint "))
| "\\iiiint" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\iiiint "))
| "\\varnothing" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varnothing "))
| "\\left" -> LEFT
| "\\right" -> RIGHT
| "\\hat" -> FUN_AR1 "\\hat "
| "\\hline" -> LITERAL (TEX_ONLY "\\hline ")
| "\\vline" -> LITERAL (TEX_ONLY "\\vline ")
| "\\widetilde" -> FUN_AR1 "\\widetilde "
| "\\widehat" -> FUN_AR1 "\\widehat "
| "\\overline" -> FUN_AR1 "\\overline "
| "\\overbrace" -> FUN_AR1nb "\\overbrace "
| "\\underline" -> FUN_AR1 "\\underline "
| "\\underbrace" -> FUN_AR1nb "\\underbrace "
| "\\overleftarrow" -> FUN_AR1 "\\overleftarrow "
| "\\overrightarrow" -> FUN_AR1 "\\overrightarrow "
| "\\overleftrightarrow"-> (tex_use_ams(); FUN_AR1 "\\overleftrightarrow ")
| "\\check" -> FUN_AR1 "\\check "
| "\\acute" -> FUN_AR1 "\\acute "
| "\\grave" -> FUN_AR1 "\\grave "
| "\\bar" -> FUN_AR1 "\\bar "
| "\\vec" -> FUN_AR1 "\\vec "
| "\\dot" -> FUN_AR1 "\\dot "
| "\\ddot" -> FUN_AR1 "\\ddot "
| "\\breve" -> FUN_AR1 "\\breve "
| "\\tilde" -> FUN_AR1 "\\tilde "
| "\\not" -> LITERAL (TEX_ONLY "\\not ")
| "\\choose" -> FUN_INFIX "\\choose "
| "\\atop" -> FUN_INFIX "\\atop "
| "\\binom" -> (tex_use_ams (); FUN_AR2 "\\binom ")
| "\\dbinom" -> (tex_use_ams (); FUN_AR2 "\\dbinom ")
| "\\tbinom" -> (tex_use_ams (); FUN_AR2 "\\tbinom ")
| "\\stackrel" -> FUN_AR2 "\\stackrel "
| "\\sideset" -> (tex_use_ams (); FUN_AR2nb "\\sideset ")
| "\\underset" -> (tex_use_ams (); FUN_AR2 "\\underset ")
| "\\overset" -> (tex_use_ams (); FUN_AR2 "\\overset ")
| "\\frac" -> FUN_AR2h ("\\frac ", fun num den -> Html.html_render [num], "<hr style=\"{background: black}\"/>", Html.html_render [den])
| "\\dfrac" -> (tex_use_ams () ; FUN_AR2 "\\dfrac ")
| "\\tfrac" -> (tex_use_ams () ; FUN_AR2h ("\\tfrac ", fun num den -> Html.html_render [num], "<hr style=\"background: black\">", Html.html_render [den]))
| "\\cfrac" -> (tex_use_ams (); FUN_AR2h ("\\cfrac ", fun num den -> Html.html_render [num], "<hr style=\"{background: black}\">", Html.html_render [den]))
| "\\over" -> FUN_INFIXh ("\\over ", fun num den -> Html.html_render num, "<hr style=\"{background: black}\"/>", Html.html_render den)
| "\\sqrt" -> FUN_AR1 "\\sqrt "
| "\\cancel" -> FUN_AR1 "\\cancel "
| "\\bcancel" -> FUN_AR1 "\\bcancel "
| "\\xcancel" -> FUN_AR1 "\\xcancel "
| "\\cancelto" -> FUN_AR2 "\\cancelto "
| "\\pmod" -> FUN_AR1hl ("\\pmod ", ("(mod ", ")"))
| "\\bmod" -> FUN_AR1hl ("\\bmod ", ("mod ", ""))
| "\\emph" -> FUN_AR1 "\\emph "
| "\\texttt" -> FUN_AR1 "\\texttt "
| "\\textbf" -> FUN_AR1 "\\textbf "
| "\\textsf" -> FUN_AR1 "\\textsf "
| "\\textit" -> FUN_AR1hf ("\\textit ", FONTFORCE_IT)
| "\\textrm" -> FUN_AR1hf ("\\textrm ", FONTFORCE_RM)
| "\\rm" -> DECLh ("\\rm ", FONTFORCE_RM)
| "\\it" -> DECLh ("\\it ", FONTFORCE_IT)
| "\\cal" -> DECL "\\cal "
| "\\displaystyle" -> LITERAL (TEX_ONLY "\\displaystyle ")
| "\\scriptstyle" -> LITERAL (TEX_ONLY "\\scriptstyle ")
| "\\textstyle" -> LITERAL (TEX_ONLY "\\textstyle ")
| "\\scriptscriptstyle"-> LITERAL (TEX_ONLY "\\scriptscriptstyle ")
| "\\bf" -> DECL "\\bf "
| "\\big" -> BIG "\\big "
| "\\Big" -> BIG "\\Big "
| "\\bigg" -> BIG "\\bigg "
| "\\Bigg" -> BIG "\\Bigg "
| "\\bigl" -> (tex_use_ams ();BIG "\\bigl ")
| "\\bigr" -> (tex_use_ams ();BIG "\\bigr ")
| "\\Bigl" -> (tex_use_ams ();BIG "\\Bigl ")
| "\\Bigr" -> (tex_use_ams ();BIG "\\Bigr ")
| "\\biggl" -> (tex_use_ams ();BIG "\\biggl ")
| "\\biggr" -> (tex_use_ams ();BIG "\\biggr ")
| "\\Biggl" -> (tex_use_ams ();BIG "\\Biggl ")
| "\\Biggr" -> (tex_use_ams ();BIG "\\Biggr ")
| "\\vartriangle" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\vartriangle "))
| "\\triangledown" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\triangledown "))
| "\\lozenge" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lozenge "))
| "\\circledS" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\circledS "))
| "\\measuredangle" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\measuredangle "))
| "\\nexists" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nexists "))
| "\\Bbbk" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Bbbk "))
| "\\backprime" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\backprime "))
| "\\blacktriangle" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\blacktriangle "))
| "\\blacktriangledown"-> (tex_use_ams (); LITERAL (TEX_ONLY "\\blacktriangledown "))
| "\\blacksquare" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\blacksquare "))
| "\\blacklozenge" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\blacklozenge "))
| "\\bigstar" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\bigstar "))
| "\\sphericalangle" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sphericalangle "))
| "\\diagup" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\diagup "))
| "\\diagdown" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\diagdown "))
| "\\dotplus" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\dotplus "))
| "\\Cap" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Cap "))
| "\\doublecap" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Cap "))
| "\\Cup" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Cup "))
| "\\doublecup" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Cup "))
| "\\barwedge" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\barwedge "))
| "\\veebar" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\veebar "))
| "\\doublebarwedge" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\doublebarwedge "))
| "\\boxminus" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\boxminus "))
| "\\boxtimes" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\boxtimes "))
| "\\boxdot" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\boxdot "))
| "\\boxplus" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\boxplus "))
| "\\divideontimes" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\divideontimes "))
| "\\ltimes" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ltimes "))
| "\\rtimes" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\rtimes "))
| "\\leftthreetimes" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\leftthreetimes "))
| "\\rightthreetimes" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\rightthreetimes "))
| "\\curlywedge" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\curlywedge "))
| "\\curlyvee" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\curlyvee "))
| "\\circleddash" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\circleddash "))
| "\\circledast" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\circledast "))
| "\\circledcirc" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\circledcirc "))
| "\\centerdot" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\centerdot "))
| "\\intercal" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\intercal "))
| "\\leqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\leqq "))
| "\\leqslant" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\leqslant "))
| "\\eqslantless" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\eqslantless "))
| "\\lessapprox" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lessapprox "))
| "\\approxeq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\approxeq "))
| "\\lessdot" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lessdot "))
| "\\lll" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lll "))
| "\\lessgtr" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lessgtr "))
| "\\lesseqgtr" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lesseqgtr "))
| "\\lesseqqgtr" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lesseqqgtr "))
| "\\doteqdot" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\doteqdot "))
| "\\Doteq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\doteqdot "))
| "\\risingdotseq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\risingdotseq "))
| "\\fallingdotseq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\fallingdotseq "))
| "\\backsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\backsim "))
| "\\backsimeq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\backsimeq "))
| "\\subseteqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\subseteqq "))
| "\\Subset" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Subset "))
| "\\preccurlyeq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\preccurlyeq "))
| "\\curlyeqprec" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\curlyeqprec "))
| "\\precsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\precsim "))
| "\\precapprox" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\precapprox "))
| "\\vartriangleleft" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\vartriangleleft "))
| "\\Vvdash" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Vvdash "))
| "\\bumpeq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\bumpeq "))
| "\\Bumpeq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Bumpeq "))
| "\\geqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\geqq "))
| "\\geqslant" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\geqslant "))
| "\\eqslantgtr" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\eqslantgtr "))
| "\\gtrsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gtrsim "))
| "\\gtrapprox" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gtrapprox "))
| "\\eqsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\eqsim "))
| "\\gtrdot" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gtrdot "))
| "\\ggg" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ggg "))
| "\\gggtr" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ggg "))
| "\\gtrless" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gtrless "))
| "\\gtreqless" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gtreqless "))
| "\\gtreqqless" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gtreqqless "))
| "\\eqcirc" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\eqcirc "))
| "\\circeq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\circeq "))
| "\\triangleq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\triangleq "))
| "\\thicksim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\thicksim "))
| "\\thickapprox" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\thickapprox "))
| "\\supseteqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\supseteqq "))
| "\\Supset" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Supset "))
| "\\succcurlyeq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\succcurlyeq "))
| "\\curlyeqsucc" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\curlyeqsucc "))
| "\\succsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\succsim "))
| "\\succapprox" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\succapprox "))
| "\\vartriangleright" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\vartriangleright "))
| "\\shortmid" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\shortmid "))
| "\\shortparallel" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\shortparallel "))
| "\\between" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\between "))
| "\\pitchfork" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\pitchfork "))
| "\\varpropto" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varpropto "))
| "\\blacktriangleleft"-> (tex_use_ams (); LITERAL (TEX_ONLY "\\blacktriangleleft "))
| "\\therefore" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\therefore "))
| "\\backepsilon" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\backepsilon "))
| "\\blacktriangleright"-> (tex_use_ams (); LITERAL (TEX_ONLY "\\blacktriangleright "))
| "\\because" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\because "))
| "\\nleqslant" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nleqslant "))
| "\\nleqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nleqq "))
| "\\lneq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lneq "))
| "\\lneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lneqq "))
| "\\lvertneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lvertneqq "))
| "\\lnsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lnsim "))
| "\\lnapprox" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lnapprox "))
| "\\nprec" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nprec "))
| "\\npreceq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\npreceq "))
| "\\precneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\precneqq "))
| "\\precnsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\precnsim "))
| "\\precnapprox" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\precnapprox "))
| "\\nsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nsim "))
| "\\nshortmid" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nshortmid "))
| "\\nvdash" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nvdash "))
| "\\nVdash" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nVdash "))
| "\\ntriangleleft" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ntriangleleft "))
| "\\ntrianglelefteq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ntrianglelefteq "))
| "\\nsubseteq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nsubseteq "))
| "\\nsubseteqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nsubseteqq "))
| "\\varsubsetneq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varsubsetneq "))
| "\\subsetneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\subsetneqq "))
| "\\varsubsetneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varsubsetneqq "))
| "\\ngtr" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ngtr "))
| "\\ngeqslant" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ngeqslant "))
| "\\ngeqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ngeqq "))
| "\\gneq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gneq "))
| "\\gneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gneqq "))
| "\\gvertneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gvertneqq "))
| "\\gnsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gnsim "))
| "\\gnapprox" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gnapprox "))
| "\\nsucc" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nsucc "))
| "\\nsucceq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nsucceq "))
| "\\succneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\succneqq "))
| "\\succnsim" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\succnsim "))
| "\\succnapprox" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\succnapprox "))
| "\\ncong" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ncong "))
| "\\nshortparallel" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nshortparallel "))
| "\\nparallel" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nparallel "))
| "\\nvDash" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nvDash "))
| "\\nVDash" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nVDash "))
| "\\ntriangleright" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ntriangleright "))
| "\\ntrianglerighteq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ntrianglerighteq "))
| "\\nsupseteq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nsupseteq "))
| "\\nsupseteqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nsupseteqq "))
| "\\varsupsetneq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varsupsetneq "))
| "\\supsetneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\supsetneqq "))
| "\\varsupsetneqq" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varsupsetneqq "))
| "\\leftleftarrows" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\leftleftarrows "))
| "\\leftrightarrows" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\leftrightarrows "))
| "\\Lleftarrow" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Lleftarrow "))
| "\\leftarrowtail" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\leftarrowtail "))
| "\\looparrowleft" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\looparrowleft "))
| "\\leftrightharpoons"-> (tex_use_ams (); LITERAL (TEX_ONLY "\\leftrightharpoons "))
| "\\curvearrowleft" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\curvearrowleft "))
| "\\circlearrowleft" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\circlearrowleft "))
| "\\Lsh" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Lsh "))
| "\\upuparrows" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\upuparrows "))
| "\\rightrightarrows" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\rightrightarrows "))
| "\\rightleftarrows" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\rightleftarrows "))
| "\\Rrightarrow" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Rrightarrow "))
| "\\rightarrowtail" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\rightarrowtail "))
| "\\looparrowright" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\looparrowright "))
| "\\curvearrowright" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\curvearrowright "))
| "\\circlearrowright" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\circlearrowright "))
| "\\Rsh" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Rsh "))
| "\\downdownarrows" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\downdownarrows "))
| "\\multimap" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\multimap "))
| "\\leftrightsquigarrow"-> (tex_use_ams (); LITERAL (TEX_ONLY "\\leftrightsquigarrow "))
| "\\rightsquigarrow" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\rightsquigarrow "))
| "\\nLeftarrow" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nLeftarrow "))
| "\\nleftrightarrow" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nleftrightarrow "))
| "\\nRightarrow" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nRightarrow "))
| "\\nLeftrightarrow" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nLeftrightarrow "))
| "\\mathit" -> (tex_use_ams (); FUN_AR1hf ("\\mathit ", FONTFORCE_IT))
| "\\mathrm" -> (tex_use_ams (); FUN_AR1hf ("\\mathrm ", FONTFORCE_RM))
| "\\mathord" -> (tex_use_ams (); FUN_AR1 "\\mathord ")
| "\\mathop" -> (tex_use_ams (); FUN_AR1 "\\mathop ")
| "\\mathbin" -> (tex_use_ams (); FUN_AR1 "\\mathbin ")
| "\\mathrel" -> (tex_use_ams (); FUN_AR1 "\\mathrel ")
| "\\mathopen" -> (tex_use_ams (); FUN_AR1 "\\mathopen ")
| "\\mathclose" -> (tex_use_ams (); FUN_AR1 "\\mathclose ")
| "\\mathpunct" -> (tex_use_ams (); FUN_AR1 "\\mathpunct ")
| "\\boldsymbol" -> (tex_use_ams (); FUN_AR1 "\\boldsymbol ")
| "\\bold" -> (tex_use_ams (); FUN_AR1 "\\mathbf ")
| "\\Bbb" -> (tex_use_ams (); FUN_AR1 "\\mathbb ")
| "\\mathbf" -> (tex_use_ams (); FUN_AR1 "\\mathbf ")
| "\\mathsf" -> (tex_use_ams (); FUN_AR1 "\\mathsf ")
| "\\mathcal" -> (tex_use_ams (); FUN_AR1 "\\mathcal ")
| "\\mathbb" -> (tex_use_ams (); FUN_AR1 "\\mathbb ")
| "\\mathtt" -> (tex_use_ams (); FUN_AR1 "\\mathtt ")
| "\\mathfrak" -> (tex_use_ams (); FUN_AR1 "\\mathfrak ")
| "\\operatorname" -> (tex_use_ams (); FUN_AR1 "\\operatorname ")
| "\\text" -> raise (Failure "malformatted \\text")
| "\\mbox" -> raise (Failure "malformatted \\mbox")
| "\\vbox" -> raise (Failure "malformatted \\vbox")
| "\\hbox" -> raise (Failure "malformatted \\hbox")
| "\\color" -> (tex_use_color (); LITERAL (TEX_ONLY "\\color"))
| "\\pagecolor" -> (tex_use_color (); LITERAL (TEX_ONLY "\\pagecolor"))
| "\\definecolor" -> (tex_use_color (); LITERAL (TEX_ONLY "\\definecolor"))
| s -> raise (Illegal_tex_function s)

View File

@ -1,11 +0,0 @@
val render_tex : Tex.t -> string
val set_encoding : string -> unit
val tex_use_nonascii: unit -> unit
val tex_use_ams: unit -> unit
val get_preface : unit -> string
val get_footer : unit -> string
exception Illegal_tex_function of string
val find: string -> Parser.token

View File

@ -1,57 +0,0 @@
(* vim: set sw=8 ts=8 et: *)
exception LexerException of string
(* *)
let lexer_token_safe lexbuf =
try Lexer.token lexbuf
with Failure s -> raise (LexerException s)
(* *)
let render tmppath finalpath tree backcolor =
let outtex = Util.mapjoin Texutil.render_tex tree in
let md5 = Digest.to_hex (Digest.string outtex) in
begin
let mathml = Mathml.render tree
and html = Html.render tree
in print_string (match (html,!Html.conservativeness,mathml) with
None,_,None -> "+" ^ md5
| Some h,Html.CONSERVATIVE,None -> "c" ^ md5 ^ h
| Some h,Html.MODERATE,None -> "m" ^ md5 ^ h
| Some h,Html.LIBERAL,None -> "l" ^ md5 ^ h
| Some h,Html.CONSERVATIVE,Some m -> "C" ^ md5 ^ h ^ "\000" ^ m
| Some h,Html.MODERATE,Some m -> "M" ^ md5 ^ h ^ "\000" ^ m
| Some h,Html.LIBERAL,Some m -> "L" ^ md5 ^ h ^ "\000" ^ m
| None,_,Some m -> "X" ^ md5 ^ m
);
Render.render tmppath finalpath outtex md5 backcolor
end
(* Arguments:
* 1st : temporary directory to use as scratch space
* 2nd : target path
* 3rd : LaTeX input
* 4th : encoding (Default: UTF-8)
* 5th : color (Default: rgb 1.0 1.0 1.0)
*
* Output one character:
* S : Parsing error
* E : Lexer exception raised
* F : TeX function not recognized
* - : Generic/Default failure code. Might be an invalid argument,
* output file already exist, a problem with an external
* command ...
* *)
let _ =
Texutil.set_encoding (try Sys.argv.(4) with _ -> "UTF-8");
try render Sys.argv.(1) Sys.argv.(2) (
Parser.tex_expr lexer_token_safe (
Lexing.from_string Sys.argv.(3))
) (try Sys.argv.(5) with _ -> "rgb 1.0 1.0 1.0")
with Parsing.Parse_error -> print_string "S"
| LexerException _ -> print_string "E"
| Texutil.Illegal_tex_function s -> print_string ("F" ^ s)
| Util.FileAlreadyExists -> print_string "-"
| Invalid_argument _ -> print_string "-"
| Failure _ -> print_string "-"
| Render.ExternalCommandFailure s -> ()
| _ -> print_string "-"

View File

@ -1,62 +0,0 @@
open Netcgi;;
open Netcgi_types;;
open Netcgi_env;;
open Netchannels;;
let cgi = new Netcgi.std_activation ()
let out = cgi # output # output_string
let math = cgi # argument_value ~default:"" "math"
let tmppath = "/home/taw/public_html/wiki/tmp/"
let finalpath = "/home/taw/public_html/wiki/math/"
let finalurl = "http://wroclaw.taw.pl.eu.org/~taw/wiki/math/"
;;
let h_header = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\""^
" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"^
"<html><head><title>texvc</title></head><body>"^
"<form method=post action=\"http://wroclaw.taw.pl.eu.org/~taw/cgi-bin/newcodebase/math/texvc_cgi\">"^
"<textarea name='math' rows=10 cols=80>"
let h_middle = "</textarea><br /><input type=submit value=\"Preview\" name='preview'></form>"
let h_footer = "</body></html>\n"
let render tmppath finalpath tree =
let outtex = Texutil.mapjoin Texutil.print tree in
let md5 = Digest.to_hex (Digest.string outtex) in
begin
out "<h3>TeX</h3>";
out outtex; (* <, & and > should be protected *)
(try out ("<h3>HTML</h3>" ^ (Texutil.html_render tree))
with _ -> out "<h3>HTML could not be rendered</h3>");
try Render.render tmppath finalpath outtex md5;
out ("<h3>Image:</h3><img src=\""^finalurl^md5^".png\">")
with Util.FileAlreadyExists -> out ("<h3>Image:</h3><img src=\""^finalurl^md5^".png\">")
| Failure s -> out ("<h3>Other failure: " ^ s ^ "</h3>")
| Render.ExternalCommandFailure "latex" -> out "<h3>latex failed</h3>"
| Render.ExternalCommandFailure "dvips" -> out "<h3>dvips failed</h3>"
| _ -> out "<h3>Other failure</h3>"
end
;;
cgi#set_header ();;
out h_header;;
out math;;
out h_middle;;
exception LexerException of string
let lexer_token_safe lexbuf =
try Lexer.token lexbuf
with Failure s -> raise (LexerException s)
;;
if math = ""
then ()
else try
render tmppath finalpath (Parser.tex_expr lexer_token_safe (Lexing.from_string math))
with Parsing.Parse_error -> out "<h3>Parse error</h3>"
| LexerException s -> out "<h3>Lexing failure</h3>"
| Texutil.Illegal_tex_function s -> out ("<h3>Illegal TeX function: " ^ s ^ "</h3>")
| Failure s -> out ("<h3>Other failure: " ^ s ^ "</h3>")
| _ -> out "<h3>Other failure</h3>"
;;
out h_footer

View File

@ -1,24 +0,0 @@
exception LexerException of string
let lexer_token_safe lexbuf =
try Lexer.token lexbuf
with Failure s -> raise (LexerException s)
let rec foo () =
try
let line = input_line stdin in
(try
let tree = Parser.tex_expr lexer_token_safe (Lexing.from_string line) in
(match Html.render tree with
Some _ -> print_string "$^\n"
| None -> print_string "$_\n";
)
with
Texutil.Illegal_tex_function s -> print_string ("$T" ^ s ^ " " ^ line ^ "\n")
| LexerException s -> print_string ("$L" ^ line ^ "\n")
| _ -> print_string ("$ " ^ line ^ "\n"));
flush stdout;
foo ();
with
End_of_file -> ()
;;
foo ();;

View File

@ -1,3 +0,0 @@
Texutil.set_encoding (try Sys.argv.(2) with _ -> "UTF-8");
try print_string (Util.mapjoin Texutil.render_tex (Parser.tex_expr Lexer.token (Lexing.from_string Sys.argv.(1))))
with _ -> ()

View File

@ -1,26 +0,0 @@
(* vim: set sw=8 ts=8 et: *)
(* TODO document *)
let mapjoin f l = (List.fold_left (fun a b -> a ^ (f b)) "" l)
(* TODO document *)
let mapjoine e f = function
[] -> ""
| h::t -> (List.fold_left (fun a b -> a ^ e ^ (f b)) (f h) t)
(* Exception used by open_out_unless_exists below *)
exception FileAlreadyExists
(* Wrapper which raise an exception when output path already exist *)
let open_out_unless_exists path =
if Sys.file_exists path
then raise FileAlreadyExists
else open_out path
(* *)
let run_in_other_directory tmppath cmd =
let prevdir = Sys.getcwd () in(
Sys.chdir tmppath;
let retval = Sys.command cmd in
(Sys.chdir prevdir; retval)
)

View File

@ -317,19 +317,8 @@ class MathHooks {
* @return bool
*/
static function onLoadExtensionSchemaUpdates( $updater = null ) {
if ( is_null( $updater ) ) {
throw new Exception( 'Math extension is only necessary in 1.18 or above' );
}
$map = [ 'mysql', 'sqlite', 'postgres', 'oracle', 'mssql' ];
$type = $updater->getDB()->getType();
if ( !in_array( $type, $map ) ) {
throw new Exception( "Math extension does not currently support $type database." );
}
$sql = __DIR__ . '/../db/math.' . $type . '.sql';
$updater->addExtensionTable( 'math', $sql );
if ( in_array( 'latexml', MathRenderer::getValidModes() ) ) {
if ( in_array( $type, [ 'mysql', 'sqlite', 'postgres' ] ) ) {
$sql = __DIR__ . '/../db/mathlatexml.' . $type . '.sql';

View File

@ -1,191 +0,0 @@
<?php
/**
* @covers MathInputCheckTexvc
*
* @group Math
*
* @license GPL-2.0-or-later
*/
class MathInputCheckTexvcTest extends MediaWikiTestCase {
/**
* @var MathInputCheckTexvc
*/
protected $BadObject;
protected $GoodObject;
protected static $hasTexvccheck;
protected static $texvccheckPath;
public static function setUpBeforeClass() {
global $wgMathTexvcCheckExecutable;
if ( is_executable( $wgMathTexvcCheckExecutable ) ) {
wfDebugLog( __CLASS__, " using build in texvccheck from "
. "\$wgMathTexvcCheckExecutable = $wgMathTexvcCheckExecutable" );
# Using build-in
self::$hasTexvccheck = true;
self::$texvccheckPath = $wgMathTexvcCheckExecutable;
} else {
# Attempt to compile
wfDebugLog( __CLASS__, " compiling texvccheck..." );
$cmd = 'cd ' . dirname( __DIR__ ) . '/texvccheck; make --always-make 2>&1';
wfShellExec( $cmd, $retval );
if ( $retval === 0 ) {
self::$hasTexvccheck = true;
self::$texvccheckPath = dirname( __DIR__ ) . '/texvccheck/texvccheck';
wfDebugLog( __CLASS__, ' compiled texvccheck at ' . self::$texvccheckPath );
} else {
wfDebugLog( __CLASS__, ' ocaml not available or compilation of texvccheck failed' );
}
}
}
/**
* Sets up the fixture, for example, opens a network connection.
* This method is called before a test is executed.
*/
protected function setUp() {
parent::setUp();
$this->BadObject = new MathInputCheckTexvc( '\newcommand{\text{do evil things}}' );
$this->GoodObject = new MathInputCheckTexvc( '\sin\left(\frac12x\right)' );
if ( ! self::$hasTexvccheck ) {
$this->markTestSkipped( "No texvccheck installed on server" );
} else {
$this->setMwGlobals( 'wgMathTexvcCheckExecutable',
self::$texvccheckPath );
}
}
/**
* This is not a real phpUnit test.
* It's just to discover whether setting default values dependent
* on the existence of executables influences the performance reaonably.
* The test is disabled by default. You can enable it via
* php .../tests/phpunit/phpunit.php --group Utility ...
* @group Utility
*/
public function testPerformanceIsExecutable() {
global $wgMathTexvcCheckExecutable;
/** @var int the number of runs used in that test */
$numberOfRuns = 10;
/** @var double the maximal average time accetable for a execution of is_executable in seconds*/
$maxAvgTime = 0.001;
$tstart = microtime( true );
for ( $i = 1; $i <= $numberOfRuns; $i++ ) {
is_executable( $wgMathTexvcCheckExecutable );
}
$time = microtime( true ) - $tstart;
$this->assertTrue(
$time < $maxAvgTime * $numberOfRuns,
'function is_executable consumes too much time'
);
}
/**
* @covers MathInputCheckTexvc::getError
*/
public function testGetError() {
$this->assertNull( $this->GoodObject->getError() );
$this->assertNull( $this->BadObject->getError() );
$this->BadObject->isValid();
$this->GoodObject->isValid();
$this->assertNull( $this->GoodObject->getError() );
$expectedMessage = wfMessage(
'math_unknown_function', '\newcommand'
)->inContentLanguage()->escaped();
$this->assertContains( $expectedMessage, $this->BadObject->getError() );
}
/**
* @covers MathInputCheckTexvc::isValid
*/
public function testIsValid() {
$this->assertFalse( $this->BadObject->isValid() );
$this->assertTrue( $this->GoodObject->isValid() );
}
/**
* @covers MathInputCheckTexvc::getValidTex
*/
public function testGetValidTex() {
$this->assertNull( $this->GoodObject->getValidTex() );
$this->assertNull( $this->BadObject->getValidTex() );
$this->BadObject->isValid();
$this->GoodObject->isValid();
$this->assertNull( $this->BadObject->getValidTex() );
// Be aware of the additional brackets and spaces inserted here
$this->assertEquals( $this->GoodObject->getValidTex(), "\\sin \\left({\\frac 12}x\\right)" );
}
/**
* Test corner cases of texvccheck conversion
* @covers MathInputCheckTexvc::getValidTex
*/
public function testGetValidTexCornerCases() {
$Object = new MathInputCheckTexvc( '\reals' );
$Object->isValid();
$this->assertEquals( "\\mathbb{R} ", $Object->getValidTex() );
$Object = new MathInputCheckTexvc( '\lbrack' ); // Bug: 54624
$Object->isValid();
$this->assertEquals( '\\lbrack ', $Object->getValidTex() );
}
/**
* Tests behavior of convertTexvcError
* The method was moved from MathTexvc to MathInputCheckTexvc
* @covers MathTexvc::convertTexvcError
*/
public function testConvertTexvcError() {
$texvc = $this->getMockBuilder( 'MathInputCheckTexvc' )
->setMethods( null )
->disableOriginalConstructor()
->getMock();
$mathFailure = wfMessage( 'math_failure' )->inContentLanguage()->escaped();
$actualLexing = $texvc->convertTexvcError( 'E' );
$expectedLexing = wfMessage( 'math_lexing_error', '' )->inContentLanguage()->escaped();
$this->assertContains(
$mathFailure, $actualLexing, 'Lexing error contains general math failure message'
);
$this->assertContains(
$expectedLexing, $actualLexing, 'Lexing error contains detailed error for lexing'
);
$actualSyntax = $texvc->convertTexvcError( 'S' );
$expectedSyntax = wfMessage( 'math_syntax_error', '' )->inContentLanguage()->escaped();
$this->assertContains(
$mathFailure, $actualSyntax, 'Syntax error contains general math failure message'
);
$this->assertContains(
$expectedSyntax, $actualSyntax, 'Syntax error contains detailed error for syntax'
);
$unknownFunction = 'figureEightIntegral';
$actualUnknownFunction = $texvc->convertTexvcError( "F$unknownFunction" );
$expectedUnknownFunction = wfMessage(
'math_unknown_function', $unknownFunction
)->inContentLanguage()->escaped();
$this->assertContains( $mathFailure, $actualUnknownFunction,
'Unknown function error contains general math failure message'
);
$this->assertContains( $expectedUnknownFunction, $actualUnknownFunction,
'Unknown function error contains detailed error for unknown function'
);
$actualUnknownError = $texvc->convertTexvcError( 'Q' );
$expectedUnknownError = wfMessage( 'math_unknown_error', '' )->inContentLanguage()->escaped();
$this->assertContains(
$mathFailure, $actualUnknownError, 'Unknown error contains general math failure message'
);
$this->assertContains( $expectedUnknownError, $actualUnknownError,
'Unknown error contains detailed error for unknownError'
);
}
}

View File

@ -35,8 +35,8 @@ class MathDatabaseTest extends MediaWikiTestCase {
// TODO: figure out why this is necessary
$this->db = wfGetDB( DB_MASTER );
// Create a new instance of MathSource
$this->renderer = new MathTexvc( self::SOME_TEX );
$this->tablesUsed[] = 'math';
$this->renderer = new MathMathML( self::SOME_TEX );
$this->tablesUsed[] = 'mathoid';
}
/**
@ -55,8 +55,6 @@ class MathDatabaseTest extends MediaWikiTestCase {
// set some values
$this->renderer->setTex( self::SOME_TEX );
$this->renderer->setMathml( self::SOME_MATHML );
$this->renderer->setHtml( self::SOME_HTML );
$this->renderer->setOutputHash( self::SOME_OUTPUTHASH );
}
/**
@ -67,7 +65,7 @@ class MathDatabaseTest extends MediaWikiTestCase {
public function testDBBasics() {
$this->setValues();
$this->renderer->writeToDatabase( $this->db );
$renderer2 = new MathTexvc( self::SOME_TEX );
$renderer2 = new MathMathML( self::SOME_TEX );
$this->assertTrue( $renderer2->readFromDatabase(), 'Reading from database failed' );
// comparing the class object does now work due to null values etc.
$this->assertEquals(
@ -77,7 +75,7 @@ class MathDatabaseTest extends MediaWikiTestCase {
$this->renderer->getMathml(), $renderer2->getMathml(), "Check MathML encoding"
);
$this->assertEquals(
$this->renderer->getHtml(), $renderer2->getHtml(), 'test if HTML is the same'
$this->renderer->getHtmlOutput(), $renderer2->getHtmlOutput(), 'test if HTML is the same'
);
}
@ -86,16 +84,16 @@ class MathDatabaseTest extends MediaWikiTestCase {
* @covers MathHooks::onLoadExtensionSchemaUpdates
*/
public function testCreateTable() {
$this->setMwGlobals( 'wgMathValidModes', [ 'png' ] );
$this->db->dropTable( "math", __METHOD__ );
$this->setMwGlobals( 'wgMathValidModes', [ 'mathml' ] );
$this->db->dropTable( "mathoid", __METHOD__ );
$dbu = DatabaseUpdater::newForDB( $this->db );
$dbu->doUpdates( [ "extensions" ] );
$this->expectOutputRegex( '/(.*)Creating math table(.*)/' );
$this->expectOutputRegex( '/(.*)Creating mathoid table(.*)/' );
$this->setValues();
$this->renderer->writeToDatabase();
$res = $this->db->select( "math", "*" );
$res = $this->db->select( "mathoid", "*" );
$row = $res->fetchRow();
$this->assertEquals( 10, count( $row ) );
$this->assertEquals( 16, count( $row ) );
}
/*
@ -107,13 +105,13 @@ class MathDatabaseTest extends MediaWikiTestCase {
$inputHash = $this->renderer->getInputHash();
$this->assertTrue( $this->renderer->isChanged() );
$this->assertTrue( $this->renderer->writeCache(), "Write new entry" );
$res = $this->db->selectField( "math", "math_inputhash",
$res = $this->db->selectField( "mathoid", "math_inputhash",
[ "math_inputhash" => $inputHash ] );
$this->assertTrue( $res !== false, "Check database entry" );
$this->assertTrue( $this->renderer->readFromDatabase(), "Read entry from database" );
$this->assertFalse( $this->renderer->isChanged() );
// modify the database entry manually
$this->db->delete( "math", [ "math_inputhash" => $inputHash ] );
$this->db->delete( "mathoid", [ "math_inputhash" => $inputHash ] );
// the renderer should not be aware of the modification and should not recreate the entry
$this->assertFalse( $this->renderer->writeCache() );
// as a result no entry can be found in the database.

View File

@ -90,17 +90,4 @@ class MathInputCheckRestbaseTest extends MediaWikiTestCase {
$this->assertEquals( $this->GoodObject->getValidTex(), '\\sin \\left({\\frac {1}{2}}x\\right)' );
}
/**
* Test corner cases of texvccheck conversion
* @covers MathInputCheckTexvc::getValidTex
*/
public function testGetValidTexCornerCases() {
$Object = new MathInputCheckTexvc( '\reals' );
$Object->isValid();
$this->assertEquals( "\\mathbb{R} ", $Object->getValidTex() );
$Object = new MathInputCheckTexvc( '\lbrack' ); // Bug: 54624
$Object->isValid();
$this->assertEquals( '\\lbrack ', $Object->getValidTex() );
}
}

View File

@ -1,191 +0,0 @@
<?php
/**
* PHPUnit tests for MathTexvc.
*
* @covers MathTexvc
*
* @group Math
*
* @license GPL-2.0-or-later
*/
class MathTexvcTest extends MediaWikiTestCase {
/**
* Tests behavior of render() upon a cache hit.
* If the rendered object exists in the database cache, MathTexvc
* just generates HTML from it, and skips shelling out to texvc
* entirely.
* @covers MathTexvc::render
*/
function testRenderCacheHit() {
global $wgMathCheckFiles;
// Disable file checks. (This is permissable, because PHPUnit
// will backup / restore global state on test setup / teardown.)
$wgMathCheckFiles = false;
// Create a MathTexvc mock, replacing methods 'readFromDatabase',
// 'callTexvc', and 'doHTMLRender' with test doubles.
$texvc = $this->getMockBuilder( 'MathTexvc' )
->setMethods( [ 'readCache', 'callTexvc', 'getHtmlOutput' ] )
->disableOriginalConstructor()
->getMock();
// When we call render() below, MathTexvc will ...
// ... first check if the item exists in the database cache:
$texvc->expects( $this->once() )
->method( 'readCache' )
->with()
->will( $this->returnValue( true ) );
// ... if cache lookup succeeded, it won't shell out to texvc:
$texvc->expects( $this->never() )
->method( 'callTexvc' );
// ... the output will not be generated if not requested
$texvc->expects( $this->never() )
->method( 'getHtmlOutput' );
$texvc->render();
}
/**
* Test behavior of render() upon cache miss.
* If the rendered object is not in the cache, MathTexvc will shell
* out to texvc to generate it. If texvc succeeds, it'll use the
* result to generate HTML.
* @covers MathTexvc::render
*/
function testRenderCacheMiss() {
$texvc = $this->getMockBuilder( 'MathTexvc' )
->setMethods( [ 'readCache', 'callTexvc', 'getHtmlOutput' ] )
->disableOriginalConstructor()
->getMock();
// When we call render() below, MathTexvc will ...
// ... first look up the item in cache:
$texvc->expects( $this->once() )
->method( 'readCache' )
->will( $this->returnValue( false ) );
// ... on cache miss, MathTexvc will shell out to texvc:
$texvc->expects( $this->once() )
->method( 'callTexvc' )
->will( $this->returnValue( MathTexvc::MW_TEXVC_SUCCESS ) );
// ... the output will not be generated if not requested
$texvc->expects( $this->never() )
->method( 'getHtmlOutput' );
$texvc->render();
}
/**
* Test behavior of render() when texvc fails.
* If texvc returns a value other than MW_TEXVC_SUCCESS, render()
* returns the error object and does not attempt to generate HTML.
* @covers MathTexvc::render
*/
function testRenderTexvcFailure() {
$texvc = $this->getMockBuilder( 'MathTexvc' )
->setMethods( [ 'readCache', 'callTexvc', 'getHtmlOutput' ] )
->disableOriginalConstructor()
->getMock();
// When we call render() below, MathTexvc will ...
// ... first look up the item in cache:
$texvc->expects( $this->any() )
->method( 'readCache' )
->will( $this->returnValue( false ) );
// ... on cache miss, shell out to texvc:
$texvc->expects( $this->once() )
->method( 'callTexvc' )
->will( $this->returnValue( false ) );
// ... if texvc fails, render() will not generate HTML:
$texvc->expects( $this->never() )
->method( 'getHtmlOutput' );
// ... it will return the error result instead:
$this->assertEquals( $texvc->render(), false );
}
/**
* Tests behavior of convertTexvcError
*
* @covers MathTexvc::convertTexvcError
*/
public function testConvertTexvcError() {
$texvc = $this->getMockBuilder( 'MathTexvc' )
->setMethods( null )
->disableOriginalConstructor()
->getMock();
$mathFailure = wfMessage( 'math_failure' )->inContentLanguage()->escaped();
$actualLexing = $texvc->convertTexvcError( 'E' );
$expectedLexing = wfMessage( 'math_lexing_error', '' )->inContentLanguage()->escaped();
$this->assertContains(
$mathFailure, $actualLexing, 'Lexing error contains general math failure message'
);
$this->assertContains(
$expectedLexing, $actualLexing, 'Lexing error contains detailed error for lexing'
);
$actualSyntax = $texvc->convertTexvcError( 'S' );
$expectedSyntax = wfMessage( 'math_syntax_error', '' )->inContentLanguage()->escaped();
$this->assertContains(
$mathFailure, $actualSyntax, 'Syntax error contains general math failure message'
);
$this->assertContains(
$expectedSyntax, $actualSyntax, 'Syntax error contains detailed error for syntax'
);
$unknownFunction = 'figureEightIntegral';
$actualUnknownFunction = $texvc->convertTexvcError( "F$unknownFunction" );
$expectedUnknownFunction = wfMessage(
'math_unknown_function', $unknownFunction
)->inContentLanguage()->escaped();
$this->assertContains( $mathFailure, $actualUnknownFunction,
'Unknown function error contains general math failure message'
);
$this->assertContains( $expectedUnknownFunction, $actualUnknownFunction,
'Unknown function error contains detailed error for unknown function'
);
$actualUnknownError = $texvc->convertTexvcError( 'Q' );
$expectedUnknownError = wfMessage( 'math_unknown_error', '' )->inContentLanguage()->escaped();
$this->assertContains(
$mathFailure, $actualUnknownError, 'Unknown error contains general math failure message'
);
$this->assertContains( $expectedUnknownError, $actualUnknownError,
'Unknown error contains detailed error for unknownError'
);
}
/**
* Test behavior $change when the rendered hash was changed
* @covers MathTexvc::setHash
*/
public function testChangeHash() {
$renderer = $this->getMockBuilder( 'MathTexvc' )
->setMethods( [ 'render', 'getMathTableName' ] )
->disableOriginalConstructor()
->getMock();
$this->assertEquals(
$renderer->isChanged(),
false,
"test if changed is initially false"
);
$renderer->setHash( '0000' );
$this->assertEquals(
$renderer->isChanged(),
true,
"assumes that changing a hash sets changed to true" );
}
}

View File

@ -1,8 +0,0 @@
# Compiled source
*.cmi
*.cmx
*.o
parser.mli
# The binaries
texvccheck

View File

@ -1,65 +0,0 @@
.PHONY: clean all
PREFIX = /usr/local
DESTDIR = /usr
SOURCEDIR = $(PWD)
INSTALL = /usr/bin/install
OBJ= tex.cmo texutil.cmo parser.cmo lexer.cmo texvccheck.cmo \
tex.cmx texutil.cmx parser.cmx lexer.cmx texvccheck.cmx \
lexer.cmi parser.cmi tex.cmi texutil.cmi texvccheck.cmi \
lexer.o parser.o tex.o texutil.o texvccheck.o \
lexer.ml parser.ml parser.mli texvccheck texvccheck.bc util.o \
util.cmo util.cmx util.cmi \
COMMON_NATIVE_OBJ =util.cmx parser.cmx texutil.cmx lexer.cmx
COMMON_BYTECODE_OBJ=util.cmo parser.cmo texutil.cmo lexer.cmo
all: texvccheck
clean:
rm -f $(OBJ)
# Native versions
texvccheck: $(COMMON_NATIVE_OBJ) texvccheck.cmx
ocamlopt -o $@ unix.cmxa $^
# Bytecode version
texvccheck.bc: $(COMMON_BYTECODE_OBJ) texvccheck.cmo
ocamlc -o $@ unix.cma $^
install: texvccheck
$(INSTALL) -dm777 $(DESTDIR)/bin
$(INSTALL) -m777 texvccheck $(DESTDIR)/bin
remove:
rm -f $(DESTDIR)/bin/texvccheck
#
# Pattern rules
#
# .ml source .mli interface
# .cmi compiled interface
# .cmo object .cma library object
# .cmx object file .cmxa library object file
%.ml: %.mll
ocamllex $<
%.mli %.ml: %.mly
ocamlyacc $<
%.cmo: %.ml
ocamlc -c $<
%.cmx: %.ml
ocamlopt -c $<
%.cmi: %.mli
ocamlc -c $<
# Various dependencies
lexer.cmo: parser.cmi tex.cmi texutil.cmi
lexer.cmx: parser.cmx tex.cmi texutil.cmx
parser.cmo: tex.cmi parser.cmi
parser.cmx: tex.cmi parser.cmi
parser.cmi: tex.cmi
texutil.cmo: parser.cmi tex.cmi util.cmo texutil.cmi
texutil.cmx: parser.cmx tex.cmi util.cmx texutil.cmi
texutil.cmi: parser.cmi tex.cmi
texvccheck.cmo: lexer.cmo parser.cmi texutil.cmi util.cmo
texvccheck.cmx: lexer.cmx parser.cmx texutil.cmx util.cmx

View File

@ -1,77 +0,0 @@
== About texvccheck ==
texvc takes the user input validates it and replaces MediaWiki specific functions.
Input data is parsed and scrutinized for safety.
texvc was written by Tomasz Wegrzanowski for use with MediaWiki; it's
included as part of the MediaWiki package (http://www.mediawiki.org) and is
under the GPL license.
texvc-lite, was extracted from the original texvc program in 2013 by
Moritz Schubotz and uses only the sanitizing and customization part.
The list of all commands can be viewed by browsing the source files.
Most commands are listed at
http://sdrv.ms/15w2gVw
there is also a tool for convenient whitelisting of special commands
that are used in local wikis.
Please report bugs at: https://bugzilla.wikimedia.org/
with "MediaWiki extensions" as product and "Math" as component.
== Setup ==
=== Requirements ===
OCaml 3.06 or later is required to compile texvc; this can be acquired from
http://caml.inria.fr/ if your system doesn't have it available.
The makefile requires GNU make.
In Ubuntu Precise, all dependencies can be installed using:
$ sudo apt-get install ocaml
=== Installation ===
Run 'make' (or 'gmake' if GNU make is not your default make). This should
produce the texvccheck executable.
By default,
MediaWiki will search in this directory for texvc, if you moved it elsewhere,
you'll have to modify $wgTexvc and set it to the path of the texvc executable.
== Usage ==
Normally texvc is called from MediaWiki's Math modules and everything
Just Works. It can be run manually for testing or for use in another app.
=== Command-line parameters ===
texvccheck '\TeX input string'
Be sure to properly quote the TeX code!
Example:
texvc "y=x+2"
=== Output format ===
The output is the sanitized and customized tex string.
texvc output format is like this:
+%s ok
S syntax error
E lexing error
F%s unknown function %s
- other error
== Hacking ==
Before you start hacking on the math package its good to know the workflow,
which is basically:
1. texvc gets called by Math/Math.body.php (check out the line beginning with "$cmd")
2. texvc does its magic, which is basically to check for invalid latex code.
3. texvc takes the user input validates it and replaces MediaWiki specific functions

View File

@ -1,119 +0,0 @@
{
open Parser
open Tex
}
let space = [' ' '\t' '\n' '\r']
let alpha = ['a'-'z' 'A'-'Z']
let literal_id = ['a'-'z' 'A'-'Z']
let literal_mn = ['0'-'9']
let literal_uf_lt = [',' ':' ';' '?' '!' '\'']
let delimiter_uf_lt = ['(' ')' '.']
let literal_uf_op = ['+' '-' '*' '=']
let delimiter_uf_op = ['/' '|']
let boxchars = ['0'-'9' 'a'-'z' 'A'-'Z' '+' '-' '*' ',' '=' '(' ')' ':' '/' ';' '?' '.' '!' '\'' '`' ' ' '\128'-'\255']
let aboxchars = ['0'-'9' 'a'-'z' 'A'-'Z' '+' '-' '*' ',' '=' '(' ')' ':' '/' ';' '?' '.' '!' '\'' '`' ' ']
let latex_function_names = "arccos" | "arcsin" | "arctan" | "arg" | "cos" | "cosh" | "cot" | "coth" | "csc"| "deg" | "det" | "dim" | "exp" | "gcd" | "hom" | "inf" | "ker" | "lg" | "lim" | "liminf" | "limsup" | "ln" | "log" | "max" | "min" | "Pr" | "sec" | "sin" | "sinh" | "sup" | "tan" | "tanh"
let mediawiki_function_names = "arccot" | "arcsec" | "arccsc" | "sgn" | "sen"
rule token = parse
space + { token lexbuf }
| "\\text" space * '{' aboxchars + '}'
{ let str = Lexing.lexeme lexbuf in
let n = String.index str '{' + 1 in
BOX ("\\text", String.sub str n (String.length str - n - 1)) }
| "\\mbox" space * '{' aboxchars + '}'
{ let str = Lexing.lexeme lexbuf in
let n = String.index str '{' + 1 in
BOX ("\\mbox", String.sub str n (String.length str - n - 1)) }
| "\\hbox" space * '{' aboxchars + '}'
{ let str = Lexing.lexeme lexbuf in
let n = String.index str '{' + 1 in
BOX ("\\hbox", String.sub str n (String.length str - n - 1)) }
| "\\vbox" space * '{' aboxchars + '}'
{ let str = Lexing.lexeme lexbuf in
let n = String.index str '{' + 1 in
BOX ("\\vbox", String.sub str n (String.length str - n - 1)) }
| "\\text" space * '{' boxchars + '}'
{ let str = Lexing.lexeme lexbuf in
let n = String.index str '{' + 1 in
BOX ("\\text", String.sub str n (String.length str - n - 1)) }
| "\\mbox" space * '{' boxchars + '}'
{ let str = Lexing.lexeme lexbuf in
let n = String.index str '{' + 1 in
BOX ("\\mbox", String.sub str n (String.length str - n - 1)) }
| "\\hbox" space * '{' boxchars + '}'
{ let str = Lexing.lexeme lexbuf in
let n = String.index str '{' + 1 in
BOX ("\\hbox", String.sub str n (String.length str - n - 1)) }
| "\\vbox" space * '{' boxchars + '}'
{ let str = Lexing.lexeme lexbuf in
let n = String.index str '{' + 1 in
BOX ("\\vbox", String.sub str n (String.length str - n - 1)) }
| literal_id { let str = Lexing.lexeme lexbuf in LITERAL (TEX_ONLY str) }
| literal_mn { let str = Lexing.lexeme lexbuf in LITERAL (TEX_ONLY str) }
| literal_uf_lt { let str = Lexing.lexeme lexbuf in LITERAL (TEX_ONLY str) }
| delimiter_uf_lt { let str = Lexing.lexeme lexbuf in DELIMITER (TEX_ONLY str) }
| "-" { let str = Lexing.lexeme lexbuf in LITERAL (TEX_ONLY str)}
| literal_uf_op { let str = Lexing.lexeme lexbuf in LITERAL (TEX_ONLY str) }
| delimiter_uf_op { let str = Lexing.lexeme lexbuf in DELIMITER (TEX_ONLY str) }
| "\\operatorname" { FUN_AR1nb "\\operatorname" }
| "\\sqrt" space * "[" { FUN_AR1opt "\\sqrt" }
| "\\xleftarrow" space * "[" { FUN_AR1opt "\\xleftarrow" }
| "\\xrightarrow" space * "[" { FUN_AR1opt "\\xrightarrow" }
| "\\" (latex_function_names as name) space * "(" { LITERAL (TEX_ONLY ("\\" ^ name ^ "(")) }
| "\\" (latex_function_names as name) space * "[" { LITERAL (TEX_ONLY ("\\" ^ name ^ "[") )}
| "\\" (latex_function_names as name) space * "\\{" { LITERAL (TEX_ONLY ("\\" ^ name ^ "\\{")) }
| "\\" (latex_function_names as name) space * { LITERAL (TEX_ONLY("\\" ^ name ^ " ")) }
| "\\" (mediawiki_function_names as name) space * "(" { ( LITERAL (TEX_ONLY ("\\operatorname{" ^ name ^ "}("))) }
| "\\" (mediawiki_function_names as name) space * "[" { ( LITERAL (TEX_ONLY ("\\operatorname{" ^ name ^ "}[")))}
| "\\" (mediawiki_function_names as name) space * "\\{" { ( LITERAL (TEX_ONLY ("\\operatorname{" ^ name ^ "}\\{")))}
| "\\" (mediawiki_function_names as name) space * { ( LITERAL (TEX_ONLY ("\\operatorname{" ^ name ^ "} "))) }
| "\\" alpha + { Texutil.find (Lexing.lexeme lexbuf) }
| "\\," { LITERAL (TEX_ONLY "\\,") }
| "\\ " { LITERAL (TEX_ONLY "\\ ") }
| "\\;" { LITERAL (TEX_ONLY "\\;") }
| "\\!" { LITERAL (TEX_ONLY "\\!") }
| "\\{" { DELIMITER (TEX_ONLY "\\{") }
| "\\}" { DELIMITER (TEX_ONLY "\\}") }
| "\\|" { DELIMITER (TEX_ONLY "\\|") }
| "\\_" { LITERAL (TEX_ONLY "\\_") }
| "\\#" { LITERAL (TEX_ONLY "\\#") }
| "\\%" { LITERAL (TEX_ONLY "\\%") }
| "\\$" { LITERAL (TEX_ONLY "\\$") }
| "\\&" { LITERAL (TEX_ONLY "\\&") }
| "&" { NEXT_CELL }
| "\\\\" { NEXT_ROW }
| "\\begin{matrix}" { BEGIN__MATRIX }
| "\\end{matrix}" { END__MATRIX }
| "\\begin{pmatrix}" { BEGIN_PMATRIX }
| "\\end{pmatrix}" { END_PMATRIX }
| "\\begin{bmatrix}" { BEGIN_BMATRIX }
| "\\end{bmatrix}" { END_BMATRIX }
| "\\begin{Bmatrix}" { BEGIN_BBMATRIX }
| "\\end{Bmatrix}" { END_BBMATRIX }
| "\\begin{vmatrix}" { BEGIN_VMATRIX }
| "\\end{vmatrix}" { END_VMATRIX }
| "\\begin{Vmatrix}" { BEGIN_VVMATRIX }
| "\\end{Vmatrix}" { END_VVMATRIX }
| "\\begin{array}" { BEGIN_ARRAY }
| "\\end{array}" { END_ARRAY }
| "\\begin{align}" { BEGIN_ALIGN }
| "\\end{align}" { END_ALIGN }
| "\\begin{alignat}" { BEGIN_ALIGNAT }
| "\\end{alignat}" { END_ALIGNAT }
| "\\begin{smallmatrix}" { BEGIN_SMALLMATRIX }
| "\\end{smallmatrix}" { END_SMALLMATRIX }
| "\\begin{cases}" { BEGIN_CASES }
| "\\end{cases}" { END_CASES }
| '>' { LITERAL (TEX_ONLY ">") }
| '<' { LITERAL (TEX_ONLY "<") }
| '%' { LITERAL (TEX_ONLY "\\%") }
| '$' { LITERAL (TEX_ONLY "\\$") }
| '~' { LITERAL (TEX_ONLY "~") }
| '[' { DELIMITER (TEX_ONLY "[") }
| ']' { SQ_CLOSE }
| '{' { CURLY_OPEN }
| '}' { CURLY_CLOSE }
| '^' { SUP }
| '_' { SUB }
| eof { EOF }

View File

@ -1,118 +0,0 @@
%{
open Tex
let sq_close_ri = HTMLABLEC(FONT_UFH,"]", "]")
%}
%token <Tex.render_t> LITERAL DELIMITER
%token <string> FUN_AR2 FUN_INFIX FUN_AR1 DECL FUN_AR1nb FUN_AR1opt BIG FUN_AR2nb
%token <string*string> BOX
%token <string*(string*string)> FUN_AR1hl
%token <string*Tex.font_force> FUN_AR1hf DECLh
%token <string*(Tex.t->Tex.t->string*string*string)> FUN_AR2h
%token <string*(Tex.t list->Tex.t list->string*string*string)> FUN_INFIXh
%token EOF CURLY_OPEN CURLY_CLOSE SUB SUP SQ_CLOSE NEXT_CELL NEXT_ROW
%token BEGIN__MATRIX BEGIN_PMATRIX BEGIN_BMATRIX BEGIN_BBMATRIX BEGIN_VMATRIX BEGIN_VVMATRIX BEGIN_CASES BEGIN_ARRAY BEGIN_ALIGN BEGIN_ALIGNAT BEGIN_SMALLMATRIX
%token END__MATRIX END_PMATRIX END_BMATRIX END_BBMATRIX END_VMATRIX END_VVMATRIX END_CASES END_ARRAY END_ALIGN END_ALIGNAT END_SMALLMATRIX
%token LEFT RIGHT
%type <Tex.t list> tex_expr
%start tex_expr
%%
tex_expr:
expr EOF { $1 }
| ne_expr FUN_INFIX ne_expr EOF
{ [TEX_INFIX($2,$1,$3)] }
| ne_expr FUN_INFIXh ne_expr EOF
{ let t,h=$2 in [TEX_INFIXh(t,h,$1,$3)] }
expr:
/* */ { [] }
| ne_expr { $1 }
ne_expr:
lit_aq expr { $1 :: $2 }
| litsq_aq expr { $1 :: $2 }
| DECLh expr { let t,h = $1 in [TEX_DECLh(t,h,$2)] }
litsq_aq:
litsq_zq { $1 }
| litsq_dq { let base,downi = $1 in TEX_DQ(base,downi) }
| litsq_uq { let base,upi = $1 in TEX_UQ(base,upi)}
| litsq_fq { $1 }
litsq_fq:
litsq_dq SUP lit { let base,downi = $1 in TEX_FQ(base,downi,$3) }
| litsq_uq SUB lit { let base,upi = $1 in TEX_FQ(base,$3,upi) }
litsq_uq:
litsq_zq SUP lit { $1,$3 }
litsq_dq:
litsq_zq SUB lit { $1,$3 }
litsq_zq:
SQ_CLOSE { TEX_LITERAL sq_close_ri }
expr_nosqc:
/* */ { [] }
| lit_aq expr_nosqc { $1 :: $2 }
lit_aq:
lit { $1 }
| lit_dq { let base,downi = $1 in TEX_DQ(base,downi) }
| lit_uq { let base,upi = $1 in TEX_UQ(base,upi)}
| lit_dqn { TEX_DQN($1) }
| lit_uqn { TEX_UQN($1) }
| lit_fq { $1 }
lit_fq:
lit_dq SUP lit { let base,downi = $1 in TEX_FQ(base,downi,$3) }
| lit_uq SUB lit { let base,upi = $1 in TEX_FQ(base,$3,upi) }
| lit_dqn SUP lit { TEX_FQN($1, $3) }
lit_uq:
lit SUP lit { $1,$3 }
lit_dq:
lit SUB lit { $1,$3 }
lit_uqn:
SUP lit { $2 }
lit_dqn:
SUB lit { $2 }
left:
LEFT DELIMITER { $2 }
| LEFT SQ_CLOSE { sq_close_ri }
right:
RIGHT DELIMITER { $2 }
| RIGHT SQ_CLOSE { sq_close_ri }
lit:
LITERAL { TEX_LITERAL $1 }
| DELIMITER { TEX_LITERAL $1 }
| BIG DELIMITER { TEX_BIG ($1,$2) }
| BIG SQ_CLOSE { TEX_BIG ($1,sq_close_ri) }
| left expr right { TEX_LR ($1,$3,$2) }
| FUN_AR1 lit { TEX_FUN1($1,$2) }
| FUN_AR1nb lit { TEX_FUN1nb($1,$2) }
| FUN_AR1hl lit { let t,h=$1 in TEX_FUN1hl(t,h,$2) }
| FUN_AR1hf lit { let t,h=$1 in TEX_FUN1hf(t,h,$2) }
| FUN_AR1opt expr_nosqc SQ_CLOSE lit { TEX_FUN2sq($1,TEX_CURLY $2,$4) }
| FUN_AR2 lit lit { TEX_FUN2($1,$2,$3) }
| FUN_AR2nb lit lit { TEX_FUN2nb($1,$2,$3) }
| FUN_AR2h lit lit { let t,h=$1 in TEX_FUN2h(t,h,$2,$3) }
| BOX { let bt,s = $1 in TEX_BOX (bt,s) }
| CURLY_OPEN expr CURLY_CLOSE
{ TEX_CURLY $2 }
| CURLY_OPEN ne_expr FUN_INFIX ne_expr CURLY_CLOSE
{ TEX_INFIX($3,$2,$4) }
| CURLY_OPEN ne_expr FUN_INFIXh ne_expr CURLY_CLOSE
{ let t,h=$3 in TEX_INFIXh(t,h,$2,$4) }
| BEGIN__MATRIX matrix END__MATRIX { TEX_MATRIX ("matrix", $2) }
| BEGIN_PMATRIX matrix END_PMATRIX { TEX_MATRIX ("pmatrix", $2) }
| BEGIN_BMATRIX matrix END_BMATRIX { TEX_MATRIX ("bmatrix", $2) }
| BEGIN_BBMATRIX matrix END_BBMATRIX { TEX_MATRIX ("Bmatrix", $2) }
| BEGIN_VMATRIX matrix END_VMATRIX { TEX_MATRIX ("vmatrix", $2) }
| BEGIN_VVMATRIX matrix END_VVMATRIX { TEX_MATRIX ("Vmatrix", $2) }
| BEGIN_ARRAY matrix END_ARRAY { TEX_MATRIX ("array", $2) }
| BEGIN_ALIGN matrix END_ALIGN { TEX_MATRIX ("aligned", $2) }
| BEGIN_ALIGNAT matrix END_ALIGNAT { TEX_MATRIX ("alignedat", $2) }
| BEGIN_SMALLMATRIX matrix END_SMALLMATRIX { TEX_MATRIX ("smallmatrix", $2) }
| BEGIN_CASES matrix END_CASES { TEX_MATRIX ("cases", $2) }
matrix:
line { [$1] }
| line NEXT_ROW matrix { $1::$3 }
line:
expr { [$1] }
| expr NEXT_CELL line { $1::$3 }
;;

View File

@ -1,48 +0,0 @@
type font_force =
FONTFORCE_IT
| FONTFORCE_RM
type font_class =
FONT_IT (* IT default, may be forced to be RM *)
| FONT_RM (* RM default, may be forced to be IT *)
| FONT_UF (* not affected by IT/RM setting *)
| FONT_RTI (* RM - any, IT - not available in HTML *)
| FONT_UFH (* in TeX UF, in HTML RM *)
type math_class =
MN
| MI
| MO
type render_t =
HTMLABLEC of font_class * string * string
| HTMLABLEM of font_class * string * string
| HTMLABLE of font_class * string * string
| MHTMLABLEC of font_class * string * string * math_class * string
| HTMLABLE_BIG of string * string
| TEX_ONLY of string
type t =
TEX_LITERAL of render_t
| TEX_CURLY of t list
| TEX_FQ of t * t * t
| TEX_DQ of t * t
| TEX_UQ of t * t
| TEX_FQN of t * t
| TEX_DQN of t
| TEX_UQN of t
| TEX_LR of render_t * render_t * t list
| TEX_BOX of string * string
| TEX_BIG of string * render_t
| TEX_FUN1 of string * t
| TEX_FUN1nb of string * t
| TEX_FUN2 of string * t * t
| TEX_FUN2nb of string * t * t
| TEX_INFIX of string * t list * t list
| TEX_FUN2sq of string * t * t
| TEX_FUN1hl of string * (string * string) * t
| TEX_FUN1hf of string * font_force * t
| TEX_FUN2h of string * (t -> t -> string * string * string) * t * t
| TEX_INFIXh of string * (t list -> t list -> string * string * string) * t list * t list
| TEX_MATRIX of string * t list list list
| TEX_DECLh of string * font_force * t list

View File

@ -1,712 +0,0 @@
(* vim: set sw=8 ts=8 et: *)
open Parser
open Tex
open Util
let tex_part = function
HTMLABLE (_,t,_) -> t
| HTMLABLEM (_,t,_) -> t
| HTMLABLEC (_,t,_) -> t
| MHTMLABLEC (_,t,_,_,_) -> t
| HTMLABLE_BIG (t,_) -> t
| TEX_ONLY t -> t
let rec render_tex = function
TEX_FQ (a,b,c) -> (render_tex a) ^ "_{" ^ (render_tex b) ^ "}^{" ^ (render_tex c) ^ "}"
| TEX_DQ (a,b) -> (render_tex a) ^ "_{" ^ (render_tex b) ^ "}"
| TEX_UQ (a,b) -> (render_tex a) ^ "^{" ^ (render_tex b) ^ "}"
| TEX_FQN (a,b) -> "_{" ^ (render_tex a) ^ "}^{" ^ (render_tex b) ^ "}"
| TEX_DQN (a) -> "_{" ^ (render_tex a) ^ "}"
| TEX_UQN (a) -> "^{" ^ (render_tex a) ^ "}"
| TEX_LITERAL s -> tex_part s
| TEX_FUN1 (f,a) -> "{" ^ f ^ " " ^ (render_tex a) ^ "}"
| TEX_FUN1nb (f,a) -> f ^ " " ^ (render_tex a)
| TEX_FUN1hl (f,_,a) -> "{" ^ f ^ " " ^ (render_tex a) ^ "}"
| TEX_FUN1hf (f,_,a) -> "{" ^ f ^ " " ^ (render_tex a) ^ "}"
| TEX_DECLh (f,_,a) -> "{" ^ f ^ "{" ^ (mapjoin render_tex a) ^ "}}"
| TEX_FUN2 (f,a,b) -> "{" ^ f ^ " " ^ (render_tex a) ^ (render_tex b) ^ "}"
| TEX_FUN2h (f,_,a,b) -> "{" ^ f ^ " " ^ (render_tex a) ^ (render_tex b) ^ "}"
| TEX_FUN2nb (f,a,b) -> f ^ (render_tex a) ^ (render_tex b)
| TEX_FUN2sq (f,a,b) -> "{" ^ f ^ "[ " ^ (render_tex a) ^ "]" ^ (render_tex b) ^ "}"
| TEX_CURLY (tl) -> "{" ^ (mapjoin render_tex tl) ^ "}"
| TEX_INFIX (s,ll,rl) -> "{" ^ (mapjoin render_tex ll) ^ " " ^ s ^ "" ^ (mapjoin render_tex rl) ^ "}"
| TEX_INFIXh (s,_,ll,rl) -> "{" ^ (mapjoin render_tex ll) ^ " " ^ s ^ "" ^ (mapjoin render_tex rl) ^ "}"
| TEX_BOX (bt,s) -> "{"^bt^"{" ^ s ^ "}}"
| TEX_BIG (bt,d) -> "{"^bt^(tex_part d)^"}"
| TEX_MATRIX (t,rows) -> "{\\begin{"^t^"}"^(mapjoine "\\\\" (mapjoine "&" (mapjoin render_tex)) rows)^"\\end{"^t^"}}"
| TEX_LR (l,r,tl) -> "\\left"^(tex_part l)^(mapjoin render_tex tl)^"\\right"^(tex_part r)
(* Turn that into hash table lookup *)
exception Illegal_tex_function of string
let find cmd = match cmd with
"\\aleph"
| "\\alpha"
| "\\amalg"
| "\\And"
| "\\angle"
| "\\approx"
| "\\approxeq"
| "\\ast"
| "\\asymp"
| "\\backepsilon"
| "\\backprime"
| "\\backsim"
| "\\backsimeq"
| "\\barwedge"
| "\\Bbbk"
| "\\because"
| "\\beta"
| "\\beth"
| "\\between"
| "\\bigcap"
| "\\bigcirc"
| "\\bigcup"
| "\\bigodot"
| "\\bigoplus"
| "\\bigotimes"
| "\\bigsqcup"
| "\\bigstar"
| "\\bigtriangledown"
| "\\bigtriangleup"
| "\\biguplus"
| "\\bigvee"
| "\\bigwedge"
| "\\blacklozenge"
| "\\blacksquare"
| "\\blacktriangle"
| "\\blacktriangledown"
| "\\blacktriangleleft"
| "\\blacktriangleright"
| "\\bot"
| "\\bowtie"
| "\\Box"
| "\\boxdot"
| "\\boxminus"
| "\\boxplus"
| "\\boxtimes"
| "\\bullet"
| "\\bumpeq"
| "\\Bumpeq"
| "\\cap"
| "\\Cap"
| "\\cdot"
| "\\cdots"
| "\\centerdot"
| "\\checkmark"
| "\\chi"
| "\\circ"
| "\\circeq"
| "\\circlearrowleft"
| "\\circlearrowright"
| "\\circledast"
| "\\circledcirc"
| "\\circleddash"
| "\\circledS"
| "\\clubsuit"
| "\\colon"
| "\\color"
| "\\complement"
| "\\cong"
| "\\coprod"
| "\\cup"
| "\\Cup"
| "\\curlyeqprec"
| "\\curlyeqsucc"
| "\\curlyvee"
| "\\curlywedge"
| "\\curvearrowleft"
| "\\curvearrowright"
| "\\dagger"
| "\\daleth"
| "\\dashv"
| "\\ddagger"
| "\\ddots"
| "\\definecolor"
| "\\delta"
| "\\Delta"
| "\\diagdown"
| "\\diagup"
| "\\diamond"
| "\\Diamond"
| "\\diamondsuit"
| "\\digamma"
| "\\displaystyle"
| "\\div"
| "\\divideontimes"
| "\\doteq"
| "\\doteqdot"
| "\\dotplus"
| "\\dots"
| "\\dotsb"
| "\\dotsc"
| "\\dotsi"
| "\\dotsm"
| "\\dotso"
| "\\doublebarwedge"
| "\\downdownarrows"
| "\\downharpoonleft"
| "\\downharpoonright"
| "\\ell"
| "\\emptyset"
| "\\epsilon"
| "\\eqcirc"
| "\\eqsim"
| "\\eqslantgtr"
| "\\eqslantless"
| "\\equiv"
| "\\eta"
| "\\eth"
| "\\exists"
| "\\fallingdotseq"
| "\\Finv"
| "\\flat"
| "\\forall"
| "\\frown"
| "\\Game"
| "\\gamma"
| "\\Gamma"
| "\\geq"
| "\\geqq"
| "\\geqslant"
| "\\gets"
| "\\gg"
| "\\ggg"
| "\\gimel"
| "\\gnapprox"
| "\\gneq"
| "\\gneqq"
| "\\gnsim"
| "\\gtrapprox"
| "\\gtrdot"
| "\\gtreqless"
| "\\gtreqqless"
| "\\gtrless"
| "\\gtrsim"
| "\\gvertneqq"
| "\\hbar"
| "\\heartsuit"
| "\\hline"
| "\\hookleftarrow"
| "\\hookrightarrow"
| "\\hslash"
| "\\iff"
| "\\iiiint"
| "\\iiint"
| "\\iint"
| "\\Im"
| "\\imath"
| "\\implies"
| "\\in"
| "\\infty"
| "\\injlim"
| "\\int"
| "\\intercal"
| "\\iota"
| "\\jmath"
| "\\kappa"
| "\\lambda"
| "\\Lambda"
| "\\land"
| "\\ldots"
| "\\leftarrow"
| "\\Leftarrow"
| "\\leftarrowtail"
| "\\leftharpoondown"
| "\\leftharpoonup"
| "\\leftleftarrows"
| "\\leftrightarrow"
| "\\Leftrightarrow"
| "\\leftrightarrows"
| "\\leftrightharpoons"
| "\\leftrightsquigarrow"
| "\\leftthreetimes"
| "\\leq"
| "\\leqq"
| "\\leqslant"
| "\\lessapprox"
| "\\lessdot"
| "\\lesseqgtr"
| "\\lesseqqgtr"
| "\\lessgtr"
| "\\lesssim"
| "\\limits"
| "\\ll"
| "\\Lleftarrow"
| "\\lll"
| "\\lnapprox"
| "\\lneq"
| "\\lneqq"
| "\\lnot"
| "\\lnsim"
| "\\longleftarrow"
| "\\Longleftarrow"
| "\\longleftrightarrow"
| "\\Longleftrightarrow"
| "\\longmapsto"
| "\\longrightarrow"
| "\\Longrightarrow"
| "\\looparrowleft"
| "\\looparrowright"
| "\\lor"
| "\\lozenge"
| "\\Lsh"
| "\\ltimes"
| "\\lVert"
| "\\lvertneqq"
| "\\mapsto"
| "\\measuredangle"
| "\\mho"
| "\\mid"
| "\\mod"
| "\\models"
| "\\mp"
| "\\mu"
| "\\multimap"
| "\\nabla"
| "\\natural"
| "\\ncong"
| "\\nearrow"
| "\\neg"
| "\\neq"
| "\\nexists"
| "\\ngeq"
| "\\ngeqq"
| "\\ngeqslant"
| "\\ngtr"
| "\\ni"
| "\\nleftarrow"
| "\\nLeftarrow"
| "\\nleftrightarrow"
| "\\nLeftrightarrow"
| "\\nleq"
| "\\nleqq"
| "\\nleqslant"
| "\\nless"
| "\\nmid"
| "\\nolimits"
| "\\not"
| "\\notin"
| "\\nparallel"
| "\\nprec"
| "\\npreceq"
| "\\nrightarrow"
| "\\nRightarrow"
| "\\nshortmid"
| "\\nshortparallel"
| "\\nsim"
| "\\nsubseteq"
| "\\nsubseteqq"
| "\\nsucc"
| "\\nsucceq"
| "\\nsupseteq"
| "\\nsupseteqq"
| "\\ntriangleleft"
| "\\ntrianglelefteq"
| "\\ntriangleright"
| "\\ntrianglerighteq"
| "\\nu"
| "\\nvdash"
| "\\nVdash"
| "\\nvDash"
| "\\nVDash"
| "\\nwarrow"
| "\\odot"
| "\\oint"
| "\\omega"
| "\\Omega"
| "\\ominus"
| "\\oplus"
| "\\oslash"
| "\\otimes"
| "\\P"
| "\\pagecolor"
| "\\parallel"
| "\\partial"
| "\\perp"
| "\\phi"
| "\\Phi"
| "\\pi"
| "\\Pi"
| "\\pitchfork"
| "\\pm"
| "\\prec"
| "\\precapprox"
| "\\preccurlyeq"
| "\\preceq"
| "\\precnapprox"
| "\\precneqq"
| "\\precnsim"
| "\\precsim"
| "\\prime"
| "\\prod"
| "\\projlim"
| "\\propto"
| "\\psi"
| "\\Psi"
| "\\qquad"
| "\\quad"
| "\\Re"
| "\\rho"
| "\\rightarrow"
| "\\Rightarrow"
| "\\rightarrowtail"
| "\\rightharpoondown"
| "\\rightharpoonup"
| "\\rightleftarrows"
| "\\rightrightarrows"
| "\\rightsquigarrow"
| "\\rightthreetimes"
| "\\risingdotseq"
| "\\Rrightarrow"
| "\\Rsh"
| "\\rtimes"
| "\\rVert"
| "\\S"
| "\\scriptscriptstyle"
| "\\scriptstyle"
| "\\searrow"
| "\\setminus"
| "\\sharp"
| "\\shortmid"
| "\\shortparallel"
| "\\sigma"
| "\\Sigma"
| "\\sim"
| "\\simeq"
| "\\smallfrown"
| "\\smallsetminus"
| "\\smallsmile"
| "\\smile"
| "\\spadesuit"
| "\\sphericalangle"
| "\\sqcap"
| "\\sqcup"
| "\\sqsubset"
| "\\sqsubseteq"
| "\\sqsupset"
| "\\sqsupseteq"
| "\\square"
| "\\star"
| "\\subset"
| "\\Subset"
| "\\subseteq"
| "\\subseteqq"
| "\\subsetneq"
| "\\subsetneqq"
| "\\succ"
| "\\succapprox"
| "\\succcurlyeq"
| "\\succeq"
| "\\succnapprox"
| "\\succneqq"
| "\\succnsim"
| "\\succsim"
| "\\sum"
| "\\supset"
| "\\Supset"
| "\\supseteq"
| "\\supseteqq"
| "\\supsetneq"
| "\\supsetneqq"
| "\\surd"
| "\\swarrow"
| "\\tau"
| "\\textstyle"
| "\\therefore"
| "\\theta"
| "\\Theta"
| "\\thickapprox"
| "\\thicksim"
| "\\times"
| "\\to"
| "\\top"
| "\\triangle"
| "\\triangledown"
| "\\triangleleft"
| "\\trianglelefteq"
| "\\triangleq"
| "\\triangleright"
| "\\trianglerighteq"
| "\\upharpoonleft"
| "\\upharpoonright"
| "\\uplus"
| "\\upsilon"
| "\\Upsilon"
| "\\upuparrows"
| "\\varepsilon"
| "\\varinjlim"
| "\\varkappa"
| "\\varliminf"
| "\\varlimsup"
| "\\varnothing"
| "\\varphi"
| "\\varpi"
| "\\varprojlim"
| "\\varpropto"
| "\\varrho"
| "\\varsigma"
| "\\varsubsetneq"
| "\\varsubsetneqq"
| "\\varsupsetneq"
| "\\varsupsetneqq"
| "\\vartheta"
| "\\vartriangle"
| "\\vartriangleleft"
| "\\vartriangleright"
| "\\vdash"
| "\\Vdash"
| "\\vDash"
| "\\vdots"
| "\\vee"
| "\\veebar"
| "\\vline"
| "\\Vvdash"
| "\\wedge"
| "\\wp"
| "\\wr"
| "\\xi"
| "\\Xi"
| "\\zeta"
-> LITERAL ( TEX_ONLY( cmd ^ " " ) )
| "\\big"
| "\\Big"
| "\\bigg"
| "\\Bigg"
| "\\biggl"
| "\\Biggl"
| "\\biggr"
| "\\Biggr"
| "\\bigl"
| "\\Bigl"
| "\\bigr"
| "\\Bigr"
-> BIG ( cmd ^ " " )
| "\\backslash"
| "\\downarrow"
| "\\Downarrow"
| "\\langle"
| "\\lbrace"
| "\\lceil"
| "\\lfloor"
| "\\llcorner"
| "\\lrcorner"
| "\\rangle"
| "\\rbrace"
| "\\rceil"
| "\\rfloor"
| "\\rightleftharpoons"
| "\\twoheadleftarrow"
| "\\twoheadrightarrow"
| "\\ulcorner"
| "\\uparrow"
| "\\Uparrow"
| "\\updownarrow"
| "\\Updownarrow"
| "\\urcorner"
| "\\Vert"
| "\\vert"
| "\\lbrack"
| "\\rbrack"
-> DELIMITER( TEX_ONLY( cmd ^ " ") )
| "\\acute"
| "\\bar"
| "\\bcancel"
| "\\bmod"
| "\\boldsymbol"
| "\\breve"
| "\\cancel"
| "\\check"
| "\\ddot"
| "\\dot"
| "\\emph"
| "\\grave"
| "\\hat"
| "\\mathbb"
| "\\mathbf"
| "\\mathbin"
| "\\mathcal"
| "\\mathclose"
| "\\mathfrak"
| "\\mathit"
| "\\mathop"
| "\\mathopen"
| "\\mathord"
| "\\mathpunct"
| "\\mathrel"
| "\\mathrm"
| "\\mathsf"
| "\\mathtt"
| "\\operatorname"
| "\\overleftarrow"
| "\\overleftrightarrow"
| "\\overline"
| "\\overrightarrow"
| "\\pmod"
| "\\sqrt"
| "\\textbf"
| "\\textit"
| "\\textrm"
| "\\textsf"
| "\\texttt"
| "\\tilde"
| "\\underline"
| "\\vec"
| "\\widehat"
| "\\widetilde"
| "\\xcancel"
| "\\xleftarrow"
| "\\xrightarrow"
-> FUN_AR1( cmd ^ " " )
| "\\binom"
| "\\cancelto"
| "\\cfrac"
| "\\dbinom"
| "\\dfrac"
| "\\frac"
| "\\overset"
| "\\stackrel"
| "\\tbinom"
| "\\tfrac"
| "\\underset"
-> FUN_AR2( cmd ^ " " )
| "\\atop"
| "\\choose"
| "\\over"
-> FUN_INFIX( cmd ^ " " )
| "\\AA"
| "\\Coppa"
| "\\coppa"
| "\\Digamma"
| "\\euro"
| "\\geneuro"
| "\\geneuronarrow"
| "\\geneurowide"
| "\\Koppa"
| "\\koppa"
| "\\officialeuro"
| "\\Sampi"
| "\\sampi"
| "\\Stigma"
| "\\stigma"
| "\\textvisiblespace"
| "\\varstigma"
-> LITERAL ( TEX_ONLY( "\\mbox{" ^ cmd ^ "} " ) )
| "\\C" -> LITERAL ( TEX_ONLY( "\\mathbb{C}" ^ " " ) )
| "\\H" -> LITERAL ( TEX_ONLY( "\\mathbb{H}" ^ " " ) )
| "\\N" -> LITERAL ( TEX_ONLY( "\\mathbb{N}" ^ " " ) )
| "\\Q" -> LITERAL ( TEX_ONLY( "\\mathbb{Q}" ^ " " ) )
| "\\R" -> LITERAL ( TEX_ONLY( "\\mathbb{R}" ^ " " ) )
| "\\Z" -> LITERAL ( TEX_ONLY( "\\mathbb{Z}" ^ " " ) )
| "\\darr" -> DELIMITER( TEX_ONLY( "\\downarrow" ^ " " ) )
| "\\dArr" -> DELIMITER( TEX_ONLY( "\\Downarrow" ^ " " ) )
| "\\Darr" -> DELIMITER( TEX_ONLY( "\\Downarrow" ^ " " ) )
| "\\lang" -> DELIMITER( TEX_ONLY( "\\langle" ^ " " ) )
| "\\rang" -> DELIMITER( TEX_ONLY( "\\rangle" ^ " " ) )
| "\\uarr" -> DELIMITER( TEX_ONLY( "\\uparrow" ^ " " ) )
| "\\uArr" -> DELIMITER( TEX_ONLY( "\\Uparrow" ^ " " ) )
| "\\Uarr" -> DELIMITER( TEX_ONLY( "\\Uparrow" ^ " " ) )
| "\\Bbb" -> FUN_AR1( "\\mathbb" ^ " " )
| "\\bold" -> FUN_AR1( "\\mathbf" ^ " " )
| "\\alef" -> LITERAL ( TEX_ONLY( "\\aleph" ^ " " ) )
| "\\alefsym" -> LITERAL ( TEX_ONLY( "\\aleph" ^ " " ) )
| "\\Alpha" -> LITERAL ( TEX_ONLY( "\\mathrm{A}" ^ " " ) )
| "\\and" -> LITERAL ( TEX_ONLY( "\\land" ^ " " ) )
| "\\ang" -> LITERAL ( TEX_ONLY( "\\angle" ^ " " ) )
| "\\Beta" -> LITERAL ( TEX_ONLY( "\\mathrm{B}" ^ " " ) )
| "\\bull" -> LITERAL ( TEX_ONLY( "\\bullet" ^ " " ) )
| "\\Chi" -> LITERAL ( TEX_ONLY( "\\mathrm{X}" ^ " " ) )
| "\\clubs" -> LITERAL ( TEX_ONLY( "\\clubsuit" ^ " " ) )
| "\\cnums" -> LITERAL ( TEX_ONLY( "\\mathbb{C}" ^ " " ) )
| "\\Complex" -> LITERAL ( TEX_ONLY( "\\mathbb{C}" ^ " " ) )
| "\\Dagger" -> LITERAL ( TEX_ONLY( "\\ddagger" ^ " " ) )
| "\\diamonds" -> LITERAL ( TEX_ONLY( "\\diamondsuit" ^ " " ) )
| "\\Doteq" -> LITERAL ( TEX_ONLY( "\\doteqdot" ^ " " ) )
| "\\doublecap" -> LITERAL ( TEX_ONLY( "\\Cap" ^ " " ) )
| "\\doublecup" -> LITERAL ( TEX_ONLY( "\\Cup" ^ " " ) )
| "\\empty" -> LITERAL ( TEX_ONLY( "\\emptyset" ^ " " ) )
| "\\Epsilon" -> LITERAL ( TEX_ONLY( "\\mathrm{E}" ^ " " ) )
| "\\Eta" -> LITERAL ( TEX_ONLY( "\\mathrm{H}" ^ " " ) )
| "\\exist" -> LITERAL ( TEX_ONLY( "\\exists" ^ " " ) )
| "\\ge" -> LITERAL ( TEX_ONLY( "\\geq" ^ " " ) )
| "\\gggtr" -> LITERAL ( TEX_ONLY( "\\ggg" ^ " " ) )
| "\\hAar" -> LITERAL ( TEX_ONLY( "\\Leftrightarrow" ^ " " ) )
| "\\harr" -> LITERAL ( TEX_ONLY( "\\leftrightarrow" ^ " " ) )
| "\\Harr" -> LITERAL ( TEX_ONLY( "\\Leftrightarrow" ^ " " ) )
| "\\hearts" -> LITERAL ( TEX_ONLY( "\\heartsuit" ^ " " ) )
| "\\image" -> LITERAL ( TEX_ONLY( "\\Im" ^ " " ) )
| "\\infin" -> LITERAL ( TEX_ONLY( "\\infty" ^ " " ) )
| "\\Iota" -> LITERAL ( TEX_ONLY( "\\mathrm{I}" ^ " " ) )
| "\\isin" -> LITERAL ( TEX_ONLY( "\\in" ^ " " ) )
| "\\Kappa" -> LITERAL ( TEX_ONLY( "\\mathrm{K}" ^ " " ) )
| "\\larr" -> LITERAL ( TEX_ONLY( "\\leftarrow" ^ " " ) )
| "\\Larr" -> LITERAL ( TEX_ONLY( "\\Leftarrow" ^ " " ) )
| "\\lArr" -> LITERAL ( TEX_ONLY( "\\Leftarrow" ^ " " ) )
| "\\le" -> LITERAL ( TEX_ONLY( "\\leq" ^ " " ) )
| "\\lrarr" -> LITERAL ( TEX_ONLY( "\\leftrightarrow" ^ " " ) )
| "\\Lrarr" -> LITERAL ( TEX_ONLY( "\\Leftrightarrow" ^ " " ) )
| "\\lrArr" -> LITERAL ( TEX_ONLY( "\\Leftrightarrow" ^ " " ) )
| "\\Mu" -> LITERAL ( TEX_ONLY( "\\mathrm{M}" ^ " " ) )
| "\\natnums" -> LITERAL ( TEX_ONLY( "\\mathbb{N}" ^ " " ) )
| "\\ne" -> LITERAL ( TEX_ONLY( "\\neq" ^ " " ) )
| "\\Nu" -> LITERAL ( TEX_ONLY( "\\mathrm{N}" ^ " " ) )
| "\\O" -> LITERAL ( TEX_ONLY( "\\emptyset" ^ " " ) )
| "\\omicron" -> LITERAL ( TEX_ONLY( "\\mathrm{o}" ^ " " ) )
| "\\Omicron" -> LITERAL ( TEX_ONLY( "\\mathrm{O}" ^ " " ) )
| "\\or" -> LITERAL ( TEX_ONLY( "\\lor" ^ " " ) )
| "\\part" -> LITERAL ( TEX_ONLY( "\\partial" ^ " " ) )
| "\\plusmn" -> LITERAL ( TEX_ONLY( "\\pm" ^ " " ) )
| "\\rarr" -> LITERAL ( TEX_ONLY( "\\rightarrow" ^ " " ) )
| "\\Rarr" -> LITERAL ( TEX_ONLY( "\\Rightarrow" ^ " " ) )
| "\\rArr" -> LITERAL ( TEX_ONLY( "\\Rightarrow" ^ " " ) )
| "\\real" -> LITERAL ( TEX_ONLY( "\\Re" ^ " " ) )
| "\\reals" -> LITERAL ( TEX_ONLY( "\\mathbb{R}" ^ " " ) )
| "\\Reals" -> LITERAL ( TEX_ONLY( "\\mathbb{R}" ^ " " ) )
| "\\restriction" -> LITERAL ( TEX_ONLY( "\\upharpoonright" ^ " " ) )
| "\\Rho" -> LITERAL ( TEX_ONLY( "\\mathrm{P}" ^ " " ) )
| "\\sdot" -> LITERAL ( TEX_ONLY( "\\cdot" ^ " " ) )
| "\\sect" -> LITERAL ( TEX_ONLY( "\\S" ^ " " ) )
| "\\spades" -> LITERAL ( TEX_ONLY( "\\spadesuit" ^ " " ) )
| "\\sub" -> LITERAL ( TEX_ONLY( "\\subset" ^ " " ) )
| "\\sube" -> LITERAL ( TEX_ONLY( "\\subseteq" ^ " " ) )
| "\\supe" -> LITERAL ( TEX_ONLY( "\\supseteq" ^ " " ) )
| "\\Tau" -> LITERAL ( TEX_ONLY( "\\mathrm{T}" ^ " " ) )
| "\\thetasym" -> LITERAL ( TEX_ONLY( "\\vartheta" ^ " " ) )
| "\\varcoppa" -> LITERAL ( TEX_ONLY( "\\mbox{\\coppa}" ^ " " ) )
| "\\weierp" -> LITERAL ( TEX_ONLY( "\\wp" ^ " " ) )
| "\\Zeta" -> LITERAL ( TEX_ONLY( "\\mathrm{Z}" ^ " " ) )
| "\\rm"
| "\\it"
| "\\cal"
| "\\bf"
-> DECLh ( cmd ^ " ", FONTFORCE_RM ) (* see bug 54818 *)
| "\\overbrace" -> FUN_AR1nb "\\overbrace "
| "\\underbrace" -> FUN_AR1nb "\\underbrace "
| "\\sideset" -> FUN_AR2nb "\\sideset "
| "\\left" -> LEFT
| "\\right" -> RIGHT
| "\\text"
| "\\mbox"
| "\\vbox"
| "\\hbox"
-> raise (Failure ("malformatted " ^ cmd))
| s -> raise (Illegal_tex_function s)

View File

@ -1,38 +0,0 @@
(* vim: set sw=8 ts=8 et: *)
exception LexerException of string
(* *)
let lexer_token_safe lexbuf =
try Lexer.token lexbuf
with Failure s -> raise (LexerException s)
(* *)
let render tree =
let outtex = Util.mapjoin Texutil.render_tex tree in
begin
print_string ("+" ^ outtex);
end
(* TODO: document
* Arguments:
* 1st : tex input string
*
* Output one character:
* E : Lexer exception raised
* F : TeX function not recognized
* S : Parsing error
* - : Generic/Default failure code. Might be an invalid argument,
* output file already exist, a problem with an external
* command ...
*)
let _ =
try render (
Parser.tex_expr lexer_token_safe (
Lexing.from_string Sys.argv.(1))
)
with Parsing.Parse_error -> print_string "S"
| LexerException _ -> print_string "E"
| Texutil.Illegal_tex_function s -> print_string ("F" ^ s)
| Invalid_argument _ -> print_string "-"
| Failure _ -> print_string "-"
| _ -> print_string "-"

View File

@ -1,9 +0,0 @@
(* vim: set sw=8 ts=8 et: *)
(* TODO document *)
let mapjoin f l = (List.fold_left (fun a b -> a ^ (f b)) "" l)
(* TODO document *)
let mapjoine e f = function
[] -> ""
| h::t -> (List.fold_left (fun a b -> a ^ e ^ (f b)) (f h) t)