#include "ltx2mathmltables.h"
#include <stdio.h>
	
static CommandStruct commandTable[] = {
{"Overleftarrow",			ci_accent,pt_one, "<mover accent='true'>", "<mo stretchy='true'>&#x21D0;</mo></mover>" },
{"Overleftrightarrow",		ci_accent,pt_one, "<mover accent='true'>", "<mo stretchy='true'>&#x21D4;</mo></mover>" },
{"Overrightarrow",			ci_accent,pt_one, "<mover accent='true'>", "<mo stretchy='true'>&#x21D2;</mo></mover>" },
{"actuarial",				ci_menclose,    pt_one,"<menclose notation='actuarial'>",  "</menclose>" },
{"acute",					ci_accent,pt_one, "<mover accent='true'>", "<mo>&#x00B4;</mo></mover>" },
{"bar",						ci_accent,pt_one, "<mover accent='true'>", "<mo stretchy='false'>&#x00AF;</mo></mover>" },
{"begin",					ci_begin,pt_especial,"", "" },
{"binom",					ci_binom,pt_two, "<mfenced><mrow><mfrac linethickness='0'>","</mfrac></mrow></mfenced>" },
{"breve",					ci_accent,pt_one, "<mover accent='true'>", "<mo>&#x02D8;</mo></mover>" },
{"cfrac",					ci_cfrac,pt_especial,    "<mfrac>", "</mstyle></mfrac>" },
{"check",					ci_accent,pt_one, "<mover accent='true'>", "<mo>&#x02C7;</mo></mover>" },
{"ddddot",					ci_accent,pt_one, "<mover accent='true'>", "<mo>&#x00A8;&#x00A8;</mo></mover>" },
{"dddot",	ci_accent,	pt_one,	"<mover accent='true'>", "<mo>&#x20DB;</mo></mover>" },
{"ddot",	ci_accent,	pt_one,	"<mover accent='true'>", "<mo>&#x00A8;</mo></mover>" },
{"dfrac",	ci_mfrac,	pt_two,	"<mstyle displaystyle='true' scriptlevel='0'><mfrac>", "</mfrac></mstyle>" },
{"dot",	ci_accent,	pt_one,	"<mover accent='true'>", "<mo>&#x02D9;</mo></mover>" },
{"end",	ci_end,	pt_especial,	"","" },
{"eqno",	ci_eqno,	pt_especial,	"<mtable><mlabeledtr><mtd><mtext>", "</mtext></mtd><mtd>" },
{"frac",	ci_frac,	pt_two,	"<mfrac>", "</mfrac>" },
{"func",	ci_func,	pt_plain,	"<mi>", "</mi>" },
{"grave",	ci_accent,	pt_one,	"<mover accent='true'>", "<mo>&#x0300;</mo></mover>" },
{"hat",	ci_accent,	pt_one,	"<mover accent='true'>", "<mo>&#x02c6;</mo></mover>" },
{"hfill",	ci_hfill,	pt_especial,	"","" },
{"hphantom",	ci_phantom,	pt_one,	"<mphantom><mpadded height='0%' depth='0'>", "</mpadded></mphantom>" },
{"hungarumlaut",	ci_accent,	pt_one,	"<mover accent='true'>", "<mo>&#x02DD;</mo></mover>" },
{"left",	ci_left,	pt_especial,	"<mfenced>", "</mrow></mfenced>" },
{"leqno",	ci_eqno,	pt_especial,	"<mtable side='left'><mlabeledtr><mtd><mtext>", "</mtext></mtd><mtd>" },
{"limits",	ci_limits,	pt_especial,	"","" },
{"longdiv",	ci_menclose,	pt_one,	"<menclose notation='longdiv'>", "</menclose>" },
{"lsub",	ci_lsub,	pt_especial,	"<mmultiscripts>", "</mmultiscripts>" },
{"lsubsup",	ci_lsubsup,	pt_especial,	"<mmultiscripts>", "</mmultiscripts>" },
{"lsup",	ci_lsup,	pt_especial,	"<mmultiscripts>", "</mmultiscripts>" },
{"mathbb",	ci_mathfont,	pt_plain,	"<mi mathvariant='double-struck'>", "</mi>" },
{"mathbf",	ci_mathfont,	pt_plain,	"<mi mathvariant='bold'>", "</mi>" },
{"mathbfrak",	ci_mathfont,	pt_plain,	"<mi mathvariant='bold-fraktur'>", "</mi>" },
{"mathbi",	ci_mathfont,	pt_plain,	"<mi mathvariant='bold-italic'>", "</mi>" },
{"mathbin",	ci_mathbin,	pt_plain,	"<mo lspace='.222222em' rspace='.222222em'>", "</mo>" },
{"mathbsc",	ci_mathfont,	pt_plain,	"<mi mathvariant='bold-script'>", "</mi>" },
{"mathbss",	ci_mathfont,	pt_plain,	"<mi mathvariant='bold-sans-serif'>", "</mi>" },
{"mathfrak",	ci_mathfont,	pt_plain,	"<mi mathvariant='fraktur'>", "</mi>" },
{"mathit",	ci_mathfont,	pt_plain,	"<mi mathvariant='italic'>", "</mi>" },
{"mathop",	ci_mathop,	pt_plain,	"<mo>", "</mo>" },
{"mathord",	ci_mathord,	pt_plain,	"<mo lspace='0' rspace='0'>", "</mo>" },
{"mathord",	ci_mathord,	pt_plain,	"<mo lspace='0' rspace='0'>", "</mo>"},
{"mathrel",	ci_mathrel,	pt_plain,	"<mo lspace='.27777em' rspace='.27777em'>", "</mo>" },
{"mathring",	ci_accent,	pt_one,	"<mover accent='true'>", "<mo>&#x02DA;</mo></mover>" },
{"mathrm",	ci_mathfont,	pt_plain,	"<mi mathvariant='normal'>", "</mi>" },
{"mathsc",	ci_mathfont,	pt_plain,	"<mi mathvariant='script'>", "</mi>" },
{"mathss",	ci_mathfont,	pt_plain,	"<mi mathvariant='sans-serif'>", "</mi>" },
{"mathssbi",	ci_mathfont,	pt_plain,	"<mi mathvariant='sans-serif-bold-italic'>", "</mi>" },
{"mathssi",	ci_mathfont,	pt_plain,	"<mi mathvariant='sans-serif-italic'>", "</mi>" },
{"mathstrut",	ci_strut,	pt_especial,	"<mphantom><mpadded width='0%' lspace='0'><mo>(</mo></mpadded></mphantom>","" },
{"mathtt",	ci_mathfont,	pt_plain,	"<mi mathvariant='monospace'>", "</mi>" },
{"mn",	ci_mn,	pt_plain,	"<mn>", "</mn>" },
{"mo",	ci_mo,	pt_plain,	"<mo>", "</mo>" },
{"ms",	ci_mathstring,	pt_especial,	"<ms>", "</ms>" },
{"nolimits",	ci_limits,	pt_especial,	"","" },
{"overbrace",	ci_underoverbrace,	pt_especial,	"<mover accent='false'>", "<mo stretchy='true'>&#xFE37;</mo></mover>" },
{"overbrack",	ci_accent,	pt_one,	"<mover accent='false'>", "<mo stretchy='true'>&#x23B4;</mo></mover>" },
{"overleftarrow",	ci_accent,	pt_one,	"<mover accent='true'>", "<mo stretchy='true'>&#x2190;</mo></mover>" },
{"overleftrightarrow",	ci_accent,	pt_one,  	"<mover accent='true'>", "<mo stretchy='true'>&#x2194;</mo></mover>" },
{"overline",	ci_accent,	pt_one,	"<mover accent='false'>", "<mo stretchy='true'>&#x00AF;</mo></mover>" },
{"overparen",	ci_accent,	pt_one,	"<mover accent='false'>", "<mo stretchy='true'>&#x2322;</mo></mover>" },
{"overrightarrow",	ci_accent,	pt_one,	"<mover accent='true'>", "<mo stretchy='true'>&#x2192;</mo></mover>" },
{"phantom",	ci_phantom,	pt_one,	"<mphantom>", "</mphantom>" },
{"qdot",	ci_accent,	pt_one,	"<mover accent='true'>", "<mo>&#x00A8;&#x00A8;</mo></mover>" },
{"right",	ci_right,	pt_especial,	"","" },
{"sqrt",	ci_sqrt,	pt_especial,	"<msqrt>", "</msqrt>" },
{"stack",	ci_stack,	pt_two,	"<mfrac linethickness='0'>", "</mfrac>" },
{"stackrel",	ci_stackrel,	pt_especial,	"<mover>", "</mover>" },
{"strut",	ci_strut,	pt_especial,	"<mspace width='0pt' height='8.5pt' depth='3.5pt'/>","" },
{"tbinom",	ci_binom,	pt_two,	"<mstyle scriptlevel='1'><mfenced><mrow><mfrac linethickness='0'>", "</mfrac></mrow></mfenced></mstyle>" },
{"tdot",	ci_accent,	pt_one,	"<mover accent='true'>", "<mo>&#x20DB;</mo></mover>" },
{"text",	ci_text,	pt_especial,	"<mtext>", "</mtext>" },
{"textbf",	ci_text,	pt_especial,	"<mtext mathvariant='bold'>", "</mtext>" },
{"textbi",	ci_text,	pt_especial,	"<mtext mathvariant='bold-italic'>", "</mtext>" },
{"textbsf",	ci_text,	pt_especial,	"<mtext mathvariant='bold-sans-serif'>", "</mtext>" },
{"textit",	ci_text,	pt_especial,	"<mtext mathvariant='italic'>", "</mtext>" },
{"textsf",	ci_text,	pt_especial,	"<mtext mathvariant='sans-serif'>", "</mtext>" },
{"textsfbi",	ci_text,	pt_especial,	"<mtext mathvariant='sans-serif-bold-italic'>", "</mtext>" },
{"textsfit",	ci_text,	pt_especial,	"<mtext mathvariant='sans-serif-italic'>", "</mtext>" },
{"texttt",	ci_text,	pt_especial,	"<mtext mathvariant='monospace'>", "</mtext>" },
{"tfrac",	ci_mfrac,	pt_two,	"<mstyle displaystyle='false' scriptlevel='0'><mfrac>", "</mfrac></mstyle>" },
{"tilde",	ci_accent,	pt_one,	"<mover accent='true'>", "<mo stretchy='false'>&#x02DC;</mo></mover>" },
{"underbrace",	ci_underoverbrace,	pt_especial,	"<munder accentunder='false'>", "<mo stretchy='true'>&#xFE38;</mo></munder>" },
{"underbrack",	ci_accent,	pt_one,	"<munder accentunder='false'>", "<mo stretchy='true'>&#x23B5;</mo></munder>" },
{"underleftarrow",	ci_accent,	pt_one,	"<munder accentunder='true'>", "<mo stretchy='true'>&#x2190;</mo></munder>" },
{"underleftrightarrow",	ci_accent,	pt_one,	"<munder accentunder='true'>", "<mo stretchy='true'>&#x2194;</mo></munder>" },
{"underline",	ci_accent,	pt_one,	"<munder accentunder='false'>", "<mo stretchy='true'>&#x0332;</mo></munder>" },
{"underparen",	ci_accent,	pt_one,	"<munder accentunder='false'>", "<mo stretchy='true'>&#xF611;</mo></munder>" },
{"underrightarrow",	ci_accent,	pt_one,	"<munder accentunder='true'>", "<mo stretchy='true'>&#x2192;</mo></munder>" },
{"undertilde",	ci_accent,	pt_one,	"<munder accentunder='false'>", "<mo stretchy='true'>&#x02DC;</mo></munder>" },
{"vec",	ci_accent,	pt_one,	"<mover accent='true'>", "<mo stretchy='false'>&#x2192;</mo></mover>" },
{"vphantom",	ci_phantom,	pt_one,	"<mphantom><mpadded width='0%' lspace='0'>", "</mpadded></mphantom>" },
{"widehat",	ci_accent,	pt_one,	"<mover accent='true'>", "<mo stretchy='true'>&#x0302;</mo></mover>" },
{"widetilde",	ci_accent,	pt_one,	"<mover accent='true'>", "<mo stretchy='true'>&#x02DC;</mo></mover>" },
{"widevec",	ci_accent,	pt_one,	"<mover accent='true'>", "<mo stretchy='true'>&#x2192;</mo></mover>" },
{"xleftarrow",	ci_ext_arrows,	pt_especial,	"<mo stretchy='true'>&#x2190;</mo>", "</mover>" },
{"xleftrightarrow",	ci_ext_arrows,	pt_especial,	"<mo stretchy='true'>&#x2194;</mo>", "</mover>"},
{"xrightarrow",	ci_ext_arrows,	pt_especial,	"<mo stretchy='true'>&#x2192;</mo>", "</mover>" }
};

struct EnvironmentStruct environmentTable[] = {
	{ "array",	  ci_array,	   "<mtable><mtr><mtd>", "</mtd></mtr></mtable>" },
	{ "bmatrix",  ci_bmatrix,   "<mfenced open='[' close=']' separators=''><mtable><mtr><mtd>", "</mtd></mtr></mtable></mfenced>" },
	{ "cases",    ci_cases,     "<mfenced open='{' close='' separators=''><mtable><mtr><mtd>", "</mtd></mtr></mtable></mfenced>" },
	{ "eqnarray", ci_eqnarray, "<mtable columnalign='right center left' columnspacing='.222222em'><mtr><mtd>", "</mtd></mtr></mtable>" },
	{ "matrix",	  ci_matrix,   "<mtable><mtr><mtd>", "</mtd></mtr></mtable>" },
	{ "pmatrix",  ci_pmatrix,   "<mfenced separators=''><mtable><mtr><mtd>", "</mtd></mtr></mtable></mfenced>" },
	{ "vmatrix",  ci_vmatrix,   "<mfenced open='|' close='|' separators=''><mtable><mtr><mtd>", "</mtd></mtr></mtable></mfenced>" },
	{ "Bmatrix",  ci_Bmatrix,   "<mfenced open='{' close='}' separators=''><mtable><mtr><mtd>", "</mtd></mtr></mtable></mfenced>" },	
	{ "Vmatrix",  ci_Vmatrix,   "<mfenced open='&#x2016;' close='&#x2016;' separators=''><mtable><mtr><mtd>", "</mtd></mtr></mtable></mfenced>" }
	
};

static FunctionStruct functionTable[] = {
	{ "Pr",			"Pr",  				  mt_func_limits},
	{ "arccos",		"arccos", 			  mt_func},
	{ "arcsin",		"arcsin",  			  mt_func},
	{ "arctan",		"arctan", 			  mt_func},
	{ "arg",		"arg",    			  mt_func},
	{ "cos",		"cos",    			  mt_func},
	{ "cosh",		"cosh",   			  mt_func},
	{ "cot",		"cot",    			  mt_func},
	{ "coth",		"coth",   			  mt_func},
	{ "csc",		"csc",    			  mt_func},
	{ "deg",		"deg",    			  mt_func},
	{ "det",		"det",  			  mt_func_limits},
	{ "dim",		"dim",    			  mt_func},
	{ "exp",		"exp",    			  mt_func},
	{ "gcd",		"gcd",  			  mt_func_limits},
	{ "hom",		"hom",    			  mt_func},
	{ "inf",		"inf",  			  mt_func_limits},
	{ "ker",		"ker",    			  mt_func},
	{ "lg",			"lg",     			  mt_func},
	{ "lim",		"lim",  			  mt_func_limits},
	{ "liminf",		"lim&#x2009;sup",	  mt_func_limits},		
	{ "limsup",		"lim&#x2009;sup",	  mt_func_limits},		
	{ "ln",			"ln",     			  mt_func},
	{ "log",		"log",    			  mt_func},
	{ "max",		"max",  			  mt_func_limits},
	{ "min",		"min",  			  mt_func_limits},	
	{ "sec",		"sec",    			  mt_func},
	{ "sin",		"sin",     			  mt_func},
	{ "sinh",		"sinh",   			  mt_func},
	{ "sup",		"sup",  			  mt_func_limits},
	{ "tan",		"tan",    			  mt_func},
	{ "tanh",		"tanh",   			  mt_func}
};


static EntityStruct entityTable[] = {

{ "Delta",  	0x394, mt_ident }, 
{ "Gamma",  	0x393, mt_ident }, 
{ "Lambda",  0x39B, mt_ident }, 
{ "Omega",  0x3A9, mt_ident }, 
{ "Phi",  0x3A6, mt_ident }, 
{ "Psi",  0x3A8, mt_ident }, 
{ "Sigma",  0x3A3, mt_ident }, 
{ "Xi",  0x39E, mt_ident }, 
{ "alpha",		0x3B1,	mt_ident },
{ "ast",  		0x2A, mt_bin }, 
{ "beta",		0x3B2,	mt_ident  },
{ "bigcap",		0x22C2, mt_mov_limits  },

{ "bigcup",		0x22C3, mt_mov_limits  },

{ "bigodot",	0x2299,	mt_mov_limits  },

{ "bigoplus",	0x2295,	mt_mov_limits  },

{ "bigotimes",	0x2297,	mt_mov_limits  },

{ "bigsqcup",	0x2A06,	mt_mov_limits  },

{ "biguplus",	0x2A04,	mt_mov_limits  },

{ "bigvee",		0x22C1,	mt_mov_limits  },

{ "bigwedge",	0x22C0,	mt_mov_limits  },

{ "cdot",  		0xB7, mt_bin }, 
{ "cdots",  	0x22EF, mt_ord }, 
{ "centerdot",  0xB7, mt_bin }, 
{ "chi",  		0x3C7, mt_ident }, 
{ "coprod",		0x2210, mt_mov_limits  },

{ "ddots",  	0x22F1, mt_ord }, 
{ "delta",  	0x3B4, mt_ident }, 
{ "div",  		0xF7, mt_bin }, 
{ "epsilon",  	0x3B5, mt_ident }, 
{ "gamma",  	0x3B3, mt_ident }, 
{ "ge",  		0x2265, mt_rel }, 
{ "iiiint",		0x2A0C,	mt_limits   },

{ "iiint",		0x222D,	mt_limits   },

{ "iint",		0x222C,	mt_limits   },

{ "infinity",  0x221E, mt_rel }, 
{ "int",		0x222B,	mt_limits   },

{ "kappa",  0x3BA, mt_ident }, 
{ "lambda",  0x3BB, mt_ident }, 
{ "ldots",  0x2026, mt_ord }, 
{ "le",  0x2264, mt_rel }, 
{ "leftarrow",  0x2190, mt_rel }, 



{ "mu",  0x3BC, mt_ident }, 

{ "nabla",  0x2207, mt_ident }, 
{ "nu",  0x3BD, mt_ident }, 
{ "oint",		0x222E,	mt_limits   },


{ "omega",  0x3C9, mt_ident }, 
{ "partial",  0x2202, mt_ord }, 
{ "phi",  0x3C6, mt_ident }, 
{ "pi",  0x3C0, mt_ident }, 
{ "pm",  0xB1, mt_rel }, 

{ "prod",		0x220f,	mt_mov_limits  },
{ "psi",  0x3C8, mt_ident }, 

{ "rho",  0x3C1, mt_ident }, 
{ "rightarrow",  0x2192, mt_rel }, 
{ "sigma",  0x3C3, mt_ident }, 
{ "sim",  0x223C, mt_rel }, 
{ "sum",		0x2211,	mt_mov_limits  },

{ "tau",  0x3C4, mt_ident }, 
{ "theta",  0x3B8, mt_ident }, 
{ "times",  0xD7, mt_bin }, 
{ "to",  0x2192, mt_rel }, 
{ "upsilon",  0x3C5, mt_ident },
{ "varepsilon",  0x3B5, mt_ident },
{ "vdots",  0x22EE, mt_ord }, 
{ "xi",  0x3BE, mt_ident },
{ "zeta",  0x3B6, mt_ident } 


};

static ErrorTable errorTable[] = {
	{ ex_out_of_memory,							"Out of memory" },
	{ ex_missing_lbrace,						"Missing '{'" },
	{ ex_prefix_superscript,					"Illegal prefix superscript: use the '\\lsup' command" },
	{ ex_prefix_subscript,						"Illegal prefix subscript: use the '\\lsub' command" },
	{ ex_misplaced_column_separator,			"Misplaced column separator" },		
	{ ex_more_rbrace_than_lbrace,				"Syntax error: more '}' than '{'" },
	{ ex_control_name_too_long,					"Control name too long: maximum is 32" },
	{ ex_misplaced_row_separator,				"Misplaced row separator" },
	{ ex_illegal_subscript,						"Illegal subscript" },
	{ ex_illegal_superscript,					"Illegal superscript" },
	{ ex_undefined_control_sequence,			"Undefined control sequence" },
	{ ex_misplaced_inline_formula,				"Misplaced inline formula" },
	{ ex_missing_parameter,						"Missing parameter" },
	{ ex_more_lbrace_than_rbrace,				"Syntax error: more '{' than '}'" },	
	{ ex_double_superscript,					"Double superscript" },
	{ ex_double_subscript,						"Double subscript" },
	{ ex_use_subscript_before_superscript,      "Use subscript first as the element is <msubsup>" },
	{ ex_internal_error,						"Internal error" },
	{ ex_missing_end_tag,						"Missing end tag" },
	{ ex_undefined_environment_type,			"Undefined environment type" },
	{ ex_unknown_alignment_character,			"Unknown alignment character" },
	{ ex_missing_begin,							"Missing \\begin" },
	{ ex_missing_end,							"Missing \\end" },
	{ ex_mismatched_environment_type,           "Mismatched environment type"},
	{ ex_too_many_columns,						"Too many columns" },
	{ ex_unknown_attribute,						"Unknown attribute" },
	{ ex_no_command_allowed,					"Command not allowed here" },
	{ ex_misplaced_limits,						"Limit controls must follow a math operator" },
	{ ex_missing_fence_parameter,				"Missing fence parameter" },
	{ ex_not_math_mode,							"Not in math mode" },
	{ ex_missing_right_sq_bracket,				"Missing ']'" },
	{ ex_missing_dollar_symbol,					"Missing '$'" },
	{ ex_missing_left_fence,					"Missing \\left" },
	{ ex_missing_right_fence,					"Missing \\right" },
	{ ex_ambiguous_script,						"Ambiguous script; use \\left and \\right" },
	{ ex_misplaced_eqno,						"Equation number not allowed here" },
	{ ex_duplicate_eqno,						"Duplicate equation number" },
	{ ex_missing_column_alignment,				"Missing column alignment" },
	{ ex_missing_subsup_base,					"Missing subscript/superscript base" },
	{ ex_unknown_character,						"Internal error: Unknown character" },
	{ ex_unhandled_mathtype,					"Internal error: unhandled math type" }
	//{ ex_misplaced_nolimits,					"Nolimits control must follow a math operator" }
};

SymbolTable mathvariant[]= {	
	{"bb",		"double-struck"},		
	{"bf",		"bold"},		
	{"bfrak",	"bold-fraktur"},		
	{"bi",		"bold-italic"},		
	{"bsc",		"bold-script"},		
	{"bss",		"bold-sans-serif"},		
	{"frak",	"fraktur"},		
	{"it",		"italic"},		
	{"rm",		"normal"}, 		
	{"sc",		"script"},		
	{"ss",		"sans-serif"},		
	{"ssbi",	"sans-serif-bold-italic"},		
	{"ssi",		"sans-serif-italic"},		
	{"tt",		"monospace"}
};

static EntityStruct fenceTable[] = {

	{ "[",      	    '[',		mt_left_fence },
    { "]",      	    ']',		mt_right_fence },
    { "\\{",      	    '{',		mt_left_fence },
    { "\\}",      	    '}',		mt_right_fence },
    { "/",      	    '/',		mt_ord },
    { "(",      	    '(',		mt_left_fence },
    { ")",      	    ')',		mt_right_fence },
    { "|",				0x007C,		mt_ord },
    { "\\|",			0x2016,		mt_ord },
    { "<",				0x2329,		mt_left_fence },
    { ">",				0x232A,		mt_right_fence },
    { ".",				0,			mt_ord },  //see function below
    { "lgroup",      	'(',		mt_left_fence },
    { "rgroup",      	')',		mt_right_fence },
   	{ "langle",			0x2329,		mt_left_fence },
    { "rangle",			0x232A,		mt_right_fence },
    { "lAngle",			0x300A,		mt_left_fence },
    { "rAngle",			0x300B,		mt_right_fence },
    { "lfloor",			0x230A,		mt_left_fence },//'&lfloor}, //0x230A},
    { "rfloor",			0x230B,		mt_right_fence },//'&rfloor}, //0x230B},
    { "lceil",			0x2308,		mt_left_fence },//'&lceil},  // 0x2308},
    { "rceil",			0x2309,		mt_right_fence },//'&rceil}, // 0x2309},
    { "lbrack",			'[',		mt_left_fence },
    { "rbrack",			']',		mt_right_fence },
    { "lBrack",			0x301A,		mt_left_fence },
    { "rBrack",			0x301B,		mt_right_fence },
    { "lbrace",			'{',		mt_left_fence },
    { "rbrace",			'}',		mt_right_fence },
    { "backslash",		'\\',		mt_ord },
    { "vert",			0x007C,		mt_ord },
    { "Vert",			0x2016,		mt_ord },
    { "uparrow",		0x2191,		mt_ord },
    { "Uparrow",		0x21D1,		mt_ord },
    { "downarrow",		0x2193,		mt_ord },
    { "Downarrow",		0x21D3,		mt_ord },
    { "updownarrow",	0x2195,		mt_ord },
    { "Updownarrow",	0x21D5,		mt_ord },
    { "lmoustache",		0x23B0,		mt_left_fence }, //0x23B0},
    { "rmoustache",		0x23B1,		mt_right_fence }, //0x23B1},
    { "lmoust",  	    0x23B0,		mt_left_fence },
    { "rmoust",			0x23B1,		mt_right_fence }
};

// thickspace .27777 
// medspace	  .222222em
// thinspace	.16667em
static SymbolStruct symbols[]= {
	{"\\ ",		"&#x00a0;",  	"<mspace width='.25em'/>", 			mt_ord },
	{"\\,",		"&#x2006;",  	"<mspace width='.16667em'/>", 		mt_ord },
	{"\\:",		"&#x205f;",  	"<mspace width='.222222em'/>", 		mt_ord },
	{"\\>",		"&#x205f;",  	"<mspace width='.222222em'/>", 		mt_ord },
	{"\\;",		"&#x2005;",  	"<mspace width='.27777em'/>", 		mt_ord },
	{"\\!",		"&#x200a;",  	"<mspace width='-.16667em'/>",  	mt_ord },
	{"\\~",		"&#x00a0;",  	"<mo>&#x00A0;</mo>",  				mt_ord },
	{"\\|",		"&#x2016;", 	"<mo mathsize='1'>&#x2016;</mo>", 	mt_fence },
	{"\\{",		"{",	   		"<mo mathsize='1'>{</mo>", 	        mt_left_fence },
	{"\\}",		"}",	   		"<mo mathsize='1'>}</mo>", 	        mt_right_fence },
	//{"|",		"|",	   		"<mo mathsize='1'>&#x0007C;</mo>", 	mt_ord },
	{"|",		"|",	   		"<mo mathsize='1'>|</mo>", 			mt_ord },
	{"[",		"[",  	   		"<mo mathsize='1'>[</mo>", 			mt_left_fence },
	{"]",		"]",  	   		"<mo mathsize='1'>]</mo>", 			mt_right_fence },
	{"(",		"(",  	   		"<mo mathsize='1'>(</mo>", 			mt_left_fence },
	{")",		")",  	   		"<mo mathsize='1'>)</mo>", 			mt_right_fence },
	{"<",		"<",  	   		"<mo mathsize='1'>&lt;</mo>", 		mt_left_fence },
	{">",		">",  	   		"<mo mathsize='1'>&gt;</mo>", 		mt_right_fence },
	{"-",		"-",			"<mo>&#x2212;</mo>", 				mt_bin_unary },
	{"`",		"&#x0300;",		"<mo>&#x0300;</mo>", 				mt_ord },
	{"@",		"&#x0040;",		"<mo>&#x0040;</mo>",            	mt_ord },
	{"*",		"*",			"<mo>*</mo>",                   	mt_ord },
	{"'",		"&#x02032;",	"<mo>&#x02032;</mo>",           	mt_ord },
	{"''",		"&#x02033;",	"<mo>&#x02033;</mo>",           	mt_ord },
	{"'''",		"&#x02034;",	"<mo>&#x02034;</mo>",           	mt_ord },
	{"\"",		"&#x0201D;",	"<mo>&#x0201D;</mo>",           	mt_ord },
	{"/",		"/",			"<mtext>/</mtext>",             	mt_ord },
	{"\\/",		"&#x200b;",		"<mo>&#x200b;</mo>",            	mt_ord },	
	{"\\%",		"%",			"<mo>%</mo>", 						mt_ord },
	{"\\#",		"&#x00023;",	"<mo>&#x00023;</mo>", 				mt_ord },
	{"\\$",		"$",			"<mtext>$</mtext>", 				mt_ord },
	{"\\^",		"&#x02C6;",		"<mo>&#x02C6;</mo>", 				mt_ord },
	{"\\&",		"&amp;",		"<mo>&amp;</mo>", 					mt_ord },
	{"\\_",		"&#x0005F;",	"<mo>&#x0005F;</mo>", 				mt_ord },
	{"\\-",		"&#x200b;",		"<mo>&#x200b;</mo>", 				mt_ord },
	{"!",		"!",			"<mo>!</mo>",   					mt_ord },
	{"+",		"+",			"<mo>+</mo>",						mt_bin_unary },
	{"=",		"=",			"<mo>=</mo>",						mt_bin },
	{":",		":",			"<mo>:</mo>",						mt_bin },
	{";",		";",			"<mo>;</mo>",						mt_ord },
	{",",		",",			"<mo>,</mo>",						mt_punct },
	{".",		".",			"<mo>.</mo>",						mt_ord },
	{"?",		"?",			"<mo>?</mo>",						mt_ord }
};

#define TABLE_SIZE(x)  ( sizeof( (x) )/sizeof( (x)[0] ))


inline int fastCompare( const char *s1, const char *s2 )
{
	return ( ( *s1 == *s2 ) ? strcmp( s1, s2 ) : *s1 - *s2 );
}


CommandStruct *isCommand( const char *name )
{
	const int size = TABLE_SIZE( commandTable );

	int result, low, mid, high;

	low = 0;
	high = size - 1;

	while( low <= high )
	{
		mid = ( low + high )/2;

		result = fastCompare( name, commandTable[mid].name );

		if( result < 0 )
		{
			high = mid - 1;
		}
		else if( result > 0 )
		{
			low = mid + 1;
		}
		else
		{
			return &commandTable[mid];			
		}
	}

	return NULL;
}


EntityStruct *isEntity( const char *name )
{
	const int size = TABLE_SIZE( entityTable );

	int result, low, mid, high;

	low = 0;
	high = size - 1;

	while( low <= high )
	{
		mid = ( low + high )/2;

		result = fastCompare( name, entityTable[mid].name );

		if( result < 0 )
		{
			high = mid - 1;
		}
		else if( result > 0 )
		{
			low = mid + 1;
		}
		else
		{
			return &entityTable[mid];			
		}
	}

	return NULL;

}


FunctionStruct *isFunction( const char *name )
{
	const int size = TABLE_SIZE( functionTable );

	int result, low, mid, high;

	low = 0;
	high = size - 1;

	while( low <= high )
	{
		mid = ( low + high )/2;

		result = fastCompare( name, functionTable[mid].name );

		if( result < 0 )
		{
			high = mid - 1;
		}
		else if( result > 0 )
		{
			low = mid + 1;
		}
		else
		{
			return &functionTable[mid];			
		}
	}

	return NULL;
}

token_type getControlType( const char *name, ControlStruct &control )
{
	
	if( ( control.command = isCommand( name ) ) != NULL )
	{
		control.token = token_control_command;		
	}
	else if( ( control.entity = isEntity( name ) ) != NULL )
	{
		control.token = token_control_entity;
	}
	else if( ( control.function = isFunction( name ) ) != NULL )
	{
		control.token = token_control_function;
	}	
	else
	{
		control.token = token_unknown;
	}

	return control.token;
}

/*

enum math_type { mt_unknown, mt_ident, mt_digit, mt_ord, mt_bin, mt_unary, mt_rel, mt_fence, 
				 mt_mov_limits, mt_limits, mt_func, mt_func_limits, mt_text };
*/

const char *getErrorMsg( ex_exception code )
{
	const int size = TABLE_SIZE( errorTable );

	for( int i = 0; i < size; ++i )
	{
		if( code == errorTable[i].code )
		{
			return errorTable[i].msg;
		}
	}	

	return NULL;
}

const char *getMathVariant( const char *attrib )
{
	const int size = TABLE_SIZE( mathvariant );

	int result, low, mid, high;

	low = 0;
	high = size - 1;

	while( low <= high )
	{
		mid = ( low + high )/2;

		result = fastCompare( attrib, mathvariant[mid].key );

		if( result < 0 )
		{
			high = mid - 1;
		}
		else if( result > 0 )
		{
			low = mid + 1;
		}
		else
		{
			return mathvariant[mid].value;			
		}
	}

	return NULL;
}


bool getFenceType( const char *name,  FenceStruct &fence )
{
	const int size = TABLE_SIZE( fenceTable );

	for( int i = 0; i < size; ++i )
	{
		if( strcmp( name, fenceTable[i].name ) == 0 )
		{
			fence.entity   = &fenceTable[i];
			

			if( fence.entity->code < 256 ) // ascii
			{
				fence.output[0] = (char)fence.entity->code;
				fence.output[1] = '\0';
			}
			else
			{				
				//sprintf_s( fence.output, sizeof( fence.output ) - 1, "&#x%x;", fence.entity->code );
				sprintf( fence.output, "&#x%x;", fence.entity->code );
			}
			return true;		
		}
	}

	fence.entity = NULL;
	return false;
}



EnvironmentStruct *getEnvironmentType( const char *name )
{
	const int size = TABLE_SIZE( environmentTable );
	
	int result, low, mid, high;

	low = 0;
	high = size - 1;

	while( low <= high )
	{
		mid = ( low + high )/2;

		result = fastCompare( name, environmentTable[mid].name );

		if( result < 0 )
		{
			high = mid - 1;
		}
		else if( result > 0 )
		{
			low = mid + 1;
		}
		else
		{
			return &environmentTable[mid];			
		}
	}


	return NULL;
}


SymbolStruct *getSymbol( const char *name )
{
	const int size = TABLE_SIZE( symbols );

	for( int i = 0; i < size; ++i )
	{
		if( strcmp( name, symbols[i].name ) == 0 )
		{
			return &symbols[i];
		}
	}

	return NULL;
}


