diff options
184 files changed, 19256 insertions, 16154 deletions
@@ -28,3 +28,28 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +----- + +The polyfill for String.fromCodePoint included in stmd.js is +Copyright Mathias Bynens <http://mathiasbynens.be/> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + @@ -1,12 +1,12 @@ -CFLAGS=-g -O3 -Wall -Wextra -std=c99 -Isrc $(OPTFLAGS) -LDFLAGS=-g -O3 -Wall -Werror -SRCDIR=src -DATADIR=data +CFLAGS?=-g -O3 -Wall -Wextra -std=c99 -Isrc -Wno-missing-field-initializers $(OPTFLAGS) +LDFLAGS?=-g -O3 -Wall -Werror +SRCDIR?=src +DATADIR?=data -PROG=./stmd +PROG?=./stmd -.PHONY: all oldtests test spec benchjs testjs -all: $(SRCDIR)/case_fold_switch.c $(PROG) +.PHONY: all test spec benchjs testjs +all: $(SRCDIR)/case_fold_switch.inc $(PROG) README.html: README.md template.html pandoc --template template.html -S -s -t html5 -o $@ $< @@ -28,9 +28,6 @@ spec.pdf: spec.md template.tex specfilter.hs --number-sections -V documentclass=report -V tocdepth=2 \ -V classoption=twosides -oldtests: - make -C oldtests --quiet clean all - test: spec.txt perl runtests.pl $< $(PROG) @@ -41,22 +38,33 @@ testjs: spec.txt benchjs: node js/bench.js ${BENCHINP} -$(PROG): $(SRCDIR)/main.c $(SRCDIR)/inlines.o $(SRCDIR)/blocks.o $(SRCDIR)/detab.o $(SRCDIR)/bstrlib.o $(SRCDIR)/scanners.o $(SRCDIR)/print.o $(SRCDIR)/html.o $(SRCDIR)/utf8.o - $(CC) $(LDFLAGS) -o $@ $^ +HTML_OBJ=$(SRCDIR)/html/html.o $(SRCDIR)/html/houdini_href_e.o $(SRCDIR)/html/houdini_html_e.o $(SRCDIR)/html/houdini_html_u.o + +STMD_OBJ=$(SRCDIR)/inlines.o $(SRCDIR)/buffer.o $(SRCDIR)/blocks.o $(SRCDIR)/scanners.c $(SRCDIR)/print.o $(SRCDIR)/utf8.o $(SRCDIR)/references.c + +$(PROG): $(SRCDIR)/html/html_unescape.h $(SRCDIR)/case_fold_switch.inc $(HTML_OBJ) $(STMD_OBJ) $(SRCDIR)/main.c + $(CC) $(LDFLAGS) -o $@ $(HTML_OBJ) $(STMD_OBJ) $(SRCDIR)/main.c $(SRCDIR)/scanners.c: $(SRCDIR)/scanners.re re2c --case-insensitive -bis $< > $@ || (rm $@ && false) -$(SRCDIR)/case_fold_switch.c: $(DATADIR)/CaseFolding-3.2.0.txt +$(SRCDIR)/case_fold_switch.inc: $(DATADIR)/CaseFolding-3.2.0.txt perl mkcasefold.pl < $< > $@ +$(SRCDIR)/html/html_unescape.h: $(SRCDIR)/html/html_unescape.gperf + gperf -I -t -N find_entity -H hash_entity -K entity -C -l --null-strings -m5 $< > $@ + .PHONY: leakcheck clean fuzztest dingus upload dingus: cd js && echo "Starting dingus server at http://localhost:9000" && python -m SimpleHTTPServer 9000 leakcheck: $(PROG) - cat oldtests/*/*.markdown | valgrind --leak-check=full --dsymutil=yes $(PROG) + # TODO produce leaktest.md that tests everything + cat leaktest.md | valgrind --leak-check=full --dsymutil=yes $(PROG) + +operf: $(PROG) + operf $(PROG) <bench.md >/dev/null fuzztest: for i in `seq 1 10`; do \ @@ -69,7 +77,7 @@ update-site: spec.html narrative.html (cd _site ; git pull ; git commit -a -m "Updated site for latest spec, narrative, js" ; git push; cd ..) clean: - -rm test $(SRCDIR)/*.o $(SRCDIR)/scanners.c - -rm -r *.dSYM - -rm README.html - -rm spec.md fuzz.txt spec.html + -rm -f test $(SRCDIR)/*.o $(SRCDIR)/scanners.c $(SRCDIR)/html/*.o + -rm -rf *.dSYM + -rm -f README.html + -rm -f spec.md fuzz.txt spec.html @@ -2,7 +2,7 @@ CommonMark ========== CommonMark is a [specification of Markdown syntax][the spec], -together with BSD3-licensed implementations (`stmd`) in C and javascript. +together with BSD3-licensed implementations (`stmd`) in C and JavaScript. The implementations ------------------- @@ -20,7 +20,7 @@ tarball.) --ast Print AST instead of HTML --version Print version -The javascript implementation is a single javascript file, with +The JavaScript implementation is a single JavaScript file, with no dependencies, that can be linked to in an HTML page. A standalone version (using `node.js`) is also provided (`js/markdown`), and there is a "dingus" for playing with it interactively. (`make dingus` will start diff --git a/js/index.html b/js/index.html index 994b147..05fc216 100644 --- a/js/index.html +++ b/js/index.html @@ -52,7 +52,7 @@ $(document).ready(function() { render(); }, 0); // ms delay }; - $("#text").keyup(parseAndRender); + $("#text").bind('keyup paste cut mouseup', parseAndRender); $(".option").change(render); }); </script> @@ -1,4 +1,4 @@ -// stmd.js - CommomMark in javascript +// stmd.js - CommomMark in JavaScript // Copyright (C) 2014 John MacFarlane // License: BSD3. @@ -11,1537 +11,3784 @@ (function(exports) { -// Some regexps used in inline parser: - -var ESCAPABLE = '[!"#$%&\'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]'; -var ESCAPED_CHAR = '\\\\' + ESCAPABLE; -var IN_DOUBLE_QUOTES = '"(' + ESCAPED_CHAR + '|[^"\\x00])*"'; -var IN_SINGLE_QUOTES = '\'(' + ESCAPED_CHAR + '|[^\'\\x00])*\''; -var IN_PARENS = '\\((' + ESCAPED_CHAR + '|[^)\\x00])*\\)'; -var REG_CHAR = '[^\\\\()\\x00-\\x20]'; -var IN_PARENS_NOSP = '\\((' + REG_CHAR + '|' + ESCAPED_CHAR + ')*\\)'; -var TAGNAME = '[A-Za-z][A-Za-z0-9]*'; -var BLOCKTAGNAME = '(?:article|header|aside|hgroup|iframe|blockquote|hr|body|li|map|button|object|canvas|ol|caption|output|col|p|colgroup|pre|dd|progress|div|section|dl|table|td|dt|tbody|embed|textarea|fieldset|tfoot|figcaption|th|figure|thead|footer|footer|tr|form|ul|h1|h2|h3|h4|h5|h6|video|script|style)'; -var ATTRIBUTENAME = '[a-zA-Z_:][a-zA-Z0-9:._-]*'; -var UNQUOTEDVALUE = "[^\"'=<>`\\x00-\\x20]+"; -var SINGLEQUOTEDVALUE = "'[^']*'"; -var DOUBLEQUOTEDVALUE = '"[^"]*"'; -var ATTRIBUTEVALUE = "(?:" + UNQUOTEDVALUE + "|" + SINGLEQUOTEDVALUE + "|" + DOUBLEQUOTEDVALUE + ")"; -var ATTRIBUTEVALUESPEC = "(?:" + "\\s*=" + "\\s*" + ATTRIBUTEVALUE + ")"; -var ATTRIBUTE = "(?:" + "\\s+" + ATTRIBUTENAME + ATTRIBUTEVALUESPEC + "?)"; -var OPENTAG = "<" + TAGNAME + ATTRIBUTE + "*" + "\\s*/?>"; -var CLOSETAG = "</" + TAGNAME + "\\s*[>]"; -var OPENBLOCKTAG = "<" + BLOCKTAGNAME + ATTRIBUTE + "*" + "\\s*/?>"; -var CLOSEBLOCKTAG = "</" + BLOCKTAGNAME + "\\s*[>]"; -var HTMLCOMMENT = "<!--([^-]+|[-][^-]+)*-->"; -var PROCESSINGINSTRUCTION = "[<][?].*?[?][>]"; -var DECLARATION = "<![A-Z]+" + "\\s+[^>]*>"; -var CDATA = "<!\\[CDATA\\[([^\\]]+|\\][^\\]]|\\]\\][^>])*\\]\\]>"; -var HTMLTAG = "(?:" + OPENTAG + "|" + CLOSETAG + "|" + HTMLCOMMENT + "|" + - PROCESSINGINSTRUCTION + "|" + DECLARATION + "|" + CDATA + ")"; -var HTMLBLOCKOPEN = "<(?:" + BLOCKTAGNAME + "[\\s/>]" + "|" + - "/" + BLOCKTAGNAME + "[\\s>]" + "|" + "[?!])"; - -var reHtmlTag = new RegExp('^' + HTMLTAG, 'i'); - -var reHtmlBlockOpen = new RegExp('^' + HTMLBLOCKOPEN, 'i'); - -var reLinkTitle = new RegExp( - '^(?:"(' + ESCAPED_CHAR + '|[^"\\x00])*"' + - '|' + - '\'(' + ESCAPED_CHAR + '|[^\'\\x00])*\'' + - '|' + - '\\((' + ESCAPED_CHAR + '|[^)\\x00])*\\))'); - -var reLinkDestinationBraces = new RegExp( - '^(?:[<](?:[^<>\\n\\\\\\x00]' + '|' + ESCAPED_CHAR + '|' + '\\\\)*[>])'); - -var reLinkDestination = new RegExp( - '^(?:' + REG_CHAR + '+|' + ESCAPED_CHAR + '|' + IN_PARENS_NOSP + ')*'); - -var reEscapable = new RegExp(ESCAPABLE); - -var reAllEscapedChar = new RegExp('\\\\(' + ESCAPABLE + ')', 'g'); - -var reEscapedChar = new RegExp('^\\\\(' + ESCAPABLE + ')'); - -var reAllTab = /\t/g; - -var reHrule = /^(?:(?:\* *){3,}|(?:_ *){3,}|(?:- *){3,}) *$/; - -// Matches a character with a special meaning in markdown, -// or a string of non-special characters. -var reMain = /^(?:[\n`\[\]\\!<&*_]|[^\n`\[\]\\!<&*_]+)/m; - -// UTILITY FUNCTIONS - -// Replace backslash escapes with literal characters. -var unescape = function(s) { - return s.replace(reAllEscapedChar, '$1'); -}; - -// Returns true if string contains only space characters. -var isBlank = function(s) { - return /^\s*$/.test(s); -}; - -// Normalize reference label: collapse internal whitespace -// to single space, remove leading/trailing whitespace, case fold. -var normalizeReference = function(s) { - return s.trim() - .replace(/\s+/,' ') - .toUpperCase(); -}; - -// Attempt to match a regex in string s at offset offset. -// Return index of match or null. -var matchAt = function(re, s, offset) { - var res = s.slice(offset).match(re); - if (res) { - return offset + res.index; - } else { - return null; - } -}; - -// Convert tabs to spaces on each line using a 4-space tab stop. -var detabLine = function(text) { - if (text.indexOf('\t') == -1) { - return text; - } else { - var lastStop = 0; - return text.replace(reAllTab, function(match, offset) { - var result = ' '.slice((offset - lastStop) % 4); - lastStop = offset + 1; - return result; - }); - } -}; - -// INLINE PARSER - -// These are methods of an InlineParser object, defined below. -// An InlineParser keeps track of a subject (a string to be -// parsed) and a position in that subject. - -// If re matches at current position in the subject, advance -// position in subject and return the match; otherwise return null. -var match = function(re) { - var match = re.exec(this.subject.slice(this.pos)); - if (match) { - this.pos += match.index + match[0].length; - return match[0]; - } else { - return null; - } -}; - -// Returns the character at the current subject position, or null if -// there are no more characters. -var peek = function() { - return this.subject[this.pos] || null; -}; - -// Parse zero or more space characters, including at most one newline -var spnl = function() { - this.match(/^ *(?:\n *)?/); - return 1; -}; - -// All of the parsers below try to match something at the current position -// in the subject. If they succeed in matching anything, they -// push an inline element onto the 'inlines' list. They return the -// number of characters parsed (possibly 0). - -// Attempt to parse backticks, adding either a backtick code span or a -// literal sequence of backticks to the 'inlines' list. -var parseBackticks = function(inlines) { - var startpos = this.pos; - var ticks = this.match(/^`+/); - if (!ticks) { - return 0; - } - var afterOpenTicks = this.pos; - var foundCode = false; - var match; - while (!foundCode && (match = this.match(/`+/m))) { - if (match == ticks) { - inlines.push({ t: 'Code', c: this.subject.slice(afterOpenTicks, - this.pos - ticks.length) - .replace(/[ \n]+/g,' ') - .trim() }); - return (this.pos - startpos); + var entities = { AAacute: 'Á', + aacute: 'á', + Abreve: 'Ă', + abreve: 'ă', + ac: '∾', + acd: '∿', + acE: '∾', + Acirc: 'Â', + acirc: 'â', + acute: '´', + Acy: 'А', + acy: 'а', + AElig: 'Æ', + aelig: 'æ', + af: '', + Afr: '𝔄', + afr: '𝔞', + Agrave: 'À', + agrave: 'à', + alefsym: 'ℵ', + aleph: 'ℵ', + Alpha: 'Α', + alpha: 'α', + Amacr: 'Ā', + amacr: 'ā', + amalg: '⨿', + amp: '&', + AMP: '&', + andand: '⩕', + And: '⩓', + and: '∧', + andd: '⩜', + andslope: '⩘', + andv: '⩚', + ang: '∠', + ange: '⦤', + angle: '∠', + angmsdaa: '⦨', + angmsdab: '⦩', + angmsdac: '⦪', + angmsdad: '⦫', + angmsdae: '⦬', + angmsdaf: '⦭', + angmsdag: '⦮', + angmsdah: '⦯', + angmsd: '∡', + angrt: '∟', + angrtvb: '⊾', + angrtvbd: '⦝', + angsph: '∢', + angst: 'Å', + angzarr: '⍼', + Aogon: 'Ą', + aogon: 'ą', + Aopf: '𝔸', + aopf: '𝕒', + apacir: '⩯', + ap: '≈', + apE: '⩰', + ape: '≊', + apid: '≋', + apos: '\'', + ApplyFunction: '', + approx: '≈', + approxeq: '≊', + Aring: 'Å', + aring: 'å', + Ascr: '𝒜', + ascr: '𝒶', + Assign: '≔', + ast: '*', + asymp: '≈', + asympeq: '≍', + Atilde: 'Ã', + atilde: 'ã', + Auml: 'Ä', + auml: 'ä', + awconint: '∳', + awint: '⨑', + backcong: '≌', + backepsilon: '϶', + backprime: '‵', + backsim: '∽', + backsimeq: '⋍', + Backslash: '∖', + Barv: '⫧', + barvee: '⊽', + barwed: '⌅', + Barwed: '⌆', + barwedge: '⌅', + bbrk: '⎵', + bbrktbrk: '⎶', + bcong: '≌', + Bcy: 'Б', + bcy: 'б', + bdquo: '„', + becaus: '∵', + because: '∵', + Because: '∵', + bemptyv: '⦰', + bepsi: '϶', + bernou: 'ℬ', + Bernoullis: 'ℬ', + Beta: 'Β', + beta: 'β', + beth: 'ℶ', + between: '≬', + Bfr: '𝔅', + bfr: '𝔟', + bigcap: '⋂', + bigcirc: '◯', + bigcup: '⋃', + bigodot: '⨀', + bigoplus: '⨁', + bigotimes: '⨂', + bigsqcup: '⨆', + bigstar: '★', + bigtriangledown: '▽', + bigtriangleup: '△', + biguplus: '⨄', + bigvee: '⋁', + bigwedge: '⋀', + bkarow: '⤍', + blacklozenge: '⧫', + blacksquare: '▪', + blacktriangle: '▴', + blacktriangledown: '▾', + blacktriangleleft: '◂', + blacktriangleright: '▸', + blank: '␣', + blk12: '▒', + blk14: '░', + blk34: '▓', + block: '█', + bne: '=', + bnequiv: '≡', + bNot: '⫭', + bnot: '⌐', + Bopf: '𝔹', + bopf: '𝕓', + bot: '⊥', + bottom: '⊥', + bowtie: '⋈', + boxbox: '⧉', + boxdl: '┐', + boxdL: '╕', + boxDl: '╖', + boxDL: '╗', + boxdr: '┌', + boxdR: '╒', + boxDr: '╓', + boxDR: '╔', + boxh: '─', + boxH: '═', + boxhd: '┬', + boxHd: '╤', + boxhD: '╥', + boxHD: '╦', + boxhu: '┴', + boxHu: '╧', + boxhU: '╨', + boxHU: '╩', + boxminus: '⊟', + boxplus: '⊞', + boxtimes: '⊠', + boxul: '┘', + boxuL: '╛', + boxUl: '╜', + boxUL: '╝', + boxur: '└', + boxuR: '╘', + boxUr: '╙', + boxUR: '╚', + boxv: '│', + boxV: '║', + boxvh: '┼', + boxvH: '╪', + boxVh: '╫', + boxVH: '╬', + boxvl: '┤', + boxvL: '╡', + boxVl: '╢', + boxVL: '╣', + boxvr: '├', + boxvR: '╞', + boxVr: '╟', + boxVR: '╠', + bprime: '‵', + breve: '˘', + Breve: '˘', + brvbar: '¦', + bscr: '𝒷', + Bscr: 'ℬ', + bsemi: '⁏', + bsim: '∽', + bsime: '⋍', + bsolb: '⧅', + bsol: '\\', + bsolhsub: '⟈', + bull: '•', + bullet: '•', + bump: '≎', + bumpE: '⪮', + bumpe: '≏', + Bumpeq: '≎', + bumpeq: '≏', + Cacute: 'Ć', + cacute: 'ć', + capand: '⩄', + capbrcup: '⩉', + capcap: '⩋', + cap: '∩', + Cap: '⋒', + capcup: '⩇', + capdot: '⩀', + CapitalDifferentialD: 'ⅅ', + caps: '∩', + caret: '⁁', + caron: 'ˇ', + Cayleys: 'ℭ', + ccaps: '⩍', + Ccaron: 'Č', + ccaron: 'č', + Ccedil: 'Ç', + ccedil: 'ç', + Ccirc: 'Ĉ', + ccirc: 'ĉ', + Cconint: '∰', + ccups: '⩌', + ccupssm: '⩐', + Cdot: 'Ċ', + cdot: 'ċ', + cedil: '¸', + Cedilla: '¸', + cemptyv: '⦲', + cent: '¢', + centerdot: '·', + CenterDot: '·', + cfr: '𝔠', + Cfr: 'ℭ', + CHcy: 'Ч', + chcy: 'ч', + check: '✓', + checkmark: '✓', + Chi: 'Χ', + chi: 'χ', + circ: 'ˆ', + circeq: '≗', + circlearrowleft: '↺', + circlearrowright: '↻', + circledast: '⊛', + circledcirc: '⊚', + circleddash: '⊝', + CircleDot: '⊙', + circledR: '®', + circledS: 'Ⓢ', + CircleMinus: '⊖', + CirclePlus: '⊕', + CircleTimes: '⊗', + cir: '○', + cirE: '⧃', + cire: '≗', + cirfnint: '⨐', + cirmid: '⫯', + cirscir: '⧂', + ClockwiseContourIntegral: '∲', + CloseCurlyDoubleQuote: '”', + CloseCurlyQuote: '’', + clubs: '♣', + clubsuit: '♣', + colon: ':', + Colon: '∷', + Colone: '⩴', + colone: '≔', + coloneq: '≔', + comma: ',', + commat: '@', + comp: '∁', + compfn: '∘', + complement: '∁', + complexes: 'ℂ', + cong: '≅', + congdot: '⩭', + Congruent: '≡', + conint: '∮', + Conint: '∯', + ContourIntegral: '∮', + copf: '𝕔', + Copf: 'ℂ', + coprod: '∐', + Coproduct: '∐', + copy: '©', + COPY: '©', + copysr: '℗', + CounterClockwiseContourIntegral: '∳', + crarr: '↵', + cross: '✗', + Cross: '⨯', + Cscr: '𝒞', + cscr: '𝒸', + csub: '⫏', + csube: '⫑', + csup: '⫐', + csupe: '⫒', + ctdot: '⋯', + cudarrl: '⤸', + cudarrr: '⤵', + cuepr: '⋞', + cuesc: '⋟', + cularr: '↶', + cularrp: '⤽', + cupbrcap: '⩈', + cupcap: '⩆', + CupCap: '≍', + cup: '∪', + Cup: '⋓', + cupcup: '⩊', + cupdot: '⊍', + cupor: '⩅', + cups: '∪', + curarr: '↷', + curarrm: '⤼', + curlyeqprec: '⋞', + curlyeqsucc: '⋟', + curlyvee: '⋎', + curlywedge: '⋏', + curren: '¤', + curvearrowleft: '↶', + curvearrowright: '↷', + cuvee: '⋎', + cuwed: '⋏', + cwconint: '∲', + cwint: '∱', + cylcty: '⌭', + dagger: '†', + Dagger: '‡', + daleth: 'ℸ', + darr: '↓', + Darr: '↡', + dArr: '⇓', + dash: '‐', + Dashv: '⫤', + dashv: '⊣', + dbkarow: '⤏', + dblac: '˝', + Dcaron: 'Ď', + dcaron: 'ď', + Dcy: 'Д', + dcy: 'д', + ddagger: '‡', + ddarr: '⇊', + DD: 'ⅅ', + dd: 'ⅆ', + DDotrahd: '⤑', + ddotseq: '⩷', + deg: '°', + Del: '∇', + Delta: 'Δ', + delta: 'δ', + demptyv: '⦱', + dfisht: '⥿', + Dfr: '𝔇', + dfr: '𝔡', + dHar: '⥥', + dharl: '⇃', + dharr: '⇂', + DiacriticalAcute: '´', + DiacriticalDot: '˙', + DiacriticalDoubleAcute: '˝', + DiacriticalGrave: '`', + DiacriticalTilde: '˜', + diam: '⋄', + diamond: '⋄', + Diamond: '⋄', + diamondsuit: '♦', + diams: '♦', + die: '¨', + DifferentialD: 'ⅆ', + digamma: 'ϝ', + disin: '⋲', + div: '÷', + divide: '÷', + divideontimes: '⋇', + divonx: '⋇', + DJcy: 'Ђ', + djcy: 'ђ', + dlcorn: '⌞', + dlcrop: '⌍', + dollar: '$', + Dopf: '𝔻', + dopf: '𝕕', + Dot: '¨', + dot: '˙', + DotDot: '⃜', + doteq: '≐', + doteqdot: '≑', + DotEqual: '≐', + dotminus: '∸', + dotplus: '∔', + dotsquare: '⊡', + doublebarwedge: '⌆', + DoubleContourIntegral: '∯', + DoubleDot: '¨', + DoubleDownArrow: '⇓', + DoubleLeftArrow: '⇐', + DoubleLeftRightArrow: '⇔', + DoubleLeftTee: '⫤', + DoubleLongLeftArrow: '⟸', + DoubleLongLeftRightArrow: '⟺', + DoubleLongRightArrow: '⟹', + DoubleRightArrow: '⇒', + DoubleRightTee: '⊨', + DoubleUpArrow: '⇑', + DoubleUpDownArrow: '⇕', + DoubleVerticalBar: '∥', + DownArrowBar: '⤓', + downarrow: '↓', + DownArrow: '↓', + Downarrow: '⇓', + DownArrowUpArrow: '⇵', + DownBreve: '̑', + downdownarrows: '⇊', + downharpoonleft: '⇃', + downharpoonright: '⇂', + DownLeftRightVector: '⥐', + DownLeftTeeVector: '⥞', + DownLeftVectorBar: '⥖', + DownLeftVector: '↽', + DownRightTeeVector: '⥟', + DownRightVectorBar: '⥗', + DownRightVector: '⇁', + DownTeeArrow: '↧', + DownTee: '⊤', + drbkarow: '⤐', + drcorn: '⌟', + drcrop: '⌌', + Dscr: '𝒟', + dscr: '𝒹', + DScy: 'Ѕ', + dscy: 'ѕ', + dsol: '⧶', + Dstrok: 'Đ', + dstrok: 'đ', + dtdot: '⋱', + dtri: '▿', + dtrif: '▾', + duarr: '⇵', + duhar: '⥯', + dwangle: '⦦', + DZcy: 'Џ', + dzcy: 'џ', + dzigrarr: '⟿', + Eacute: 'É', + eacute: 'é', + easter: '⩮', + Ecaron: 'Ě', + ecaron: 'ě', + Ecirc: 'Ê', + ecirc: 'ê', + ecir: '≖', + ecolon: '≕', + Ecy: 'Э', + ecy: 'э', + eDDot: '⩷', + Edot: 'Ė', + edot: 'ė', + eDot: '≑', + ee: 'ⅇ', + efDot: '≒', + Efr: '𝔈', + efr: '𝔢', + eg: '⪚', + Egrave: 'È', + egrave: 'è', + egs: '⪖', + egsdot: '⪘', + el: '⪙', + Element: '∈', + elinters: '⏧', + ell: 'ℓ', + els: '⪕', + elsdot: '⪗', + Emacr: 'Ē', + emacr: 'ē', + empty: '∅', + emptyset: '∅', + EmptySmallSquare: '◻', + emptyv: '∅', + EmptyVerySmallSquare: '▫', + emsp13: ' ', + emsp14: ' ', + emsp: ' ', + ENG: 'Ŋ', + eng: 'ŋ', + ensp: ' ', + Eogon: 'Ę', + eogon: 'ę', + Eopf: '𝔼', + eopf: '𝕖', + epar: '⋕', + eparsl: '⧣', + eplus: '⩱', + epsi: 'ε', + Epsilon: 'Ε', + epsilon: 'ε', + epsiv: 'ϵ', + eqcirc: '≖', + eqcolon: '≕', + eqsim: '≂', + eqslantgtr: '⪖', + eqslantless: '⪕', + Equal: '⩵', + equals: '=', + EqualTilde: '≂', + equest: '≟', + Equilibrium: '⇌', + equiv: '≡', + equivDD: '⩸', + eqvparsl: '⧥', + erarr: '⥱', + erDot: '≓', + escr: 'ℯ', + Escr: 'ℰ', + esdot: '≐', + Esim: '⩳', + esim: '≂', + Eta: 'Η', + eta: 'η', + ETH: 'Ð', + eth: 'ð', + Euml: 'Ë', + euml: 'ë', + euro: '€', + excl: '!', + exist: '∃', + Exists: '∃', + expectation: 'ℰ', + exponentiale: 'ⅇ', + ExponentialE: 'ⅇ', + fallingdotseq: '≒', + Fcy: 'Ф', + fcy: 'ф', + female: '♀', + ffilig: 'ffi', + fflig: 'ff', + ffllig: 'ffl', + Ffr: '𝔉', + ffr: '𝔣', + filig: 'fi', + FilledSmallSquare: '◼', + FilledVerySmallSquare: '▪', + fjlig: 'f', + flat: '♭', + fllig: 'fl', + fltns: '▱', + fnof: 'ƒ', + Fopf: '𝔽', + fopf: '𝕗', + forall: '∀', + ForAll: '∀', + fork: '⋔', + forkv: '⫙', + Fouriertrf: 'ℱ', + fpartint: '⨍', + frac12: '½', + frac13: '⅓', + frac14: '¼', + frac15: '⅕', + frac16: '⅙', + frac18: '⅛', + frac23: '⅔', + frac25: '⅖', + frac34: '¾', + frac35: '⅗', + frac38: '⅜', + frac45: '⅘', + frac56: '⅚', + frac58: '⅝', + frac78: '⅞', + frasl: '⁄', + frown: '⌢', + fscr: '𝒻', + Fscr: 'ℱ', + gacute: 'ǵ', + Gamma: 'Γ', + gamma: 'γ', + Gammad: 'Ϝ', + gammad: 'ϝ', + gap: '⪆', + Gbreve: 'Ğ', + gbreve: 'ğ', + Gcedil: 'Ģ', + Gcirc: 'Ĝ', + gcirc: 'ĝ', + Gcy: 'Г', + gcy: 'г', + Gdot: 'Ġ', + gdot: 'ġ', + ge: '≥', + gE: '≧', + gEl: '⪌', + gel: '⋛', + geq: '≥', + geqq: '≧', + geqslant: '⩾', + gescc: '⪩', + ges: '⩾', + gesdot: '⪀', + gesdoto: '⪂', + gesdotol: '⪄', + gesl: '⋛', + gesles: '⪔', + Gfr: '𝔊', + gfr: '𝔤', + gg: '≫', + Gg: '⋙', + ggg: '⋙', + gimel: 'ℷ', + GJcy: 'Ѓ', + gjcy: 'ѓ', + gla: '⪥', + gl: '≷', + glE: '⪒', + glj: '⪤', + gnap: '⪊', + gnapprox: '⪊', + gne: '⪈', + gnE: '≩', + gneq: '⪈', + gneqq: '≩', + gnsim: '⋧', + Gopf: '𝔾', + gopf: '𝕘', + grave: '`', + GreaterEqual: '≥', + GreaterEqualLess: '⋛', + GreaterFullEqual: '≧', + GreaterGreater: '⪢', + GreaterLess: '≷', + GreaterSlantEqual: '⩾', + GreaterTilde: '≳', + Gscr: '𝒢', + gscr: 'ℊ', + gsim: '≳', + gsime: '⪎', + gsiml: '⪐', + gtcc: '⪧', + gtcir: '⩺', + gt: '>', + GT: '>', + Gt: '≫', + gtdot: '⋗', + gtlPar: '⦕', + gtquest: '⩼', + gtrapprox: '⪆', + gtrarr: '⥸', + gtrdot: '⋗', + gtreqless: '⋛', + gtreqqless: '⪌', + gtrless: '≷', + gtrsim: '≳', + gvertneqq: '≩', + gvnE: '≩', + Hacek: 'ˇ', + hairsp: ' ', + half: '½', + hamilt: 'ℋ', + HARDcy: 'Ъ', + hardcy: 'ъ', + harrcir: '⥈', + harr: '↔', + hArr: '⇔', + harrw: '↭', + Hat: '^', + hbar: 'ℏ', + Hcirc: 'Ĥ', + hcirc: 'ĥ', + hearts: '♥', + heartsuit: '♥', + hellip: '…', + hercon: '⊹', + hfr: '𝔥', + Hfr: 'ℌ', + HilbertSpace: 'ℋ', + hksearow: '⤥', + hkswarow: '⤦', + hoarr: '⇿', + homtht: '∻', + hookleftarrow: '↩', + hookrightarrow: '↪', + hopf: '𝕙', + Hopf: 'ℍ', + horbar: '―', + HorizontalLine: '─', + hscr: '𝒽', + Hscr: 'ℋ', + hslash: 'ℏ', + Hstrok: 'Ħ', + hstrok: 'ħ', + HumpDownHump: '≎', + HumpEqual: '≏', + hybull: '⁃', + hyphen: '‐', + Iacute: 'Í', + iacute: 'í', + ic: '', + Icirc: 'Î', + icirc: 'î', + Icy: 'И', + icy: 'и', + Idot: 'İ', + IEcy: 'Е', + iecy: 'е', + iexcl: '¡', + iff: '⇔', + ifr: '𝔦', + Ifr: 'ℑ', + Igrave: 'Ì', + igrave: 'ì', + ii: 'ⅈ', + iiiint: '⨌', + iiint: '∭', + iinfin: '⧜', + iiota: '℩', + IJlig: 'IJ', + ijlig: 'ij', + Imacr: 'Ī', + imacr: 'ī', + image: 'ℑ', + ImaginaryI: 'ⅈ', + imagline: 'ℐ', + imagpart: 'ℑ', + imath: 'ı', + Im: 'ℑ', + imof: '⊷', + imped: 'Ƶ', + Implies: '⇒', + incare: '℅', + in: '∈', + infin: '∞', + infintie: '⧝', + inodot: 'ı', + intcal: '⊺', + int: '∫', + Int: '∬', + integers: 'ℤ', + Integral: '∫', + intercal: '⊺', + Intersection: '⋂', + intlarhk: '⨗', + intprod: '⨼', + InvisibleComma: '', + InvisibleTimes: '', + IOcy: 'Ё', + iocy: 'ё', + Iogon: 'Į', + iogon: 'į', + Iopf: '𝕀', + iopf: '𝕚', + Iota: 'Ι', + iota: 'ι', + iprod: '⨼', + iquest: '¿', + iscr: '𝒾', + Iscr: 'ℐ', + isin: '∈', + isindot: '⋵', + isinE: '⋹', + isins: '⋴', + isinsv: '⋳', + isinv: '∈', + it: '', + Itilde: 'Ĩ', + itilde: 'ĩ', + Iukcy: 'І', + iukcy: 'і', + Iuml: 'Ï', + iuml: 'ï', + Jcirc: 'Ĵ', + jcirc: 'ĵ', + Jcy: 'Й', + jcy: 'й', + Jfr: '𝔍', + jfr: '𝔧', + jmath: 'ȷ', + Jopf: '𝕁', + jopf: '𝕛', + Jscr: '𝒥', + jscr: '𝒿', + Jsercy: 'Ј', + jsercy: 'ј', + Jukcy: 'Є', + jukcy: 'є', + Kappa: 'Κ', + kappa: 'κ', + kappav: 'ϰ', + Kcedil: 'Ķ', + kcedil: 'ķ', + Kcy: 'К', + kcy: 'к', + Kfr: '𝔎', + kfr: '𝔨', + kgreen: 'ĸ', + KHcy: 'Х', + khcy: 'х', + KJcy: 'Ќ', + kjcy: 'ќ', + Kopf: '𝕂', + kopf: '𝕜', + Kscr: '𝒦', + kscr: '𝓀', + lAarr: '⇚', + Lacute: 'Ĺ', + lacute: 'ĺ', + laemptyv: '⦴', + lagran: 'ℒ', + Lambda: 'Λ', + lambda: 'λ', + lang: '⟨', + Lang: '⟪', + langd: '⦑', + langle: '⟨', + lap: '⪅', + Laplacetrf: 'ℒ', + laquo: '«', + larrb: '⇤', + larrbfs: '⤟', + larr: '←', + Larr: '↞', + lArr: '⇐', + larrfs: '⤝', + larrhk: '↩', + larrlp: '↫', + larrpl: '⤹', + larrsim: '⥳', + larrtl: '↢', + latail: '⤙', + lAtail: '⤛', + lat: '⪫', + late: '⪭', + lates: '⪭', + lbarr: '⤌', + lBarr: '⤎', + lbbrk: '❲', + lbrace: '{', + lbrack: '[', + lbrke: '⦋', + lbrksld: '⦏', + lbrkslu: '⦍', + Lcaron: 'Ľ', + lcaron: 'ľ', + Lcedil: 'Ļ', + lcedil: 'ļ', + lceil: '⌈', + lcub: '{', + Lcy: 'Л', + lcy: 'л', + ldca: '⤶', + ldquo: '“', + ldquor: '„', + ldrdhar: '⥧', + ldrushar: '⥋', + ldsh: '↲', + le: '≤', + lE: '≦', + LeftAngleBracket: '⟨', + LeftArrowBar: '⇤', + leftarrow: '←', + LeftArrow: '←', + Leftarrow: '⇐', + LeftArrowRightArrow: '⇆', + leftarrowtail: '↢', + LeftCeiling: '⌈', + LeftDoubleBracket: '⟦', + LeftDownTeeVector: '⥡', + LeftDownVectorBar: '⥙', + LeftDownVector: '⇃', + LeftFloor: '⌊', + leftharpoondown: '↽', + leftharpoonup: '↼', + leftleftarrows: '⇇', + leftrightarrow: '↔', + LeftRightArrow: '↔', + Leftrightarrow: '⇔', + leftrightarrows: '⇆', + leftrightharpoons: '⇋', + leftrightsquigarrow: '↭', + LeftRightVector: '⥎', + LeftTeeArrow: '↤', + LeftTee: '⊣', + LeftTeeVector: '⥚', + leftthreetimes: '⋋', + LeftTriangleBar: '⧏', + LeftTriangle: '⊲', + LeftTriangleEqual: '⊴', + LeftUpDownVector: '⥑', + LeftUpTeeVector: '⥠', + LeftUpVectorBar: '⥘', + LeftUpVector: '↿', + LeftVectorBar: '⥒', + LeftVector: '↼', + lEg: '⪋', + leg: '⋚', + leq: '≤', + leqq: '≦', + leqslant: '⩽', + lescc: '⪨', + les: '⩽', + lesdot: '⩿', + lesdoto: '⪁', + lesdotor: '⪃', + lesg: '⋚', + lesges: '⪓', + lessapprox: '⪅', + lessdot: '⋖', + lesseqgtr: '⋚', + lesseqqgtr: '⪋', + LessEqualGreater: '⋚', + LessFullEqual: '≦', + LessGreater: '≶', + lessgtr: '≶', + LessLess: '⪡', + lesssim: '≲', + LessSlantEqual: '⩽', + LessTilde: '≲', + lfisht: '⥼', + lfloor: '⌊', + Lfr: '𝔏', + lfr: '𝔩', + lg: '≶', + lgE: '⪑', + lHar: '⥢', + lhard: '↽', + lharu: '↼', + lharul: '⥪', + lhblk: '▄', + LJcy: 'Љ', + ljcy: 'љ', + llarr: '⇇', + ll: '≪', + Ll: '⋘', + llcorner: '⌞', + Lleftarrow: '⇚', + llhard: '⥫', + lltri: '◺', + Lmidot: 'Ŀ', + lmidot: 'ŀ', + lmoustache: '⎰', + lmoust: '⎰', + lnap: '⪉', + lnapprox: '⪉', + lne: '⪇', + lnE: '≨', + lneq: '⪇', + lneqq: '≨', + lnsim: '⋦', + loang: '⟬', + loarr: '⇽', + lobrk: '⟦', + longleftarrow: '⟵', + LongLeftArrow: '⟵', + Longleftarrow: '⟸', + longleftrightarrow: '⟷', + LongLeftRightArrow: '⟷', + Longleftrightarrow: '⟺', + longmapsto: '⟼', + longrightarrow: '⟶', + LongRightArrow: '⟶', + Longrightarrow: '⟹', + looparrowleft: '↫', + looparrowright: '↬', + lopar: '⦅', + Lopf: '𝕃', + lopf: '𝕝', + loplus: '⨭', + lotimes: '⨴', + lowast: '∗', + lowbar: '_', + LowerLeftArrow: '↙', + LowerRightArrow: '↘', + loz: '◊', + lozenge: '◊', + lozf: '⧫', + lpar: '(', + lparlt: '⦓', + lrarr: '⇆', + lrcorner: '⌟', + lrhar: '⇋', + lrhard: '⥭', + lrm: '', + lrtri: '⊿', + lsaquo: '‹', + lscr: '𝓁', + Lscr: 'ℒ', + lsh: '↰', + Lsh: '↰', + lsim: '≲', + lsime: '⪍', + lsimg: '⪏', + lsqb: '[', + lsquo: '‘', + lsquor: '‚', + Lstrok: 'Ł', + lstrok: 'ł', + ltcc: '⪦', + ltcir: '⩹', + lt: '<', + LT: '<', + Lt: '≪', + ltdot: '⋖', + lthree: '⋋', + ltimes: '⋉', + ltlarr: '⥶', + ltquest: '⩻', + ltri: '◃', + ltrie: '⊴', + ltrif: '◂', + ltrPar: '⦖', + lurdshar: '⥊', + luruhar: '⥦', + lvertneqq: '≨', + lvnE: '≨', + macr: '¯', + male: '♂', + malt: '✠', + maltese: '✠', + Map: '⤅', + map: '↦', + mapsto: '↦', + mapstodown: '↧', + mapstoleft: '↤', + mapstoup: '↥', + marker: '▮', + mcomma: '⨩', + Mcy: 'М', + mcy: 'м', + mdash: '—', + mDDot: '∺', + measuredangle: '∡', + MediumSpace: ' ', + Mellintrf: 'ℳ', + Mfr: '𝔐', + mfr: '𝔪', + mho: '℧', + micro: 'µ', + midast: '*', + midcir: '⫰', + mid: '∣', + middot: '·', + minusb: '⊟', + minus: '−', + minusd: '∸', + minusdu: '⨪', + MinusPlus: '∓', + mlcp: '⫛', + mldr: '…', + mnplus: '∓', + models: '⊧', + Mopf: '𝕄', + mopf: '𝕞', + mp: '∓', + mscr: '𝓂', + Mscr: 'ℳ', + mstpos: '∾', + Mu: 'Μ', + mu: 'μ', + multimap: '⊸', + mumap: '⊸', + nabla: '∇', + Nacute: 'Ń', + nacute: 'ń', + nang: '∠', + nap: '≉', + napE: '⩰', + napid: '≋', + napos: 'ʼn', + napprox: '≉', + natural: '♮', + naturals: 'ℕ', + natur: '♮', + nbsp: ' ', + nbump: '≎', + nbumpe: '≏', + ncap: '⩃', + Ncaron: 'Ň', + ncaron: 'ň', + Ncedil: 'Ņ', + ncedil: 'ņ', + ncong: '≇', + ncongdot: '⩭', + ncup: '⩂', + Ncy: 'Н', + ncy: 'н', + ndash: '–', + nearhk: '⤤', + nearr: '↗', + neArr: '⇗', + nearrow: '↗', + ne: '≠', + nedot: '≐', + NegativeMediumSpace: '', + NegativeThickSpace: '', + NegativeThinSpace: '', + NegativeVeryThinSpace: '', + nequiv: '≢', + nesear: '⤨', + nesim: '≂', + NestedGreaterGreater: '≫', + NestedLessLess: '≪', + NewLine: '\n', + nexist: '∄', + nexists: '∄', + Nfr: '𝔑', + nfr: '𝔫', + ngE: '≧', + nge: '≱', + ngeq: '≱', + ngeqq: '≧', + ngeqslant: '⩾', + nges: '⩾', + nGg: '⋙', + ngsim: '≵', + nGt: '≫', + ngt: '≯', + ngtr: '≯', + nGtv: '≫', + nharr: '↮', + nhArr: '⇎', + nhpar: '⫲', + ni: '∋', + nis: '⋼', + nisd: '⋺', + niv: '∋', + NJcy: 'Њ', + njcy: 'њ', + nlarr: '↚', + nlArr: '⇍', + nldr: '‥', + nlE: '≦', + nle: '≰', + nleftarrow: '↚', + nLeftarrow: '⇍', + nleftrightarrow: '↮', + nLeftrightarrow: '⇎', + nleq: '≰', + nleqq: '≦', + nleqslant: '⩽', + nles: '⩽', + nless: '≮', + nLl: '⋘', + nlsim: '≴', + nLt: '≪', + nlt: '≮', + nltri: '⋪', + nltrie: '⋬', + nLtv: '≪', + nmid: '∤', + NoBreak: '', + NonBreakingSpace: ' ', + nopf: '𝕟', + Nopf: 'ℕ', + Not: '⫬', + not: '¬', + NotCongruent: '≢', + NotCupCap: '≭', + NotDoubleVerticalBar: '∦', + NotElement: '∉', + NotEqual: '≠', + NotEqualTilde: '≂', + NotExists: '∄', + NotGreater: '≯', + NotGreaterEqual: '≱', + NotGreaterFullEqual: '≧', + NotGreaterGreater: '≫', + NotGreaterLess: '≹', + NotGreaterSlantEqual: '⩾', + NotGreaterTilde: '≵', + NotHumpDownHump: '≎', + NotHumpEqual: '≏', + notin: '∉', + notindot: '⋵', + notinE: '⋹', + notinva: '∉', + notinvb: '⋷', + notinvc: '⋶', + NotLeftTriangleBar: '⧏', + NotLeftTriangle: '⋪', + NotLeftTriangleEqual: '⋬', + NotLess: '≮', + NotLessEqual: '≰', + NotLessGreater: '≸', + NotLessLess: '≪', + NotLessSlantEqual: '⩽', + NotLessTilde: '≴', + NotNestedGreaterGreater: '⪢', + NotNestedLessLess: '⪡', + notni: '∌', + notniva: '∌', + notnivb: '⋾', + notnivc: '⋽', + NotPrecedes: '⊀', + NotPrecedesEqual: '⪯', + NotPrecedesSlantEqual: '⋠', + NotReverseElement: '∌', + NotRightTriangleBar: '⧐', + NotRightTriangle: '⋫', + NotRightTriangleEqual: '⋭', + NotSquareSubset: '⊏', + NotSquareSubsetEqual: '⋢', + NotSquareSuperset: '⊐', + NotSquareSupersetEqual: '⋣', + NotSubset: '⊂', + NotSubsetEqual: '⊈', + NotSucceeds: '⊁', + NotSucceedsEqual: '⪰', + NotSucceedsSlantEqual: '⋡', + NotSucceedsTilde: '≿', + NotSuperset: '⊃', + NotSupersetEqual: '⊉', + NotTilde: '≁', + NotTildeEqual: '≄', + NotTildeFullEqual: '≇', + NotTildeTilde: '≉', + NotVerticalBar: '∤', + nparallel: '∦', + npar: '∦', + nparsl: '⫽', + npart: '∂', + npolint: '⨔', + npr: '⊀', + nprcue: '⋠', + nprec: '⊀', + npreceq: '⪯', + npre: '⪯', + nrarrc: '⤳', + nrarr: '↛', + nrArr: '⇏', + nrarrw: '↝', + nrightarrow: '↛', + nRightarrow: '⇏', + nrtri: '⋫', + nrtrie: '⋭', + nsc: '⊁', + nsccue: '⋡', + nsce: '⪰', + Nscr: '𝒩', + nscr: '𝓃', + nshortmid: '∤', + nshortparallel: '∦', + nsim: '≁', + nsime: '≄', + nsimeq: '≄', + nsmid: '∤', + nspar: '∦', + nsqsube: '⋢', + nsqsupe: '⋣', + nsub: '⊄', + nsubE: '⫅', + nsube: '⊈', + nsubset: '⊂', + nsubseteq: '⊈', + nsubseteqq: '⫅', + nsucc: '⊁', + nsucceq: '⪰', + nsup: '⊅', + nsupE: '⫆', + nsupe: '⊉', + nsupset: '⊃', + nsupseteq: '⊉', + nsupseteqq: '⫆', + ntgl: '≹', + Ntilde: 'Ñ', + ntilde: 'ñ', + ntlg: '≸', + ntriangleleft: '⋪', + ntrianglelefteq: '⋬', + ntriangleright: '⋫', + ntrianglerighteq: '⋭', + Nu: 'Ν', + nu: 'ν', + num: '#', + numero: '№', + numsp: ' ', + nvap: '≍', + nvdash: '⊬', + nvDash: '⊭', + nVdash: '⊮', + nVDash: '⊯', + nvge: '≥', + nvgt: '>', + nvHarr: '⤄', + nvinfin: '⧞', + nvlArr: '⤂', + nvle: '≤', + nvlt: '>', + nvltrie: '⊴', + nvrArr: '⤃', + nvrtrie: '⊵', + nvsim: '∼', + nwarhk: '⤣', + nwarr: '↖', + nwArr: '⇖', + nwarrow: '↖', + nwnear: '⤧', + Oacute: 'Ó', + oacute: 'ó', + oast: '⊛', + Ocirc: 'Ô', + ocirc: 'ô', + ocir: '⊚', + Ocy: 'О', + ocy: 'о', + odash: '⊝', + Odblac: 'Ő', + odblac: 'ő', + odiv: '⨸', + odot: '⊙', + odsold: '⦼', + OElig: 'Œ', + oelig: 'œ', + ofcir: '⦿', + Ofr: '𝔒', + ofr: '𝔬', + ogon: '˛', + Ograve: 'Ò', + ograve: 'ò', + ogt: '⧁', + ohbar: '⦵', + ohm: 'Ω', + oint: '∮', + olarr: '↺', + olcir: '⦾', + olcross: '⦻', + oline: '‾', + olt: '⧀', + Omacr: 'Ō', + omacr: 'ō', + Omega: 'Ω', + omega: 'ω', + Omicron: 'Ο', + omicron: 'ο', + omid: '⦶', + ominus: '⊖', + Oopf: '𝕆', + oopf: '𝕠', + opar: '⦷', + OpenCurlyDoubleQuote: '“', + OpenCurlyQuote: '‘', + operp: '⦹', + oplus: '⊕', + orarr: '↻', + Or: '⩔', + or: '∨', + ord: '⩝', + order: 'ℴ', + orderof: 'ℴ', + ordf: 'ª', + ordm: 'º', + origof: '⊶', + oror: '⩖', + orslope: '⩗', + orv: '⩛', + oS: 'Ⓢ', + Oscr: '𝒪', + oscr: 'ℴ', + Oslash: 'Ø', + oslash: 'ø', + osol: '⊘', + Otilde: 'Õ', + otilde: 'õ', + otimesas: '⨶', + Otimes: '⨷', + otimes: '⊗', + Ouml: 'Ö', + ouml: 'ö', + ovbar: '⌽', + OverBar: '‾', + OverBrace: '⏞', + OverBracket: '⎴', + OverParenthesis: '⏜', + para: '¶', + parallel: '∥', + par: '∥', + parsim: '⫳', + parsl: '⫽', + part: '∂', + PartialD: '∂', + Pcy: 'П', + pcy: 'п', + percnt: '%', + period: '.', + permil: '‰', + perp: '⊥', + pertenk: '‱', + Pfr: '𝔓', + pfr: '𝔭', + Phi: 'Φ', + phi: 'φ', + phiv: 'ϕ', + phmmat: 'ℳ', + phone: '☎', + Pi: 'Π', + pi: 'π', + pitchfork: '⋔', + piv: 'ϖ', + planck: 'ℏ', + planckh: 'ℎ', + plankv: 'ℏ', + plusacir: '⨣', + plusb: '⊞', + pluscir: '⨢', + plus: '+', + plusdo: '∔', + plusdu: '⨥', + pluse: '⩲', + PlusMinus: '±', + plusmn: '±', + plussim: '⨦', + plustwo: '⨧', + pm: '±', + Poincareplane: 'ℌ', + pointint: '⨕', + popf: '𝕡', + Popf: 'ℙ', + pound: '£', + prap: '⪷', + Pr: '⪻', + pr: '≺', + prcue: '≼', + precapprox: '⪷', + prec: '≺', + preccurlyeq: '≼', + Precedes: '≺', + PrecedesEqual: '⪯', + PrecedesSlantEqual: '≼', + PrecedesTilde: '≾', + preceq: '⪯', + precnapprox: '⪹', + precneqq: '⪵', + precnsim: '⋨', + pre: '⪯', + prE: '⪳', + precsim: '≾', + prime: '′', + Prime: '″', + primes: 'ℙ', + prnap: '⪹', + prnE: '⪵', + prnsim: '⋨', + prod: '∏', + Product: '∏', + profalar: '⌮', + profline: '⌒', + profsurf: '⌓', + prop: '∝', + Proportional: '∝', + Proportion: '∷', + propto: '∝', + prsim: '≾', + prurel: '⊰', + Pscr: '𝒫', + pscr: '𝓅', + Psi: 'Ψ', + psi: 'ψ', + puncsp: ' ', + Qfr: '𝔔', + qfr: '𝔮', + qint: '⨌', + qopf: '𝕢', + Qopf: 'ℚ', + qprime: '⁗', + Qscr: '𝒬', + qscr: '𝓆', + quaternions: 'ℍ', + quatint: '⨖', + quest: '?', + questeq: '≟', + quot: '"', + QUOT: '"', + rAarr: '⇛', + race: '∽', + Racute: 'Ŕ', + racute: 'ŕ', + radic: '√', + raemptyv: '⦳', + rang: '⟩', + Rang: '⟫', + rangd: '⦒', + range: '⦥', + rangle: '⟩', + raquo: '»', + rarrap: '⥵', + rarrb: '⇥', + rarrbfs: '⤠', + rarrc: '⤳', + rarr: '→', + Rarr: '↠', + rArr: '⇒', + rarrfs: '⤞', + rarrhk: '↪', + rarrlp: '↬', + rarrpl: '⥅', + rarrsim: '⥴', + Rarrtl: '⤖', + rarrtl: '↣', + rarrw: '↝', + ratail: '⤚', + rAtail: '⤜', + ratio: '∶', + rationals: 'ℚ', + rbarr: '⤍', + rBarr: '⤏', + RBarr: '⤐', + rbbrk: '❳', + rbrace: '}', + rbrack: ']', + rbrke: '⦌', + rbrksld: '⦎', + rbrkslu: '⦐', + Rcaron: 'Ř', + rcaron: 'ř', + Rcedil: 'Ŗ', + rcedil: 'ŗ', + rceil: '⌉', + rcub: '}', + Rcy: 'Р', + rcy: 'р', + rdca: '⤷', + rdldhar: '⥩', + rdquo: '”', + rdquor: '”', + rdsh: '↳', + real: 'ℜ', + realine: 'ℛ', + realpart: 'ℜ', + reals: 'ℝ', + Re: 'ℜ', + rect: '▭', + reg: '®', + REG: '®', + ReverseElement: '∋', + ReverseEquilibrium: '⇋', + ReverseUpEquilibrium: '⥯', + rfisht: '⥽', + rfloor: '⌋', + rfr: '𝔯', + Rfr: 'ℜ', + rHar: '⥤', + rhard: '⇁', + rharu: '⇀', + rharul: '⥬', + Rho: 'Ρ', + rho: 'ρ', + rhov: 'ϱ', + RightAngleBracket: '⟩', + RightArrowBar: '⇥', + rightarrow: '→', + RightArrow: '→', + Rightarrow: '⇒', + RightArrowLeftArrow: '⇄', + rightarrowtail: '↣', + RightCeiling: '⌉', + RightDoubleBracket: '⟧', + RightDownTeeVector: '⥝', + RightDownVectorBar: '⥕', + RightDownVector: '⇂', + RightFloor: '⌋', + rightharpoondown: '⇁', + rightharpoonup: '⇀', + rightleftarrows: '⇄', + rightleftharpoons: '⇌', + rightrightarrows: '⇉', + rightsquigarrow: '↝', + RightTeeArrow: '↦', + RightTee: '⊢', + RightTeeVector: '⥛', + rightthreetimes: '⋌', + RightTriangleBar: '⧐', + RightTriangle: '⊳', + RightTriangleEqual: '⊵', + RightUpDownVector: '⥏', + RightUpTeeVector: '⥜', + RightUpVectorBar: '⥔', + RightUpVector: '↾', + RightVectorBar: '⥓', + RightVector: '⇀', + ring: '˚', + risingdotseq: '≓', + rlarr: '⇄', + rlhar: '⇌', + rlm: '', + rmoustache: '⎱', + rmoust: '⎱', + rnmid: '⫮', + roang: '⟭', + roarr: '⇾', + robrk: '⟧', + ropar: '⦆', + ropf: '𝕣', + Ropf: 'ℝ', + roplus: '⨮', + rotimes: '⨵', + RoundImplies: '⥰', + rpar: ')', + rpargt: '⦔', + rppolint: '⨒', + rrarr: '⇉', + Rrightarrow: '⇛', + rsaquo: '›', + rscr: '𝓇', + Rscr: 'ℛ', + rsh: '↱', + Rsh: '↱', + rsqb: ']', + rsquo: '’', + rsquor: '’', + rthree: '⋌', + rtimes: '⋊', + rtri: '▹', + rtrie: '⊵', + rtrif: '▸', + rtriltri: '⧎', + RuleDelayed: '⧴', + ruluhar: '⥨', + rx: '℞', + Sacute: 'Ś', + sacute: 'ś', + sbquo: '‚', + scap: '⪸', + Scaron: 'Š', + scaron: 'š', + Sc: '⪼', + sc: '≻', + sccue: '≽', + sce: '⪰', + scE: '⪴', + Scedil: 'Ş', + scedil: 'ş', + Scirc: 'Ŝ', + scirc: 'ŝ', + scnap: '⪺', + scnE: '⪶', + scnsim: '⋩', + scpolint: '⨓', + scsim: '≿', + Scy: 'С', + scy: 'с', + sdotb: '⊡', + sdot: '⋅', + sdote: '⩦', + searhk: '⤥', + searr: '↘', + seArr: '⇘', + searrow: '↘', + sect: '§', + semi: ';', + seswar: '⤩', + setminus: '∖', + setmn: '∖', + sext: '✶', + Sfr: '𝔖', + sfr: '𝔰', + sfrown: '⌢', + sharp: '♯', + SHCHcy: 'Щ', + shchcy: 'щ', + SHcy: 'Ш', + shcy: 'ш', + ShortDownArrow: '↓', + ShortLeftArrow: '←', + shortmid: '∣', + shortparallel: '∥', + ShortRightArrow: '→', + ShortUpArrow: '↑', + shy: '', + Sigma: 'Σ', + sigma: 'σ', + sigmaf: 'ς', + sigmav: 'ς', + sim: '∼', + simdot: '⩪', + sime: '≃', + simeq: '≃', + simg: '⪞', + simgE: '⪠', + siml: '⪝', + simlE: '⪟', + simne: '≆', + simplus: '⨤', + simrarr: '⥲', + slarr: '←', + SmallCircle: '∘', + smallsetminus: '∖', + smashp: '⨳', + smeparsl: '⧤', + smid: '∣', + smile: '⌣', + smt: '⪪', + smte: '⪬', + smtes: '⪬', + SOFTcy: 'Ь', + softcy: 'ь', + solbar: '⌿', + solb: '⧄', + sol: '/', + Sopf: '𝕊', + sopf: '𝕤', + spades: '♠', + spadesuit: '♠', + spar: '∥', + sqcap: '⊓', + sqcaps: '⊓', + sqcup: '⊔', + sqcups: '⊔', + Sqrt: '√', + sqsub: '⊏', + sqsube: '⊑', + sqsubset: '⊏', + sqsubseteq: '⊑', + sqsup: '⊐', + sqsupe: '⊒', + sqsupset: '⊐', + sqsupseteq: '⊒', + square: '□', + Square: '□', + SquareIntersection: '⊓', + SquareSubset: '⊏', + SquareSubsetEqual: '⊑', + SquareSuperset: '⊐', + SquareSupersetEqual: '⊒', + SquareUnion: '⊔', + squarf: '▪', + squ: '□', + squf: '▪', + srarr: '→', + Sscr: '𝒮', + sscr: '𝓈', + ssetmn: '∖', + ssmile: '⌣', + sstarf: '⋆', + Star: '⋆', + star: '☆', + starf: '★', + straightepsilon: 'ϵ', + straightphi: 'ϕ', + strns: '¯', + sub: '⊂', + Sub: '⋐', + subdot: '⪽', + subE: '⫅', + sube: '⊆', + subedot: '⫃', + submult: '⫁', + subnE: '⫋', + subne: '⊊', + subplus: '⪿', + subrarr: '⥹', + subset: '⊂', + Subset: '⋐', + subseteq: '⊆', + subseteqq: '⫅', + SubsetEqual: '⊆', + subsetneq: '⊊', + subsetneqq: '⫋', + subsim: '⫇', + subsub: '⫕', + subsup: '⫓', + succapprox: '⪸', + succ: '≻', + succcurlyeq: '≽', + Succeeds: '≻', + SucceedsEqual: '⪰', + SucceedsSlantEqual: '≽', + SucceedsTilde: '≿', + succeq: '⪰', + succnapprox: '⪺', + succneqq: '⪶', + succnsim: '⋩', + succsim: '≿', + SuchThat: '∋', + sum: '∑', + Sum: '∑', + sung: '♪', + sup1: '¹', + sup2: '²', + sup3: '³', + sup: '⊃', + Sup: '⋑', + supdot: '⪾', + supdsub: '⫘', + supE: '⫆', + supe: '⊇', + supedot: '⫄', + Superset: '⊃', + SupersetEqual: '⊇', + suphsol: '⟉', + suphsub: '⫗', + suplarr: '⥻', + supmult: '⫂', + supnE: '⫌', + supne: '⊋', + supplus: '⫀', + supset: '⊃', + Supset: '⋑', + supseteq: '⊇', + supseteqq: '⫆', + supsetneq: '⊋', + supsetneqq: '⫌', + supsim: '⫈', + supsub: '⫔', + supsup: '⫖', + swarhk: '⤦', + swarr: '↙', + swArr: '⇙', + swarrow: '↙', + swnwar: '⤪', + szlig: 'ß', + Tab: ' ', + target: '⌖', + Tau: 'Τ', + tau: 'τ', + tbrk: '⎴', + Tcaron: 'Ť', + tcaron: 'ť', + Tcedil: 'Ţ', + tcedil: 'ţ', + Tcy: 'Т', + tcy: 'т', + tdot: '⃛', + telrec: '⌕', + Tfr: '𝔗', + tfr: '𝔱', + there4: '∴', + therefore: '∴', + Therefore: '∴', + Theta: 'Θ', + theta: 'θ', + thetasym: 'ϑ', + thetav: 'ϑ', + thickapprox: '≈', + thicksim: '∼', + ThickSpace: ' ', + ThinSpace: ' ', + thinsp: ' ', + thkap: '≈', + thksim: '∼', + THORN: 'Þ', + thorn: 'þ', + tilde: '˜', + Tilde: '∼', + TildeEqual: '≃', + TildeFullEqual: '≅', + TildeTilde: '≈', + timesbar: '⨱', + timesb: '⊠', + times: '×', + timesd: '⨰', + tint: '∭', + toea: '⤨', + topbot: '⌶', + topcir: '⫱', + top: '⊤', + Topf: '𝕋', + topf: '𝕥', + topfork: '⫚', + tosa: '⤩', + tprime: '‴', + trade: '™', + TRADE: '™', + triangle: '▵', + triangledown: '▿', + triangleleft: '◃', + trianglelefteq: '⊴', + triangleq: '≜', + triangleright: '▹', + trianglerighteq: '⊵', + tridot: '◬', + trie: '≜', + triminus: '⨺', + TripleDot: '⃛', + triplus: '⨹', + trisb: '⧍', + tritime: '⨻', + trpezium: '⏢', + Tscr: '𝒯', + tscr: '𝓉', + TScy: 'Ц', + tscy: 'ц', + TSHcy: 'Ћ', + tshcy: 'ћ', + Tstrok: 'Ŧ', + tstrok: 'ŧ', + twixt: '≬', + twoheadleftarrow: '↞', + twoheadrightarrow: '↠', + Uacute: 'Ú', + uacute: 'ú', + uarr: '↑', + Uarr: '↟', + uArr: '⇑', + Uarrocir: '⥉', + Ubrcy: 'Ў', + ubrcy: 'ў', + Ubreve: 'Ŭ', + ubreve: 'ŭ', + Ucirc: 'Û', + ucirc: 'û', + Ucy: 'У', + ucy: 'у', + udarr: '⇅', + Udblac: 'Ű', + udblac: 'ű', + udhar: '⥮', + ufisht: '⥾', + Ufr: '𝔘', + ufr: '𝔲', + Ugrave: 'Ù', + ugrave: 'ù', + uHar: '⥣', + uharl: '↿', + uharr: '↾', + uhblk: '▀', + ulcorn: '⌜', + ulcorner: '⌜', + ulcrop: '⌏', + ultri: '◸', + Umacr: 'Ū', + umacr: 'ū', + uml: '¨', + UnderBar: '_', + UnderBrace: '⏟', + UnderBracket: '⎵', + UnderParenthesis: '⏝', + Union: '⋃', + UnionPlus: '⊎', + Uogon: 'Ų', + uogon: 'ų', + Uopf: '𝕌', + uopf: '𝕦', + UpArrowBar: '⤒', + uparrow: '↑', + UpArrow: '↑', + Uparrow: '⇑', + UpArrowDownArrow: '⇅', + updownarrow: '↕', + UpDownArrow: '↕', + Updownarrow: '⇕', + UpEquilibrium: '⥮', + upharpoonleft: '↿', + upharpoonright: '↾', + uplus: '⊎', + UpperLeftArrow: '↖', + UpperRightArrow: '↗', + upsi: 'υ', + Upsi: 'ϒ', + upsih: 'ϒ', + Upsilon: 'Υ', + upsilon: 'υ', + UpTeeArrow: '↥', + UpTee: '⊥', + upuparrows: '⇈', + urcorn: '⌝', + urcorner: '⌝', + urcrop: '⌎', + Uring: 'Ů', + uring: 'ů', + urtri: '◹', + Uscr: '𝒰', + uscr: '𝓊', + utdot: '⋰', + Utilde: 'Ũ', + utilde: 'ũ', + utri: '▵', + utrif: '▴', + uuarr: '⇈', + Uuml: 'Ü', + uuml: 'ü', + uwangle: '⦧', + vangrt: '⦜', + varepsilon: 'ϵ', + varkappa: 'ϰ', + varnothing: '∅', + varphi: 'ϕ', + varpi: 'ϖ', + varpropto: '∝', + varr: '↕', + vArr: '⇕', + varrho: 'ϱ', + varsigma: 'ς', + varsubsetneq: '⊊', + varsubsetneqq: '⫋', + varsupsetneq: '⊋', + varsupsetneqq: '⫌', + vartheta: 'ϑ', + vartriangleleft: '⊲', + vartriangleright: '⊳', + vBar: '⫨', + Vbar: '⫫', + vBarv: '⫩', + Vcy: 'В', + vcy: 'в', + vdash: '⊢', + vDash: '⊨', + Vdash: '⊩', + VDash: '⊫', + Vdashl: '⫦', + veebar: '⊻', + vee: '∨', + Vee: '⋁', + veeeq: '≚', + vellip: '⋮', + verbar: '|', + Verbar: '‖', + vert: '|', + Vert: '‖', + VerticalBar: '∣', + VerticalLine: '|', + VerticalSeparator: '❘', + VerticalTilde: '≀', + VeryThinSpace: ' ', + Vfr: '𝔙', + vfr: '𝔳', + vltri: '⊲', + vnsub: '⊂', + vnsup: '⊃', + Vopf: '𝕍', + vopf: '𝕧', + vprop: '∝', + vrtri: '⊳', + Vscr: '𝒱', + vscr: '𝓋', + vsubnE: '⫋', + vsubne: '⊊', + vsupnE: '⫌', + vsupne: '⊋', + Vvdash: '⊪', + vzigzag: '⦚', + Wcirc: 'Ŵ', + wcirc: 'ŵ', + wedbar: '⩟', + wedge: '∧', + Wedge: '⋀', + wedgeq: '≙', + weierp: '℘', + Wfr: '𝔚', + wfr: '𝔴', + Wopf: '𝕎', + wopf: '𝕨', + wp: '℘', + wr: '≀', + wreath: '≀', + Wscr: '𝒲', + wscr: '𝓌', + xcap: '⋂', + xcirc: '◯', + xcup: '⋃', + xdtri: '▽', + Xfr: '𝔛', + xfr: '𝔵', + xharr: '⟷', + xhArr: '⟺', + Xi: 'Ξ', + xi: 'ξ', + xlarr: '⟵', + xlArr: '⟸', + xmap: '⟼', + xnis: '⋻', + xodot: '⨀', + Xopf: '𝕏', + xopf: '𝕩', + xoplus: '⨁', + xotime: '⨂', + xrarr: '⟶', + xrArr: '⟹', + Xscr: '𝒳', + xscr: '𝓍', + xsqcup: '⨆', + xuplus: '⨄', + xutri: '△', + xvee: '⋁', + xwedge: '⋀', + Yacute: 'Ý', + yacute: 'ý', + YAcy: 'Я', + yacy: 'я', + Ycirc: 'Ŷ', + ycirc: 'ŷ', + Ycy: 'Ы', + ycy: 'ы', + yen: '¥', + Yfr: '𝔜', + yfr: '𝔶', + YIcy: 'Ї', + yicy: 'ї', + Yopf: '𝕐', + yopf: '𝕪', + Yscr: '𝒴', + yscr: '𝓎', + YUcy: 'Ю', + yucy: 'ю', + yuml: 'ÿ', + Yuml: 'Ÿ', + Zacute: 'Ź', + zacute: 'ź', + Zcaron: 'Ž', + zcaron: 'ž', + Zcy: 'З', + zcy: 'з', + Zdot: 'Ż', + zdot: 'ż', + zeetrf: 'ℨ', + ZeroWidthSpace: '', + Zeta: 'Ζ', + zeta: 'ζ', + zfr: '𝔷', + Zfr: 'ℨ', + ZHcy: 'Ж', + zhcy: 'ж', + zigrarr: '⇝', + zopf: '𝕫', + Zopf: 'ℤ', + Zscr: '𝒵', + zscr: '𝓏', + zwj: '', + zwnj: '' }; + + // Constants for character codes: + + var C_NEWLINE = 10; + var C_SPACE = 32; + var C_ASTERISK = 42; + var C_UNDERSCORE = 95; + var C_BACKTICK = 96; + var C_OPEN_BRACKET = 91; + var C_CLOSE_BRACKET = 93; + var C_LESSTHAN = 60; + var C_GREATERTHAN = 62; + var C_BANG = 33; + var C_BACKSLASH = 92; + var C_AMPERSAND = 38; + var C_OPEN_PAREN = 40; + var C_COLON = 58; + + // Some regexps used in inline parser: + + var ESCAPABLE = '[!"#$%&\'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]'; + var ESCAPED_CHAR = '\\\\' + ESCAPABLE; + var IN_DOUBLE_QUOTES = '"(' + ESCAPED_CHAR + '|[^"\\x00])*"'; + var IN_SINGLE_QUOTES = '\'(' + ESCAPED_CHAR + '|[^\'\\x00])*\''; + var IN_PARENS = '\\((' + ESCAPED_CHAR + '|[^)\\x00])*\\)'; + var REG_CHAR = '[^\\\\()\\x00-\\x20]'; + var IN_PARENS_NOSP = '\\((' + REG_CHAR + '|' + ESCAPED_CHAR + ')*\\)'; + var TAGNAME = '[A-Za-z][A-Za-z0-9]*'; + var BLOCKTAGNAME = '(?:article|header|aside|hgroup|iframe|blockquote|hr|body|li|map|button|object|canvas|ol|caption|output|col|p|colgroup|pre|dd|progress|div|section|dl|table|td|dt|tbody|embed|textarea|fieldset|tfoot|figcaption|th|figure|thead|footer|footer|tr|form|ul|h1|h2|h3|h4|h5|h6|video|script|style)'; + var ATTRIBUTENAME = '[a-zA-Z_:][a-zA-Z0-9:._-]*'; + var UNQUOTEDVALUE = "[^\"'=<>`\\x00-\\x20]+"; + var SINGLEQUOTEDVALUE = "'[^']*'"; + var DOUBLEQUOTEDVALUE = '"[^"]*"'; + var ATTRIBUTEVALUE = "(?:" + UNQUOTEDVALUE + "|" + SINGLEQUOTEDVALUE + "|" + DOUBLEQUOTEDVALUE + ")"; + var ATTRIBUTEVALUESPEC = "(?:" + "\\s*=" + "\\s*" + ATTRIBUTEVALUE + ")"; + var ATTRIBUTE = "(?:" + "\\s+" + ATTRIBUTENAME + ATTRIBUTEVALUESPEC + "?)"; + var OPENTAG = "<" + TAGNAME + ATTRIBUTE + "*" + "\\s*/?>"; + var CLOSETAG = "</" + TAGNAME + "\\s*[>]"; + var OPENBLOCKTAG = "<" + BLOCKTAGNAME + ATTRIBUTE + "*" + "\\s*/?>"; + var CLOSEBLOCKTAG = "</" + BLOCKTAGNAME + "\\s*[>]"; + var HTMLCOMMENT = "<!--([^-]+|[-][^-]+)*-->"; + var PROCESSINGINSTRUCTION = "[<][?].*?[?][>]"; + var DECLARATION = "<![A-Z]+" + "\\s+[^>]*>"; + var CDATA = "<!\\[CDATA\\[([^\\]]+|\\][^\\]]|\\]\\][^>])*\\]\\]>"; + var HTMLTAG = "(?:" + OPENTAG + "|" + CLOSETAG + "|" + HTMLCOMMENT + "|" + + PROCESSINGINSTRUCTION + "|" + DECLARATION + "|" + CDATA + ")"; + var HTMLBLOCKOPEN = "<(?:" + BLOCKTAGNAME + "[\\s/>]" + "|" + + "/" + BLOCKTAGNAME + "[\\s>]" + "|" + "[?!])"; + var ENTITY = "&(?:#x[a-f0-9]{1,8}|#[0-9]{1,8}|[a-z][a-z0-9]{1,31});"; + + var reHtmlTag = new RegExp('^' + HTMLTAG, 'i'); + + var reHtmlBlockOpen = new RegExp('^' + HTMLBLOCKOPEN, 'i'); + + var reLinkTitle = new RegExp( + '^(?:"(' + ESCAPED_CHAR + '|[^"\\x00])*"' + + '|' + + '\'(' + ESCAPED_CHAR + '|[^\'\\x00])*\'' + + '|' + + '\\((' + ESCAPED_CHAR + '|[^)\\x00])*\\))'); + + var reLinkDestinationBraces = new RegExp( + '^(?:[<](?:[^<>\\n\\\\\\x00]' + '|' + ESCAPED_CHAR + '|' + '\\\\)*[>])'); + + var reLinkDestination = new RegExp( + '^(?:' + REG_CHAR + '+|' + ESCAPED_CHAR + '|' + IN_PARENS_NOSP + ')*'); + + var reEscapable = new RegExp(ESCAPABLE); + + var reAllEscapedChar = new RegExp('\\\\(' + ESCAPABLE + ')', 'g'); + + var reEscapedChar = new RegExp('^\\\\(' + ESCAPABLE + ')'); + + var reAllTab = /\t/g; + + var reHrule = /^(?:(?:\* *){3,}|(?:_ *){3,}|(?:- *){3,}) *$/; + + var reEntityHere = new RegExp('^' + ENTITY, 'i'); + + var reEntity = new RegExp(ENTITY, 'gi'); + + // Matches a character with a special meaning in markdown, + // or a string of non-special characters. Note: we match + // clumps of _ or * or `, because they need to be handled in groups. + var reMain = /^(?:[_*`\n]+|[\[\]\\!<&*_]|(?: *[^\n `\[\]\\!<&*_]+)+|[ \n]+)/m; + + // UTILITY FUNCTIONS + // polyfill for fromCodePoint: + // https://github.com/mathiasbynens/String.fromCodePoint + /*! http://mths.be/fromcodepoint v0.2.1 by @mathias */ + if (!String.fromCodePoint) { + (function() { + var defineProperty = (function() { + // IE 8 only supports `Object.defineProperty` on DOM elements + try { + var object = {}; + var $defineProperty = Object.defineProperty; + var result = $defineProperty(object, object, object) && $defineProperty; + } catch(error) {} + return result; + }()); + var stringFromCharCode = String.fromCharCode; + var floor = Math.floor; + var fromCodePoint = function(_) { + var MAX_SIZE = 0x4000; + var codeUnits = []; + var highSurrogate; + var lowSurrogate; + var index = -1; + var length = arguments.length; + if (!length) { + return ''; + } + var result = ''; + while (++index < length) { + var codePoint = Number(arguments[index]); + if ( + !isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity` + codePoint < 0 || // not a valid Unicode code point + codePoint > 0x10FFFF || // not a valid Unicode code point + floor(codePoint) != codePoint // not an integer + ) { + return String.fromCharCode(0xFFFD); + } + if (codePoint <= 0xFFFF) { // BMP code point + codeUnits.push(codePoint); + } else { // Astral code point; split in surrogate halves + // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + codePoint -= 0x10000; + highSurrogate = (codePoint >> 10) + 0xD800; + lowSurrogate = (codePoint % 0x400) + 0xDC00; + codeUnits.push(highSurrogate, lowSurrogate); + } + if (index + 1 == length || codeUnits.length > MAX_SIZE) { + result += stringFromCharCode.apply(null, codeUnits); + codeUnits.length = 0; + } + } + return result; + }; + if (defineProperty) { + defineProperty(String, 'fromCodePoint', { + 'value': fromCodePoint, + 'configurable': true, + 'writable': true + }); + } else { + String.fromCodePoint = fromCodePoint; + } + }()); } - } - // If we got here, we didn't match a closing backtick sequence. - inlines.push({ t: 'Str', c: ticks }); - this.pos = afterOpenTicks; - return (this.pos - startpos); -}; - -// Parse a backslash-escaped special character, adding either the escaped -// character, a hard line break (if the backslash is followed by a newline), -// or a literal backslash to the 'inlines' list. -var parseEscaped = function(inlines) { - var subj = this.subject, - pos = this.pos; - if (subj[pos] === '\\') { - if (subj[pos + 1] === '\n') { - inlines.push({ t: 'Hardbreak' }); - this.pos = this.pos + 2; - return 2; - } else if (reEscapable.test(subj[pos + 1])) { - inlines.push({ t: 'Str', c: subj[pos + 1] }); - this.pos = this.pos + 2; - return 2; - } else { - this.pos++; - inlines.push({t: 'Str', c: '\\'}); - return 1; - } - } else { - return 0; - } -}; - -// Attempt to parse an autolink (URL or email in pointy brackets). -var parseAutolink = function(inlines) { - var m; - var dest; - if ((m = this.match(/^<([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/))) { // email autolink - dest = m.slice(1,-1); - inlines.push({ t: 'Link', label: [{ t: 'Str', c: dest }], - destination: 'mailto:' + dest }); - return m.length; - } else if ((m = this.match(/^<(?:coap|doi|javascript|aaa|aaas|about|acap|cap|cid|crid|data|dav|dict|dns|file|ftp|geo|go|gopher|h323|http|https|iax|icap|im|imap|info|ipp|iris|iris.beep|iris.xpc|iris.xpcs|iris.lwz|ldap|mailto|mid|msrp|msrps|mtqp|mupdate|news|nfs|ni|nih|nntp|opaquelocktoken|pop|pres|rtsp|service|session|shttp|sieve|sip|sips|sms|snmp|soap.beep|soap.beeps|tag|tel|telnet|tftp|thismessage|tn3270|tip|tv|urn|vemmi|ws|wss|xcon|xcon-userid|xmlrpc.beep|xmlrpc.beeps|xmpp|z39.50r|z39.50s|adiumxtra|afp|afs|aim|apt|attachment|aw|beshare|bitcoin|bolo|callto|chrome|chrome-extension|com-eventbrite-attendee|content|cvs|dlna-playsingle|dlna-playcontainer|dtn|dvb|ed2k|facetime|feed|finger|fish|gg|git|gizmoproject|gtalk|hcp|icon|ipn|irc|irc6|ircs|itms|jar|jms|keyparc|lastfm|ldaps|magnet|maps|market|message|mms|ms-help|msnim|mumble|mvn|notes|oid|palm|paparazzi|platform|proxy|psyc|query|res|resource|rmi|rsync|rtmp|secondlife|sftp|sgn|skype|smb|soldat|spotify|ssh|steam|svn|teamspeak|things|udp|unreal|ut2004|ventrilo|view-source|webcal|wtai|wyciwyg|xfire|xri|ymsgr):[^<>\x00-\x20]*>/i))) { - dest = m.slice(1,-1); - inlines.push({ t: 'Link', label: [{ t: 'Str', c: dest }], - destination: dest }); - return m.length; - } else { - return 0; - } -}; - -// Attempt to parse a raw HTML tag. -var parseHtmlTag = function(inlines) { - var m = this.match(reHtmlTag); - if (m) { - inlines.push({ t: 'Html', c: m }); - return m.length; - } else { - return 0; - } -}; - -// Scan a sequence of characters == c, and return information about -// the number of delimiters and whether they are positioned such that -// they can open and/or close emphasis or strong emphasis. A utility -// function for strong/emph parsing. -var scanDelims = function(c) { - var numdelims = 0; - var first_close_delims = 0; - var char_before, char_after; - var startpos = this.pos; - - char_before = this.pos === 0 ? '\n' : - this.subject[this.pos - 1]; - - while (this.peek() === c) { - numdelims++; - this.pos++; - } - - char_after = this.peek() || '\n'; - - var can_open = numdelims > 0 && numdelims <= 3 && !(/\s/.test(char_after)); - var can_close = numdelims > 0 && numdelims <= 3 && !(/\s/.test(char_before)); - if (c === '_') { - can_open = can_open && !((/[a-z0-9]/i).test(char_before)); - can_close = can_close && !((/[a-z0-9]/i).test(char_after)); - } - this.pos = startpos; - return { numdelims: numdelims, - can_open: can_open, - can_close: can_close }; -}; - -// Attempt to parse emphasis or strong emphasis in an efficient way, -// with no backtracking. -var parseEmphasis = function(inlines) { - var startpos = this.pos; - var c ; - var first_close = 0; - var nxt = this.peek(); - if (nxt == '*' || nxt == '_') { - c = nxt; - } else { - return 0; - } - - var numdelims; - var delimpos; - - // Get opening delimiters. - res = this.scanDelims(c); - numdelims = res.numdelims; - this.pos += numdelims; - // We provisionally add a literal string. If we match appropriate - // closing delimiters, we'll change this to Strong or Emph. - inlines.push({t: 'Str', - c: this.subject.substr(this.pos - numdelims, numdelims)}); - // Record the position of this opening delimiter: - delimpos = inlines.length - 1; - - if (!res.can_open || numdelims === 0) { - return 0; - } - - var first_close_delims = 0; - - switch (numdelims) { - case 1: // we started with * or _ - while (true) { - res = this.scanDelims(c); - if (res.numdelims >= 1 && res.can_close) { - this.pos += 1; - // Convert the inline at delimpos, currently a string with the delim, - // into an Emph whose contents are the succeeding inlines - inlines[delimpos].t = 'Emph'; - inlines[delimpos].c = inlines.slice(delimpos + 1); - inlines.splice(delimpos + 1); - break; - } else { - if (this.parseInline(inlines) === 0) { - break; - } - } - } - return (this.pos - startpos); - - case 2: // We started with ** or __ - while (true) { - res = this.scanDelims(c); - if (res.numdelims >= 2 && res.can_close) { - this.pos += 2; - inlines[delimpos].t = 'Strong'; - inlines[delimpos].c = inlines.slice(delimpos + 1); - inlines.splice(delimpos + 1); - break; - } else { - if (this.parseInline(inlines) === 0) { - break; - } - } - } - return (this.pos - startpos); - - case 3: // We started with *** or ___ - while (true) { - res = this.scanDelims(c); - if (res.numdelims >= 1 && res.numdelims <= 3 && res.can_close && - res.numdelims != first_close_delims) { - - if (first_close_delims === 1 && numdelims > 2) { - res.numdelims = 2; - } else if (first_close_delims === 2) { - res.numdelims = 1; - } else if (res.numdelims === 3) { - // If we opened with ***, then we interpret *** as ** followed by * - // giving us <strong><em> - res.numdelims = 1; - } - - this.pos += res.numdelims; - - if (first_close > 0) { // if we've already passed the first closer: - inlines[delimpos].t = first_close_delims === 1 ? 'Strong' : 'Emph'; - inlines[delimpos].c = [ - { t: first_close_delims === 1 ? 'Emph' : 'Strong', - c: inlines.slice(delimpos + 1, first_close)} - ].concat(inlines.slice(first_close + 1)); - inlines.splice(delimpos + 1); - break; - } else { // this is the first closer; for now, add literal string; - // we'll change this when he hit the second closer - inlines.push({t: 'Str', - c: this.subject.slice(this.pos - res.numdelims, - this.pos) }); - first_close = inlines.length - 1; - first_close_delims = res.numdelims; - } - } else { // parse another inline element, til we hit the end - if (this.parseInline(inlines) === 0) { - break; - } - } - } - return (this.pos - startpos); - - default: - return res; - } - - return 0; -}; - -// Attempt to parse link title (sans quotes), returning the string -// or null if no match. -var parseLinkTitle = function() { - var title = this.match(reLinkTitle); - if (title) { - // chop off quotes from title and unescape: - return unescape(title.substr(1, title.length - 2)); - } else { - return null; - } -}; - -// Attempt to parse link destination, returning the string or -// null if no match. -var parseLinkDestination = function() { - var res = this.match(reLinkDestinationBraces); - if (res) { // chop off surrounding <..>: - return unescape(res.substr(1, res.length - 2)); - } else { - res = this.match(reLinkDestination); - if (res !== null) { - return unescape(res); - } else { - return null; - } - } -}; - -// Attempt to parse a link label, returning number of characters parsed. -var parseLinkLabel = function() { - if (this.peek() != '[') { - return 0; - } - var startpos = this.pos; - var nest_level = 0; - if (this.label_nest_level > 0) { - // If we've already checked to the end of this subject - // for a label, even with a different starting [, we - // know we won't find one here and we can just return. - // This avoids lots of backtracking. - // Note: nest level 1 would be: [foo [bar] - // nest level 2 would be: [foo [bar [baz] - this.label_nest_level--; - return 0; - } - this.pos++; // advance past [ - var c; - while ((c = this.peek()) && (c != ']' || nest_level > 0)) { - switch (c) { - case '`': - this.parseBackticks([]); - break; - case '<': - this.parseAutolink([]) || this.parseHtmlTag([]) || this.parseString([]); - break; - case '[': // nested [] - nest_level++; - this.pos++; - break; - case ']': // nested [] - nest_level--; - this.pos++; - break; - case '\\': - this.parseEscaped([]); - break; - default: - this.parseString([]); - } - } - if (c === ']') { - this.label_nest_level = 0; - this.pos++; // advance past ] - return this.pos - startpos; - } else { - if (!c) { - this.label_nest_level = nest_level; - } - this.pos = startpos; - return 0; - } -}; - -// Parse raw link label, including surrounding [], and return -// inline contents. (Note: this is not a method of InlineParser.) -var parseRawLabel = function(s) { - // note: parse without a refmap; we don't want links to resolve - // in nested brackets! - return new InlineParser().parse(s.substr(1, s.length - 2), {}); -}; - -// Attempt to parse a link. If successful, add the link to -// inlines. -var parseLink = function(inlines) { - var startpos = this.pos; - var reflabel; - var n; - var dest; - var title; - - n = this.parseLinkLabel(); - if (n === 0) { - return 0; - } - var afterlabel = this.pos; - var rawlabel = this.subject.substr(startpos, n); - - // if we got this far, we've parsed a label. - // Try to parse an explicit link: [label](url "title") - if (this.peek() == '(') { - this.pos++; - if (this.spnl() && - ((dest = this.parseLinkDestination()) !== null) && - this.spnl() && - // make sure there's a space before the title: - (/^\s/.test(this.subject[this.pos - 1]) && - (title = this.parseLinkTitle() || '') || true) && - this.spnl() && - this.match(/^\)/)) { - inlines.push({ t: 'Link', - destination: dest, - title: title, - label: parseRawLabel(rawlabel) }); - return this.pos - startpos; - } else { + + var entityToChar = function(m) { + var isNumeric = /^&#/.test(m); + var isHex = /^&#[Xx]/.test(m); + var uchar; + if (isNumeric) { + var num; + if (isHex) { + num = parseInt(m.slice(3,-1), 16); + } else { + num = parseInt(m.slice(2,-1), 10); + } + uchar = String.fromCodePoint(num); + } else { + uchar = entities[m.slice(1,-1)]; + } + return (uchar || m); + }; + + // Replace entities and backslash escapes with literal characters. + var unescapeEntBS = function(s) { + return s.replace(reAllEscapedChar, '$1') + .replace(reEntity, entityToChar); + }; + + // Returns true if string contains only space characters. + var isBlank = function(s) { + return /^\s*$/.test(s); + }; + + // Normalize reference label: collapse internal whitespace + // to single space, remove leading/trailing whitespace, case fold. + var normalizeReference = function(s) { + return s.trim() + .replace(/\s+/,' ') + .toUpperCase(); + }; + + // Attempt to match a regex in string s at offset offset. + // Return index of match or null. + var matchAt = function(re, s, offset) { + var res = s.slice(offset).match(re); + if (res) { + return offset + res.index; + } else { + return null; + } + }; + + // Convert tabs to spaces on each line using a 4-space tab stop. + var detabLine = function(text) { + if (text.indexOf('\t') == -1) { + return text; + } else { + var lastStop = 0; + return text.replace(reAllTab, function(match, offset) { + var result = ' '.slice((offset - lastStop) % 4); + lastStop = offset + 1; + return result; + }); + } + }; + + // INLINE PARSER + + // These are methods of an InlineParser object, defined below. + // An InlineParser keeps track of a subject (a string to be + // parsed) and a position in that subject. + + // If re matches at current position in the subject, advance + // position in subject and return the match; otherwise return null. + var match = function(re) { + var match = re.exec(this.subject.slice(this.pos)); + if (match) { + this.pos += match.index + match[0].length; + return match[0]; + } else { + return null; + } + }; + + // Returns the code for the character at the current subject position, or -1 + // there are no more characters. + var peek = function() { + if (this.pos < this.subject.length) { + return this.subject.charCodeAt(this.pos); + } else { + return -1; + } + }; + + // Parse zero or more space characters, including at most one newline + var spnl = function() { + this.match(/^ *(?:\n *)?/); + return 1; + }; + + // All of the parsers below try to match something at the current position + // in the subject. If they succeed in matching anything, they + // return the inline matched, advancing the subject. + + // Attempt to parse backticks, returning either a backtick code span or a + // literal sequence of backticks. + var parseBackticks = function(inlines) { + var startpos = this.pos; + var ticks = this.match(/^`+/); + if (!ticks) { + return 0; + } + var afterOpenTicks = this.pos; + var foundCode = false; + var match; + while (!foundCode && (match = this.match(/`+/m))) { + if (match == ticks) { + inlines.push({ t: 'Code', c: this.subject.slice(afterOpenTicks, + this.pos - ticks.length) + .replace(/[ \n]+/g,' ') + .trim() }); + return true; + } + } + // If we got here, we didn't match a closing backtick sequence. + this.pos = afterOpenTicks; + inlines.push({ t: 'Str', c: ticks }); + return true; + }; + + // Parse a backslash-escaped special character, adding either the escaped + // character, a hard line break (if the backslash is followed by a newline), + // or a literal backslash to the 'inlines' list. + var parseBackslash = function(inlines) { + var subj = this.subject, + pos = this.pos; + if (subj.charCodeAt(pos) === C_BACKSLASH) { + if (subj.charAt(pos + 1) === '\n') { + this.pos = this.pos + 2; + inlines.push({ t: 'Hardbreak' }); + } else if (reEscapable.test(subj.charAt(pos + 1))) { + this.pos = this.pos + 2; + inlines.push({ t: 'Str', c: subj.charAt(pos + 1) }); + } else { + this.pos++; + inlines.push({t: 'Str', c: '\\'}); + } + return true; + } else { + return false; + } + }; + + // Attempt to parse an autolink (URL or email in pointy brackets). + var parseAutolink = function(inlines) { + var m; + var dest; + if ((m = this.match(/^<([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/))) { // email autolink + dest = m.slice(1,-1); + inlines.push( + {t: 'Link', + label: [{ t: 'Str', c: dest }], + destination: 'mailto:' + encodeURI(unescape(dest)) }); + return true; + } else if ((m = this.match(/^<(?:coap|doi|javascript|aaa|aaas|about|acap|cap|cid|crid|data|dav|dict|dns|file|ftp|geo|go|gopher|h323|http|https|iax|icap|im|imap|info|ipp|iris|iris.beep|iris.xpc|iris.xpcs|iris.lwz|ldap|mailto|mid|msrp|msrps|mtqp|mupdate|news|nfs|ni|nih|nntp|opaquelocktoken|pop|pres|rtsp|service|session|shttp|sieve|sip|sips|sms|snmp|soap.beep|soap.beeps|tag|tel|telnet|tftp|thismessage|tn3270|tip|tv|urn|vemmi|ws|wss|xcon|xcon-userid|xmlrpc.beep|xmlrpc.beeps|xmpp|z39.50r|z39.50s|adiumxtra|afp|afs|aim|apt|attachment|aw|beshare|bitcoin|bolo|callto|chrome|chrome-extension|com-eventbrite-attendee|content|cvs|dlna-playsingle|dlna-playcontainer|dtn|dvb|ed2k|facetime|feed|finger|fish|gg|git|gizmoproject|gtalk|hcp|icon|ipn|irc|irc6|ircs|itms|jar|jms|keyparc|lastfm|ldaps|magnet|maps|market|message|mms|ms-help|msnim|mumble|mvn|notes|oid|palm|paparazzi|platform|proxy|psyc|query|res|resource|rmi|rsync|rtmp|secondlife|sftp|sgn|skype|smb|soldat|spotify|ssh|steam|svn|teamspeak|things|udp|unreal|ut2004|ventrilo|view-source|webcal|wtai|wyciwyg|xfire|xri|ymsgr):[^<>\x00-\x20]*>/i))) { + dest = m.slice(1,-1); + inlines.push({ + t: 'Link', + label: [{ t: 'Str', c: dest }], + destination: encodeURI(unescape(dest)) }); + return true; + } else { + return false; + } + }; + + // Attempt to parse a raw HTML tag. + var parseHtmlTag = function(inlines) { + var m = this.match(reHtmlTag); + if (m) { + inlines.push({ t: 'Html', c: m }); + return true; + } else { + return false; + } + }; + + // Scan a sequence of characters with code cc, and return information about + // the number of delimiters and whether they are positioned such that + // they can open and/or close emphasis or strong emphasis. A utility + // function for strong/emph parsing. + var scanDelims = function(cc) { + var numdelims = 0; + var first_close_delims = 0; + var char_before, char_after, cc_after; + var startpos = this.pos; + + char_before = this.pos === 0 ? '\n' : + this.subject.charAt(this.pos - 1); + + while (this.peek() === cc) { + numdelims++; + this.pos++; + } + + cc_after = this.peek(); + if (cc_after === -1) { + char_after = '\n'; + } else { + char_after = String.fromCodePoint(cc_after); + } + + var can_open = numdelims > 0 && numdelims <= 3 && !(/\s/.test(char_after)); + var can_close = numdelims > 0 && numdelims <= 3 && !(/\s/.test(char_before)); + if (cc === C_UNDERSCORE) { + can_open = can_open && !((/[a-z0-9]/i).test(char_before)); + can_close = can_close && !((/[a-z0-9]/i).test(char_after)); + } this.pos = startpos; - return 0; - } - } - // If we're here, it wasn't an explicit link. Try to parse a reference link. - // first, see if there's another label - var savepos = this.pos; - this.spnl(); - var beforelabel = this.pos; - n = this.parseLinkLabel(); - if (n == 2) { - // empty second label - reflabel = rawlabel; - } else if (n > 0) { - reflabel = this.subject.slice(beforelabel, beforelabel + n); - } else { - this.pos = savepos; - reflabel = rawlabel; - } - // lookup rawlabel in refmap - var link = this.refmap[normalizeReference(reflabel)]; - if (link) { - inlines.push({t: 'Link', - destination: link.destination, - title: link.title, - label: parseRawLabel(rawlabel) }); - return this.pos - startpos; - } else { - this.pos = startpos; - return 0; - } - // Nothing worked, rewind: - this.pos = startpos; - return 0; -}; - -// Attempt to parse an entity, adding to inlines if successful. -var parseEntity = function(inlines) { - var m; - if ((m = this.match(/^&(?:#x[a-f0-9]{1,8}|#[0-9]{1,8}|[a-z][a-z0-9]{1,31});/i))) { - inlines.push({ t: 'Entity', c: m }); - return m.length; - } else { - return 0; - } -}; - -// Parse a run of ordinary characters, or a single character with -// a special meaning in markdown, as a plain string, adding to inlines. -var parseString = function(inlines) { - var m; - if ((m = this.match(reMain))) { - inlines.push({ t: 'Str', c: m }); - return m.length; - } else { - return 0; - } -}; - -// Parse a newline. If it was preceded by two spaces, return a hard -// line break; otherwise a soft line break. -var parseNewline = function(inlines) { - if (this.peek() == '\n') { - this.pos++; - var last = inlines[inlines.length - 1]; - if (last && last.t == 'Str' && last.c.slice(-2) == ' ') { - last.c = last.c.replace(/ *$/,''); - inlines.push({ t: 'Hardbreak' }); - } else { - if (last && last.t == 'Str' && last.c.slice(-1) == ' ') { - last.c = last.c.slice(0, -1); - } - inlines.push({ t: 'Softbreak' }); - } - return 1; - } else { - return 0; - } -}; - -// Attempt to parse an image. If the opening '!' is not followed -// by a link, add a literal '!' to inlines. -var parseImage = function(inlines) { - if (this.match(/^!/)) { - var n = this.parseLink(inlines); - if (n === 0) { - inlines.push({ t: 'Str', c: '!' }); - return 1; - } else if (inlines[inlines.length - 1] && - inlines[inlines.length - 1].t == 'Link') { - inlines[inlines.length - 1].t = 'Image'; - return n+1; - } else { - throw "Shouldn't happen"; - } - } else { - return 0; - } -}; - -// Attempt to parse a link reference, modifying refmap. -var parseReference = function(s, refmap) { - this.subject = s; - this.pos = 0; - var rawlabel; - var dest; - var title; - var matchChars; - var startpos = this.pos; - var match; - - // label: - matchChars = this.parseLinkLabel(); - if (matchChars === 0) { - return 0; - } else { - rawlabel = this.subject.substr(0, matchChars); - } - - // colon: - if (this.peek() === ':') { - this.pos++; - } else { - this.pos = startpos; - return 0; - } - - // link url - this.spnl(); - - dest = this.parseLinkDestination(); - if (dest === null || dest.length === 0) { - this.pos = startpos; - return 0; - } - - var beforetitle = this.pos; - this.spnl(); - title = this.parseLinkTitle(); - if (title === null) { - title = ''; - // rewind before spaces - this.pos = beforetitle; - } - - // make sure we're at line end: - if (this.match(/^ *(?:\n|$)/) === null) { - this.pos = startpos; - return 0; - } - - var normlabel = normalizeReference(rawlabel); - - if (!refmap[normlabel]) { - refmap[normlabel] = { destination: dest, title: title }; - } - return this.pos - startpos; -}; - -// Parse the next inline element in subject, advancing subject position -// and adding the result to 'inlines'. -var parseInline = function(inlines) { - var c = this.peek(); - var res; - switch(c) { - case '\n': - res = this.parseNewline(inlines); - break; - case '\\': - res = this.parseEscaped(inlines); - break; - case '`': - res = this.parseBackticks(inlines); - break; - case '*': - case '_': - res = this.parseEmphasis(inlines); - break; - case '[': - res = this.parseLink(inlines); - break; - case '!': - res = this.parseImage(inlines); - break; - case '<': - res = this.parseAutolink(inlines) || - this.parseHtmlTag(inlines); - break; - case '&': - res = this.parseEntity(inlines); - break; - default: - } - return res || this.parseString(inlines); -}; - -// Parse s as a list of inlines, using refmap to resolve references. -var parseInlines = function(s, refmap) { - this.subject = s; - this.pos = 0; - this.refmap = refmap || {}; - var inlines = []; - while (this.parseInline(inlines)) ; - return inlines; -}; - -// The InlineParser object. -function InlineParser(){ - return { - subject: '', - label_nest_level: 0, // used by parseLinkLabel method - pos: 0, - refmap: {}, - match: match, - peek: peek, - spnl: spnl, - parseBackticks: parseBackticks, - parseEscaped: parseEscaped, - parseAutolink: parseAutolink, - parseHtmlTag: parseHtmlTag, - scanDelims: scanDelims, - parseEmphasis: parseEmphasis, - parseLinkTitle: parseLinkTitle, - parseLinkDestination: parseLinkDestination, - parseLinkLabel: parseLinkLabel, - parseLink: parseLink, - parseEntity: parseEntity, - parseString: parseString, - parseNewline: parseNewline, - parseImage: parseImage, - parseReference: parseReference, - parseInline: parseInline, - parse: parseInlines - }; -} - -// DOC PARSER - -// These are methods of a DocParser object, defined below. - -var makeBlock = function(tag, start_line, start_column) { - return { t: tag, - open: true, - last_line_blank: false, - start_line: start_line, - start_column: start_column, - end_line: start_line, - children: [], - parent: null, - // string_content is formed by concatenating strings, in finalize: - string_content: "", - strings: [], - inline_content: [] - }; -}; - -// Returns true if parent block can contain child block. -var canContain = function(parent_type, child_type) { - return ( parent_type == 'Document' || - parent_type == 'BlockQuote' || - parent_type == 'ListItem' || - (parent_type == 'List' && child_type == 'ListItem') ); -}; - -// Returns true if block type can accept lines of text. -var acceptsLines = function(block_type) { - return ( block_type == 'Paragraph' || - block_type == 'IndentedCode' || - block_type == 'FencedCode' ); -}; - -// Returns true if block ends with a blank line, descending if needed -// into lists and sublists. -var endsWithBlankLine = function(block) { - if (block.last_line_blank) { - return true; - } - if ((block.t == 'List' || block.t == 'ListItem') && block.children.length > 0) { - return endsWithBlankLine(block.children[block.children.length - 1]); - } else { - return false; - } -}; - -// Break out of all containing lists, resetting the tip of the -// document to the parent of the highest list, and finalizing -// all the lists. (This is used to implement the "two blank lines -// break of of all lists" feature.) -var breakOutOfLists = function(block, line_number) { - var b = block; - var last_list = null; - do { - if (b.t === 'List') { - last_list = b; - } - b = b.parent; - } while (b); + return { numdelims: numdelims, + can_open: can_open, + can_close: can_close }; + }; + + var Emph = function(ils) { + return {t: 'Emph', c: ils}; + }; + + var Strong = function(ils) { + return {t: 'Strong', c: ils}; + }; + + var Str = function(s) { + return {t: 'Str', c: s}; + }; + + // Attempt to parse emphasis or strong emphasis. + var parseEmphasis = function(cc,inlines) { + var startpos = this.pos; + var c ; + var first_close = 0; + c = String.fromCodePoint(cc); + + var numdelims; + var numclosedelims; + var delimpos; + + // Get opening delimiters. + res = this.scanDelims(cc); + numdelims = res.numdelims; + + if (numdelims === 0) { + this.pos = startpos; + return false; + } - if (last_list) { - while (block != last_list) { - this.finalize(block, line_number); - block = block.parent; - } - this.finalize(last_list, line_number); - this.tip = last_list.parent; - } -}; - -// Add a line to the block at the tip. We assume the tip -// can accept lines -- that check should be done before calling this. -var addLine = function(ln, offset) { - var s = ln.slice(offset); - if (!(this.tip.open)) { - throw({ msg: "Attempted to add line (" + ln + ") to closed container." }); - } - this.tip.strings.push(s); -}; - -// Add block of type tag as a child of the tip. If the tip can't -// accept children, close and finalize it and try its parent, -// and so on til we find a block that can accept children. -var addChild = function(tag, line_number, offset) { - while (!canContain(this.tip.t, tag)) { - this.finalize(this.tip, line_number); - } - - var column_number = offset + 1; // offset 0 = column 1 - var newBlock = makeBlock(tag, line_number, column_number); - this.tip.children.push(newBlock); - newBlock.parent = this.tip; - this.tip = newBlock; - return newBlock; -}; - -// Parse a list marker and return data on the marker (type, -// start, delimiter, bullet character, padding) or null. -var parseListMarker = function(ln, offset) { - var rest = ln.slice(offset); - var match; - var spaces_after_marker; - var data = {}; - if (rest.match(reHrule)) { - return null; - } - if ((match = rest.match(/^[*+-]( +|$)/))) { - spaces_after_marker = match[1].length; - data.type = 'Bullet'; - data.bullet_char = match[0][0]; - - } else if ((match = rest.match(/^(\d+)([.)])( +|$)/))) { - spaces_after_marker = match[3].length; - data.type = 'Ordered'; - data.start = parseInt(match[1]); - data.delimiter = match[2]; - } else { - return null; - } - var blank_item = match[0].length === rest.length; - if (spaces_after_marker >= 5 || - spaces_after_marker < 1 || - blank_item) { - data.padding = match[0].length - spaces_after_marker + 1; - } else { - data.padding = match[0].length; - } - return data; -}; - -// Returns true if the two list items are of the same type, -// with the same delimiter and bullet character. This is used -// in agglomerating list items into lists. -var listsMatch = function(list_data, item_data) { - return (list_data.type === item_data.type && - list_data.delimiter === item_data.delimiter && - list_data.bullet_char === item_data.bullet_char); -}; - -// Analyze a line of text and update the document appropriately. -// We parse markdown text by calling this on each line of input, -// then finalizing the document. -var incorporateLine = function(ln, line_number) { - - var all_matched = true; - var last_child; - var first_nonspace; - var offset = 0; - var match; - var data; - var blank; - var indent; - var last_matched_container; - var i; - var CODE_INDENT = 4; - - var container = this.doc; - var oldtip = this.tip; - - // Convert tabs to spaces: - ln = detabLine(ln); - - // For each containing block, try to parse the associated line start. - // Bail out on failure: container will point to the last matching block. - // Set all_matched to false if not all containers match. - while (container.children.length > 0) { - last_child = container.children[container.children.length - 1]; - if (!last_child.open) { - break; - } - container = last_child; - - match = matchAt(/[^ ]/, ln, offset); - if (match === null) { - first_nonspace = ln.length; - blank = true; - } else { - first_nonspace = match; - blank = false; - } - indent = first_nonspace - offset; - - switch (container.t) { - case 'BlockQuote': - var matched = indent <= 3 && ln[first_nonspace] === '>'; - if (matched) { - offset = first_nonspace + 1; - if (ln[offset] === ' ') { - offset++; - } + if (numdelims >= 4 || !res.can_open) { + this.pos += numdelims; + inlines.push(Str(this.subject.slice(startpos, startpos + numdelims))); + return true; + } + + this.pos += numdelims; + + var delims_to_match = numdelims; + + var current = []; + var firstend; + var firstpos; + var state = 0; + var can_close = false; + var can_open = false; + var last_emphasis_closer = null; + while (this.last_emphasis_closer[c] >= this.pos) { + res = this.scanDelims(cc); + numclosedelims = res.numdelims; + + if (res.can_close) { + if (last_emphasis_closer === null || + last_emphasis_closer < this.pos) { + last_emphasis_closer = this.pos; + } + if (numclosedelims === 3 && delims_to_match === 3) { + delims_to_match -= 3; + this.pos += 3; + current = [{t: 'Strong', c: [{t: 'Emph', c: current}]}]; + } else if (numclosedelims >= 2 && delims_to_match >= 2) { + delims_to_match -= 2; + this.pos += 2; + firstend = current.length; + firstpos = this.pos; + current = [{t: 'Strong', c: current}]; + } else if (numclosedelims >= 1 && delims_to_match >= 1) { + delims_to_match -= 1; + this.pos += 1; + firstend = current.length; + firstpos = this.pos; + current = [{t: 'Emph', c: current}]; + } else { + if (!(this.parseInline(current,true))) { + break; + } + } + if (delims_to_match === 0) { + Array.prototype.push.apply(inlines, current); + return true; + } + } else if (!(this.parseInline(current,true))) { + break; + } + } + + // we didn't match emphasis: fallback + inlines.push(Str(this.subject.slice(startpos, + startpos + delims_to_match))); + if (delims_to_match < numdelims) { + Array.prototype.push.apply(inlines, current.slice(0,firstend)); + this.pos = firstpos; + } else { // delims_to_match === numdelims + this.pos = startpos + delims_to_match; + } + + if (last_emphasis_closer) { + this.last_emphasis_closer[c] = last_emphasis_closer; + } + return true; + }; + + // Attempt to parse link title (sans quotes), returning the string + // or null if no match. + var parseLinkTitle = function() { + var title = this.match(reLinkTitle); + if (title) { + // chop off quotes from title and unescape: + return unescapeEntBS(title.substr(1, title.length - 2)); } else { - all_matched = false; + return null; } - break; + }; + + // Attempt to parse link destination, returning the string or + // null if no match. + var parseLinkDestination = function() { + var res = this.match(reLinkDestinationBraces); + if (res) { // chop off surrounding <..>: + return encodeURI(unescape(unescapeEntBS(res.substr(1, res.length - 2)))); + } else { + res = this.match(reLinkDestination); + if (res !== null) { + return encodeURI(unescape(unescapeEntBS(res))); + } else { + return null; + } + } + }; - case 'ListItem': - if (indent >= container.list_data.marker_offset + - container.list_data.padding) { - offset += container.list_data.marker_offset + - container.list_data.padding; - } else if (blank) { - offset = first_nonspace; + // Attempt to parse a link label, returning number of characters parsed. + var parseLinkLabel = function() { + if (this.peek() != C_OPEN_BRACKET) { + return 0; + } + var startpos = this.pos; + var nest_level = 0; + if (this.label_nest_level > 0) { + // If we've already checked to the end of this subject + // for a label, even with a different starting [, we + // know we won't find one here and we can just return. + // This avoids lots of backtracking. + // Note: nest level 1 would be: [foo [bar] + // nest level 2 would be: [foo [bar [baz] + this.label_nest_level--; + return 0; + } + this.pos++; // advance past [ + var c; + while ((c = this.peek()) && c != -1 && (c != C_CLOSE_BRACKET || nest_level > 0)) { + switch (c) { + case C_BACKTICK: + this.parseBackticks([]); + break; + case C_LESSTHAN: + if (!(this.parseAutolink([]) || this.parseHtmlTag([]))) { + this.pos++; + } + break; + case C_OPEN_BRACKET: // nested [] + nest_level++; + this.pos++; + break; + case C_CLOSE_BRACKET: // nested [] + nest_level--; + this.pos++; + break; + case C_BACKSLASH: + this.parseBackslash([]); + break; + default: + this.parseString([]); + } + } + if (c === C_CLOSE_BRACKET) { + this.label_nest_level = 0; + this.pos++; // advance past ] + return this.pos - startpos; + } else { + if (c === -1) { + this.label_nest_level = nest_level; + } + this.pos = startpos; + return 0; + } + }; + + // Parse raw link label, including surrounding [], and return + // inline contents. (Note: this is not a method of InlineParser.) + var parseRawLabel = function(s) { + // note: parse without a refmap; we don't want links to resolve + // in nested brackets! + return new InlineParser().parse(s.substr(1, s.length - 2), {}); + }; + + // Attempt to parse a link. If successful, return the link. + var parseLink = function(inlines) { + var startpos = this.pos; + var reflabel; + var n; + var dest; + var title; + + n = this.parseLinkLabel(); + if (n === 0) { + return false; + } + var afterlabel = this.pos; + var rawlabel = this.subject.substr(startpos, n); + + // if we got this far, we've parsed a label. + // Try to parse an explicit link: [label](url "title") + if (this.peek() == C_OPEN_PAREN) { + this.pos++; + if (this.spnl() && + ((dest = this.parseLinkDestination()) !== null) && + this.spnl() && + // make sure there's a space before the title: + (/^\s/.test(this.subject.charAt(this.pos - 1)) && + (title = this.parseLinkTitle() || '') || true) && + this.spnl() && + this.match(/^\)/)) { + inlines.push({ t: 'Link', + destination: dest, + title: title, + label: parseRawLabel(rawlabel) }); + return true; + } else { + this.pos = startpos; + return false; + } + } + // If we're here, it wasn't an explicit link. Try to parse a reference link. + // first, see if there's another label + var savepos = this.pos; + this.spnl(); + var beforelabel = this.pos; + n = this.parseLinkLabel(); + if (n == 2) { + // empty second label + reflabel = rawlabel; + } else if (n > 0) { + reflabel = this.subject.slice(beforelabel, beforelabel + n); + } else { + this.pos = savepos; + reflabel = rawlabel; + } + // lookup rawlabel in refmap + var link = this.refmap[normalizeReference(reflabel)]; + if (link) { + inlines.push({t: 'Link', + destination: link.destination, + title: link.title, + label: parseRawLabel(rawlabel) }); + return true; + } else { + this.pos = startpos; + return false; + } + // Nothing worked, rewind: + this.pos = startpos; + return false; + }; + + // Attempt to parse an entity, return Entity object if successful. + var parseEntity = function(inlines) { + var m; + if ((m = this.match(reEntityHere))) { + inlines.push({ t: 'Str', c: entityToChar(m) }); + return true; + } else { + return false; + } + }; + + // Parse a run of ordinary characters, or a single character with + // a special meaning in markdown, as a plain string, adding to inlines. + var parseString = function(inlines) { + var m; + if ((m = this.match(reMain))) { + inlines.push({ t: 'Str', c: m }); + return true; + } else { + return false; + } + }; + + // Parse a newline. If it was preceded by two spaces, return a hard + // line break; otherwise a soft line break. + var parseNewline = function(inlines) { + var m = this.match(/^ *\n/); + if (m) { + if (m.length > 2) { + inlines.push({ t: 'Hardbreak' }); + } else if (m.length > 0) { + inlines.push({ t: 'Softbreak' }); + } + return true; + } + return false; + }; + + // Attempt to parse an image. If the opening '!' is not followed + // by a link, return a literal '!'. + var parseImage = function(inlines) { + if (this.match(/^!/)) { + var link = this.parseLink(inlines); + if (link) { + inlines[inlines.length - 1].t = 'Image'; + return true; + } else { + inlines.push({ t: 'Str', c: '!' }); + return true; + } + } else { + return false; + } + }; + + // Attempt to parse a link reference, modifying refmap. + var parseReference = function(s, refmap) { + this.subject = s; + this.pos = 0; + this.label_nest_level = 0; + var rawlabel; + var dest; + var title; + var matchChars; + var startpos = this.pos; + var match; + + // label: + matchChars = this.parseLinkLabel(); + if (matchChars === 0) { + return 0; } else { - all_matched = false; + rawlabel = this.subject.substr(0, matchChars); } - break; - case 'IndentedCode': - if (indent >= CODE_INDENT) { - offset += CODE_INDENT; - } else if (blank) { - offset = first_nonspace; + // colon: + if (this.peek() === C_COLON) { + this.pos++; } else { - all_matched = false; + this.pos = startpos; + return 0; } - break; - case 'ATXHeader': - case 'SetextHeader': - case 'HorizontalRule': - // a header can never container > 1 line, so fail to match: - all_matched = false; - break; + // link url + this.spnl(); - case 'FencedCode': - // skip optional spaces of fence offset - i = container.fence_offset; - while (i > 0 && ln[offset] === ' ') { - offset++; - i--; + dest = this.parseLinkDestination(); + if (dest === null || dest.length === 0) { + this.pos = startpos; + return 0; } - break; - case 'HtmlBlock': - if (blank) { - all_matched = false; + var beforetitle = this.pos; + this.spnl(); + title = this.parseLinkTitle(); + if (title === null) { + title = ''; + // rewind before spaces + this.pos = beforetitle; } - break; - case 'Paragraph': - if (blank) { - container.last_line_blank = true; - all_matched = false; + // make sure we're at line end: + if (this.match(/^ *(?:\n|$)/) === null) { + this.pos = startpos; + return 0; } - break; - default: - } + var normlabel = normalizeReference(rawlabel); - if (!all_matched) { - container = container.parent; // back up to last matching block - break; - } - } - - last_matched_container = container; - - // This function is used to finalize and close any unmatched - // blocks. We aren't ready to do this now, because we might - // have a lazy paragraph continuation, in which case we don't - // want to close unmatched blocks. So we store this closure for - // use later, when we have more information. - var closeUnmatchedBlocks = function(mythis) { - // finalize any blocks not matched - while (!already_done && oldtip != last_matched_container) { - mythis.finalize(oldtip, line_number); - oldtip = oldtip.parent; - } - var already_done = true; - }; - - // Check to see if we've hit 2nd blank line; if so break out of list: - if (blank && container.last_line_blank) { - this.breakOutOfLists(container, line_number); - } - - // Unless last matched container is a code block, try new container starts, - // adding children to the last matched container: - while (container.t != 'FencedCode' && - container.t != 'IndentedCode' && - container.t != 'HtmlBlock' && - // this is a little performance optimization: - matchAt(/^[ #`~*+_=<>0-9-]/,ln,offset) !== null) { - - match = matchAt(/[^ ]/, ln, offset); - if (match === null) { - first_nonspace = ln.length; - blank = true; - } else { - first_nonspace = match; - blank = false; - } - indent = first_nonspace - offset; - - if (indent >= CODE_INDENT) { - // indented code - if (this.tip.t != 'Paragraph' && !blank) { - offset += CODE_INDENT; - closeUnmatchedBlocks(this); - container = this.addChild('IndentedCode', line_number, offset); - } else { // indent > 4 in a lazy paragraph continuation - break; - } - - } else if (ln[first_nonspace] === '>') { - // blockquote - offset = first_nonspace + 1; - // optional following space - if (ln[offset] === ' ') { - offset++; - } - closeUnmatchedBlocks(this); - container = this.addChild('BlockQuote', line_number, offset); - - } else if ((match = ln.slice(first_nonspace).match(/^#{1,6}(?: +|$)/))) { - // ATX header - offset = first_nonspace + match[0].length; - closeUnmatchedBlocks(this); - container = this.addChild('ATXHeader', line_number, first_nonspace); - container.level = match[0].trim().length; // number of #s - // remove trailing ###s: - container.strings = - [ln.slice(offset).replace(/(?:(\\#) *#*| *#+) *$/,'$1')]; - break; - - } else if ((match = ln.slice(first_nonspace).match(/^`{3,}(?!.*`)|^~{3,}(?!.*~)/))) { - // fenced code block - var fence_length = match[0].length; - closeUnmatchedBlocks(this); - container = this.addChild('FencedCode', line_number, first_nonspace); - container.fence_length = fence_length; - container.fence_char = match[0][0]; - container.fence_offset = first_nonspace - offset; - offset = first_nonspace + fence_length; - break; - - } else if (matchAt(reHtmlBlockOpen, ln, first_nonspace) !== null) { - // html block - closeUnmatchedBlocks(this); - container = this.addChild('HtmlBlock', line_number, first_nonspace); - // note, we don't adjust offset because the tag is part of the text - break; - - } else if (container.t == 'Paragraph' && - container.strings.length === 1 && - ((match = ln.slice(first_nonspace).match(/^(?:=+|-+) *$/)))) { - // setext header line - closeUnmatchedBlocks(this); - container.t = 'SetextHeader'; // convert Paragraph to SetextHeader - container.level = match[0][0] === '=' ? 1 : 2; - offset = ln.length; - - } else if (matchAt(reHrule, ln, first_nonspace) !== null) { - // hrule - closeUnmatchedBlocks(this); - container = this.addChild('HorizontalRule', line_number, first_nonspace); - offset = ln.length - 1; - break; - - } else if ((data = parseListMarker(ln, first_nonspace))) { - // list item - closeUnmatchedBlocks(this); - data.marker_offset = indent; - offset = first_nonspace + data.padding; - - // add the list if needed - if (container.t !== 'List' || - !(listsMatch(container.list_data, data))) { - container = this.addChild('List', line_number, first_nonspace); - container.list_data = data; - } - - // add the list item - container = this.addChild('ListItem', line_number, first_nonspace); - container.list_data = data; - - } else { - break; + if (!refmap[normlabel]) { + refmap[normlabel] = { destination: dest, title: title }; + } + return this.pos - startpos; + }; + + // Parse the next inline element in subject, advancing subject position. + // If memoize is set, memoize the result. + // On success, add the result to the inlines list, and return true. + // On failure, return false. + var parseInline = function(inlines, memoize) { + var startpos = this.pos; + var origlen = inlines.length; + var memoized = memoize && this.memo[startpos]; + if (memoized) { + this.pos = memoized.endpos; + Array.prototype.push.apply(inlines, memoized.inline); + return true; + } - } + var c = this.peek(); + if (c === -1) { + return false; + } + var res; + switch(c) { + case C_NEWLINE: + case C_SPACE: + res = this.parseNewline(inlines); + break; + case C_BACKSLASH: + res = this.parseBackslash(inlines); + break; + case C_BACKTICK: + res = this.parseBackticks(inlines); + break; + case C_ASTERISK: + case C_UNDERSCORE: + res = this.parseEmphasis(c, inlines); + break; + case C_OPEN_BRACKET: + res = this.parseLink(inlines); + break; + case C_BANG: + res = this.parseImage(inlines); + break; + case C_LESSTHAN: + res = this.parseAutolink(inlines) || this.parseHtmlTag(inlines); + break; + case C_AMPERSAND: + res = this.parseEntity(inlines); + break; + default: + res = this.parseString(inlines); + break; + } + if (!res) { + this.pos += 1; + inlines.push({t: 'Str', c: String.fromCodePoint(c)}); + } - if (acceptsLines(container.t)) { - // if it's a line container, it can't contain other containers - break; - } - } - - // What remains at the offset is a text line. Add the text to the - // appropriate container. - - match = matchAt(/[^ ]/, ln, offset); - if (match === null) { - first_nonspace = ln.length; - blank = true; - } else { - first_nonspace = match; - blank = false; - } - indent = first_nonspace - offset; - - // First check for a lazy paragraph continuation: - if (this.tip !== last_matched_container && - !blank && - this.tip.t == 'Paragraph' && - this.tip.strings.length > 0) { - // lazy paragraph continuation - - this.last_line_blank = false; - this.addLine(ln, offset); - - } else { // not a lazy continuation - - // finalize any blocks not matched - closeUnmatchedBlocks(this); - - // Block quote lines are never blank as they start with > - // and we don't count blanks in fenced code for purposes of tight/loose - // lists or breaking out of lists. We also don't set last_line_blank - // on an empty list item. - container.last_line_blank = blank && - !(container.t == 'BlockQuote' || - container.t == 'FencedCode' || - (container.t == 'ListItem' && - container.children.length === 0 && - container.start_line == line_number)); - - var cont = container; - while (cont.parent) { - cont.parent.last_line_blank = false; - cont = cont.parent; + if (memoize) { + this.memo[startpos] = { inline: inlines.slice(origlen), + endpos: this.pos }; + } + return true; + }; + + // Parse s as a list of inlines, using refmap to resolve references. + var parseInlines = function(s, refmap) { + this.subject = s; + this.pos = 0; + this.refmap = refmap || {}; + this.memo = {}; + this.last_emphasis_closer = { '*': s.length, '_': s.length }; + var inlines = []; + while (this.parseInline(inlines, false)) { + } + return inlines; + }; + + // The InlineParser object. + function InlineParser(){ + return { + subject: '', + label_nest_level: 0, // used by parseLinkLabel method + last_emphasis_closer: null, // used by parseEmphasis method + pos: 0, + refmap: {}, + memo: {}, + match: match, + peek: peek, + spnl: spnl, + parseBackticks: parseBackticks, + parseBackslash: parseBackslash, + parseAutolink: parseAutolink, + parseHtmlTag: parseHtmlTag, + scanDelims: scanDelims, + parseEmphasis: parseEmphasis, + parseLinkTitle: parseLinkTitle, + parseLinkDestination: parseLinkDestination, + parseLinkLabel: parseLinkLabel, + parseLink: parseLink, + parseEntity: parseEntity, + parseString: parseString, + parseNewline: parseNewline, + parseImage: parseImage, + parseReference: parseReference, + parseInline: parseInline, + parse: parseInlines + }; } - switch (container.t) { - case 'IndentedCode': - case 'HtmlBlock': - this.addLine(ln, offset); - break; - - case 'FencedCode': - // check for closing code fence: - match = (indent <= 3 && - ln[first_nonspace] == container.fence_char && - ln.slice(first_nonspace).match(/^(?:`{3,}|~{3,})(?= *$)/)); - if (match && match[0].length >= container.fence_length) { - // don't add closing fence to container; instead, close it: - this.finalize(container, line_number); - } else { - this.addLine(ln, offset); - } - break; - - case 'ATXHeader': - case 'SetextHeader': - case 'HorizontalRule': - // nothing to do; we already added the contents. - break; - - default: - if (acceptsLines(container.t)) { - this.addLine(ln, first_nonspace); - } else if (blank) { - // do nothing - } else if (container.t != 'HorizontalRule' && - container.t != 'SetextHeader') { - // create paragraph container for line - container = this.addChild('Paragraph', line_number, first_nonspace); - this.addLine(ln, first_nonspace); - } else { - console.log("Line " + line_number.toString() + - " with container type " + container.t + - " did not match any condition."); - - } - } - } -}; - -// Finalize a block. Close it and do any necessary postprocessing, -// e.g. creating string_content from strings, setting the 'tight' -// or 'loose' status of a list, and parsing the beginnings -// of paragraphs for reference definitions. Reset the tip to the -// parent of the closed block. -var finalize = function(block, line_number) { - var pos; - // don't do anything if the block is already closed - if (!block.open) { - return 0; - } - block.open = false; - if (line_number > block.start_line) { - block.end_line = line_number - 1; - } else { - block.end_line = line_number; - } - - switch (block.t) { - case 'Paragraph': - block.string_content = block.strings.join('\n').replace(/^ */m,''); - - // try parsing the beginning as link reference definitions: - while (block.string_content[0] === '[' && - (pos = this.inlineParser.parseReference(block.string_content, - this.refmap))) { - block.string_content = block.string_content.slice(pos); - if (isBlank(block.string_content)) { - block.t = 'ReferenceDef'; - break; - } - } - break; - - case 'ATXHeader': - case 'SetextHeader': - case 'HtmlBlock': - block.string_content = block.strings.join('\n'); - break; - - case 'IndentedCode': - block.string_content = block.strings.join('\n').replace(/(\n *)*$/,'\n'); - break; - - case 'FencedCode': - // first line becomes info string - block.info = unescape(block.strings[0].trim()); - if (block.strings.length == 1) { - block.string_content = ''; - } else { - block.string_content = block.strings.slice(1).join('\n') + '\n'; - } - break; - - case 'List': - block.tight = true; // tight by default - - var numitems = block.children.length; - var i = 0; - while (i < numitems) { - var item = block.children[i]; - // check for non-final list item ending with blank line: - var last_item = i == numitems - 1; - if (endsWithBlankLine(item) && !last_item) { - block.tight = false; - break; - } - // recurse into children of list item, to see if there are - // spaces between any of them: - var numsubitems = item.children.length; - var j = 0; - while (j < numsubitems) { - var subitem = item.children[j]; - var last_subitem = j == numsubitems - 1; - if (endsWithBlankLine(subitem) && !(last_item && last_subitem)) { - block.tight = false; - break; - } - j++; - } - i++; - } - break; - - default: - break; - } - - this.tip = block.parent || this.top; -}; - -// Walk through a block & children recursively, parsing string content -// into inline content where appropriate. -var processInlines = function(block) { - switch(block.t) { - case 'Paragraph': - case 'SetextHeader': - case 'ATXHeader': - block.inline_content = - this.inlineParser.parse(block.string_content.trim(), this.refmap); - block.string_content = ""; - break; - default: - break; - } - - if (block.children) { - for (var i = 0; i < block.children.length; i++) { - this.processInlines(block.children[i]); - } - } - -}; - -// The main parsing function. Returns a parsed document AST. -var parse = function(input) { - this.doc = makeBlock('Document', 1, 1); - this.tip = this.doc; - this.refmap = {}; - var lines = input.replace(/\n$/,'').split(/\r\n|\n|\r/); - var len = lines.length; - for (var i = 0; i < len; i++) { - this.incorporateLine(lines[i], i+1); - } - while (this.tip) { - this.finalize(this.tip, len - 1); - } - this.processInlines(this.doc); - return this.doc; -}; - - -// The DocParser object. -function DocParser(){ - return { - doc: makeBlock('Document', 1, 1), - tip: this.doc, - refmap: {}, - inlineParser: new InlineParser(), - breakOutOfLists: breakOutOfLists, - addLine: addLine, - addChild: addChild, - incorporateLine: incorporateLine, - finalize: finalize, - processInlines: processInlines, - parse: parse - }; -} - -// HTML RENDERER - -// Helper function to produce content in a pair of HTML tags. -var inTags = function(tag, attribs, contents, selfclosing) { - var result = '<' + tag; - if (attribs) { - var i = 0; - var attrib; - while ((attrib = attribs[i]) !== undefined) { - result = result.concat(' ', attrib[0], '="', attrib[1], '"'); - i++; + // DOC PARSER + + // These are methods of a DocParser object, defined below. + + var makeBlock = function(tag, start_line, start_column) { + return { t: tag, + open: true, + last_line_blank: false, + start_line: start_line, + start_column: start_column, + end_line: start_line, + children: [], + parent: null, + // string_content is formed by concatenating strings, in finalize: + string_content: "", + strings: [], + inline_content: [] + }; + }; + + // Returns true if parent block can contain child block. + var canContain = function(parent_type, child_type) { + return ( parent_type == 'Document' || + parent_type == 'BlockQuote' || + parent_type == 'ListItem' || + (parent_type == 'List' && child_type == 'ListItem') ); + }; + + // Returns true if block type can accept lines of text. + var acceptsLines = function(block_type) { + return ( block_type == 'Paragraph' || + block_type == 'IndentedCode' || + block_type == 'FencedCode' ); + }; + + // Returns true if block ends with a blank line, descending if needed + // into lists and sublists. + var endsWithBlankLine = function(block) { + if (block.last_line_blank) { + return true; + } + if ((block.t == 'List' || block.t == 'ListItem') && block.children.length > 0) { + return endsWithBlankLine(block.children[block.children.length - 1]); + } else { + return false; + } + }; + + // Break out of all containing lists, resetting the tip of the + // document to the parent of the highest list, and finalizing + // all the lists. (This is used to implement the "two blank lines + // break of of all lists" feature.) + var breakOutOfLists = function(block, line_number) { + var b = block; + var last_list = null; + do { + if (b.t === 'List') { + last_list = b; + } + b = b.parent; + } while (b); + + if (last_list) { + while (block != last_list) { + this.finalize(block, line_number); + block = block.parent; + } + this.finalize(last_list, line_number); + this.tip = last_list.parent; + } + }; + + // Add a line to the block at the tip. We assume the tip + // can accept lines -- that check should be done before calling this. + var addLine = function(ln, offset) { + var s = ln.slice(offset); + if (!(this.tip.open)) { + throw({ msg: "Attempted to add line (" + ln + ") to closed container." }); + } + this.tip.strings.push(s); + }; + + // Add block of type tag as a child of the tip. If the tip can't + // accept children, close and finalize it and try its parent, + // and so on til we find a block that can accept children. + var addChild = function(tag, line_number, offset) { + while (!canContain(this.tip.t, tag)) { + this.finalize(this.tip, line_number); + } + + var column_number = offset + 1; // offset 0 = column 1 + var newBlock = makeBlock(tag, line_number, column_number); + this.tip.children.push(newBlock); + newBlock.parent = this.tip; + this.tip = newBlock; + return newBlock; + }; + + // Parse a list marker and return data on the marker (type, + // start, delimiter, bullet character, padding) or null. + var parseListMarker = function(ln, offset) { + var rest = ln.slice(offset); + var match; + var spaces_after_marker; + var data = {}; + if (rest.match(reHrule)) { + return null; + } + if ((match = rest.match(/^[*+-]( +|$)/))) { + spaces_after_marker = match[1].length; + data.type = 'Bullet'; + data.bullet_char = match[0][0]; + + } else if ((match = rest.match(/^(\d+)([.)])( +|$)/))) { + spaces_after_marker = match[3].length; + data.type = 'Ordered'; + data.start = parseInt(match[1]); + data.delimiter = match[2]; + } else { + return null; + } + var blank_item = match[0].length === rest.length; + if (spaces_after_marker >= 5 || + spaces_after_marker < 1 || + blank_item) { + data.padding = match[0].length - spaces_after_marker + 1; + } else { + data.padding = match[0].length; + } + return data; + }; + + // Returns true if the two list items are of the same type, + // with the same delimiter and bullet character. This is used + // in agglomerating list items into lists. + var listsMatch = function(list_data, item_data) { + return (list_data.type === item_data.type && + list_data.delimiter === item_data.delimiter && + list_data.bullet_char === item_data.bullet_char); + }; + + // Analyze a line of text and update the document appropriately. + // We parse markdown text by calling this on each line of input, + // then finalizing the document. + var incorporateLine = function(ln, line_number) { + + var all_matched = true; + var last_child; + var first_nonspace; + var offset = 0; + var match; + var data; + var blank; + var indent; + var last_matched_container; + var i; + var CODE_INDENT = 4; + + var container = this.doc; + var oldtip = this.tip; + + // Convert tabs to spaces: + ln = detabLine(ln); + + // For each containing block, try to parse the associated line start. + // Bail out on failure: container will point to the last matching block. + // Set all_matched to false if not all containers match. + while (container.children.length > 0) { + last_child = container.children[container.children.length - 1]; + if (!last_child.open) { + break; + } + container = last_child; + + match = matchAt(/[^ ]/, ln, offset); + if (match === null) { + first_nonspace = ln.length; + blank = true; + } else { + first_nonspace = match; + blank = false; + } + indent = first_nonspace - offset; + + switch (container.t) { + case 'BlockQuote': + if (indent <= 3 && ln.charCodeAt(first_nonspace) === C_GREATERTHAN) { + offset = first_nonspace + 1; + if (ln.charCodeAt(offset) === C_SPACE) { + offset++; + } + } else { + all_matched = false; + } + break; + + case 'ListItem': + if (indent >= container.list_data.marker_offset + + container.list_data.padding) { + offset += container.list_data.marker_offset + + container.list_data.padding; + } else if (blank) { + offset = first_nonspace; + } else { + all_matched = false; + } + break; + + case 'IndentedCode': + if (indent >= CODE_INDENT) { + offset += CODE_INDENT; + } else if (blank) { + offset = first_nonspace; + } else { + all_matched = false; + } + break; + + case 'ATXHeader': + case 'SetextHeader': + case 'HorizontalRule': + // a header can never container > 1 line, so fail to match: + all_matched = false; + break; + + case 'FencedCode': + // skip optional spaces of fence offset + i = container.fence_offset; + while (i > 0 && ln.charCodeAt(offset) === C_SPACE) { + offset++; + i--; + } + break; + + case 'HtmlBlock': + if (blank) { + all_matched = false; + } + break; + + case 'Paragraph': + if (blank) { + container.last_line_blank = true; + all_matched = false; + } + break; + + default: + } + + if (!all_matched) { + container = container.parent; // back up to last matching block + break; + } + } + + last_matched_container = container; + + // This function is used to finalize and close any unmatched + // blocks. We aren't ready to do this now, because we might + // have a lazy paragraph continuation, in which case we don't + // want to close unmatched blocks. So we store this closure for + // use later, when we have more information. + var closeUnmatchedBlocks = function(mythis) { + // finalize any blocks not matched + while (!already_done && oldtip != last_matched_container) { + mythis.finalize(oldtip, line_number); + oldtip = oldtip.parent; + } + var already_done = true; + }; + + // Check to see if we've hit 2nd blank line; if so break out of list: + if (blank && container.last_line_blank) { + this.breakOutOfLists(container, line_number); + } + + // Unless last matched container is a code block, try new container starts, + // adding children to the last matched container: + while (container.t != 'FencedCode' && + container.t != 'IndentedCode' && + container.t != 'HtmlBlock' && + // this is a little performance optimization: + matchAt(/^[ #`~*+_=<>0-9-]/,ln,offset) !== null) { + + match = matchAt(/[^ ]/, ln, offset); + if (match === null) { + first_nonspace = ln.length; + blank = true; + } else { + first_nonspace = match; + blank = false; + } + indent = first_nonspace - offset; + + if (indent >= CODE_INDENT) { + // indented code + if (this.tip.t != 'Paragraph' && !blank) { + offset += CODE_INDENT; + closeUnmatchedBlocks(this); + container = this.addChild('IndentedCode', line_number, offset); + } else { // indent > 4 in a lazy paragraph continuation + break; + } + + } else if (ln.charCodeAt(first_nonspace) === C_GREATERTHAN) { + // blockquote + offset = first_nonspace + 1; + // optional following space + if (ln.charCodeAt(offset) === C_SPACE) { + offset++; + } + closeUnmatchedBlocks(this); + container = this.addChild('BlockQuote', line_number, offset); + + } else if ((match = ln.slice(first_nonspace).match(/^#{1,6}(?: +|$)/))) { + // ATX header + offset = first_nonspace + match[0].length; + closeUnmatchedBlocks(this); + container = this.addChild('ATXHeader', line_number, first_nonspace); + container.level = match[0].trim().length; // number of #s + // remove trailing ###s: + container.strings = + [ln.slice(offset).replace(/(?:(\\#) *#*| *#+) *$/,'$1')]; + break; + + } else if ((match = ln.slice(first_nonspace).match(/^`{3,}(?!.*`)|^~{3,}(?!.*~)/))) { + // fenced code block + var fence_length = match[0].length; + closeUnmatchedBlocks(this); + container = this.addChild('FencedCode', line_number, first_nonspace); + container.fence_length = fence_length; + container.fence_char = match[0][0]; + container.fence_offset = first_nonspace - offset; + offset = first_nonspace + fence_length; + break; + + } else if (matchAt(reHtmlBlockOpen, ln, first_nonspace) !== null) { + // html block + closeUnmatchedBlocks(this); + container = this.addChild('HtmlBlock', line_number, first_nonspace); + // note, we don't adjust offset because the tag is part of the text + break; + + } else if (container.t == 'Paragraph' && + container.strings.length === 1 && + ((match = ln.slice(first_nonspace).match(/^(?:=+|-+) *$/)))) { + // setext header line + closeUnmatchedBlocks(this); + container.t = 'SetextHeader'; // convert Paragraph to SetextHeader + container.level = match[0][0] === '=' ? 1 : 2; + offset = ln.length; + + } else if (matchAt(reHrule, ln, first_nonspace) !== null) { + // hrule + closeUnmatchedBlocks(this); + container = this.addChild('HorizontalRule', line_number, first_nonspace); + offset = ln.length - 1; + break; + + } else if ((data = parseListMarker(ln, first_nonspace))) { + // list item + closeUnmatchedBlocks(this); + data.marker_offset = indent; + offset = first_nonspace + data.padding; + + // add the list if needed + if (container.t !== 'List' || + !(listsMatch(container.list_data, data))) { + container = this.addChild('List', line_number, first_nonspace); + container.list_data = data; + } + + // add the list item + container = this.addChild('ListItem', line_number, first_nonspace); + container.list_data = data; + + } else { + break; + + } + + if (acceptsLines(container.t)) { + // if it's a line container, it can't contain other containers + break; + } + } + + // What remains at the offset is a text line. Add the text to the + // appropriate container. + + match = matchAt(/[^ ]/, ln, offset); + if (match === null) { + first_nonspace = ln.length; + blank = true; + } else { + first_nonspace = match; + blank = false; + } + indent = first_nonspace - offset; + + // First check for a lazy paragraph continuation: + if (this.tip !== last_matched_container && + !blank && + this.tip.t == 'Paragraph' && + this.tip.strings.length > 0) { + // lazy paragraph continuation + + this.last_line_blank = false; + this.addLine(ln, offset); + + } else { // not a lazy continuation + + // finalize any blocks not matched + closeUnmatchedBlocks(this); + + // Block quote lines are never blank as they start with > + // and we don't count blanks in fenced code for purposes of tight/loose + // lists or breaking out of lists. We also don't set last_line_blank + // on an empty list item. + container.last_line_blank = blank && + !(container.t == 'BlockQuote' || + container.t == 'FencedCode' || + (container.t == 'ListItem' && + container.children.length === 0 && + container.start_line == line_number)); + + var cont = container; + while (cont.parent) { + cont.parent.last_line_blank = false; + cont = cont.parent; + } + + switch (container.t) { + case 'IndentedCode': + case 'HtmlBlock': + this.addLine(ln, offset); + break; + + case 'FencedCode': + // check for closing code fence: + match = (indent <= 3 && + ln.charAt(first_nonspace) == container.fence_char && + ln.slice(first_nonspace).match(/^(?:`{3,}|~{3,})(?= *$)/)); + if (match && match[0].length >= container.fence_length) { + // don't add closing fence to container; instead, close it: + this.finalize(container, line_number); + } else { + this.addLine(ln, offset); + } + break; + + case 'ATXHeader': + case 'SetextHeader': + case 'HorizontalRule': + // nothing to do; we already added the contents. + break; + + default: + if (acceptsLines(container.t)) { + this.addLine(ln, first_nonspace); + } else if (blank) { + // do nothing + } else if (container.t != 'HorizontalRule' && + container.t != 'SetextHeader') { + // create paragraph container for line + container = this.addChild('Paragraph', line_number, first_nonspace); + this.addLine(ln, first_nonspace); + } else { + console.log("Line " + line_number.toString() + + " with container type " + container.t + + " did not match any condition."); + + } + } + } + }; + + // Finalize a block. Close it and do any necessary postprocessing, + // e.g. creating string_content from strings, setting the 'tight' + // or 'loose' status of a list, and parsing the beginnings + // of paragraphs for reference definitions. Reset the tip to the + // parent of the closed block. + var finalize = function(block, line_number) { + var pos; + // don't do anything if the block is already closed + if (!block.open) { + return 0; + } + block.open = false; + if (line_number > block.start_line) { + block.end_line = line_number - 1; + } else { + block.end_line = line_number; + } + + switch (block.t) { + case 'Paragraph': + block.string_content = block.strings.join('\n').replace(/^ */m,''); + + // try parsing the beginning as link reference definitions: + while (block.string_content.charCodeAt(0) === C_OPEN_BRACKET && + (pos = this.inlineParser.parseReference(block.string_content, + this.refmap))) { + block.string_content = block.string_content.slice(pos); + if (isBlank(block.string_content)) { + block.t = 'ReferenceDef'; + break; + } + } + break; + + case 'ATXHeader': + case 'SetextHeader': + case 'HtmlBlock': + block.string_content = block.strings.join('\n'); + break; + + case 'IndentedCode': + block.string_content = block.strings.join('\n').replace(/(\n *)*$/,'\n'); + break; + + case 'FencedCode': + // first line becomes info string + block.info = unescapeEntBS(block.strings[0].trim()); + if (block.strings.length == 1) { + block.string_content = ''; + } else { + block.string_content = block.strings.slice(1).join('\n') + '\n'; + } + break; + + case 'List': + block.tight = true; // tight by default + + var numitems = block.children.length; + var i = 0; + while (i < numitems) { + var item = block.children[i]; + // check for non-final list item ending with blank line: + var last_item = i == numitems - 1; + if (endsWithBlankLine(item) && !last_item) { + block.tight = false; + break; + } + // recurse into children of list item, to see if there are + // spaces between any of them: + var numsubitems = item.children.length; + var j = 0; + while (j < numsubitems) { + var subitem = item.children[j]; + var last_subitem = j == numsubitems - 1; + if (endsWithBlankLine(subitem) && !(last_item && last_subitem)) { + block.tight = false; + break; + } + j++; + } + i++; + } + break; + + default: + break; + } + + this.tip = block.parent || this.top; + }; + + // Walk through a block & children recursively, parsing string content + // into inline content where appropriate. + var processInlines = function(block) { + switch(block.t) { + case 'Paragraph': + case 'SetextHeader': + case 'ATXHeader': + block.inline_content = + this.inlineParser.parse(block.string_content.trim(), this.refmap); + block.string_content = ""; + break; + default: + break; + } + + if (block.children) { + for (var i = 0; i < block.children.length; i++) { + this.processInlines(block.children[i]); + } + } + + }; + + // The main parsing function. Returns a parsed document AST. + var parse = function(input) { + this.doc = makeBlock('Document', 1, 1); + this.tip = this.doc; + this.refmap = {}; + var lines = input.replace(/\n$/,'').split(/\r\n|\n|\r/); + var len = lines.length; + for (var i = 0; i < len; i++) { + this.incorporateLine(lines[i], i+1); + } + while (this.tip) { + this.finalize(this.tip, len - 1); + } + this.processInlines(this.doc); + return this.doc; + }; + + + // The DocParser object. + function DocParser(){ + return { + doc: makeBlock('Document', 1, 1), + tip: this.doc, + refmap: {}, + inlineParser: new InlineParser(), + breakOutOfLists: breakOutOfLists, + addLine: addLine, + addChild: addChild, + incorporateLine: incorporateLine, + finalize: finalize, + processInlines: processInlines, + parse: parse + }; } - } - if (contents) { - result = result.concat('>', contents, '</', tag, '>'); - } else if (selfclosing) { - result = result + ' />'; - } else { - result = result.concat('></', tag, '>'); - } - return result; -}; - -// Render an inline element as HTML. -var renderInline = function(inline) { - var attrs; - switch (inline.t) { - case 'Str': - return this.escape(inline.c); - case 'Softbreak': - return this.softbreak; - case 'Hardbreak': - return inTags('br',[],"",true) + '\n'; - case 'Emph': - return inTags('em', [], this.renderInlines(inline.c)); - case 'Strong': - return inTags('strong', [], this.renderInlines(inline.c)); - case 'Html': - return inline.c; - case 'Entity': - return inline.c; - case 'Link': - attrs = [['href', this.escape(inline.destination, true)]]; - if (inline.title) { - attrs.push(['title', this.escape(inline.title, true)]); - } - return inTags('a', attrs, this.renderInlines(inline.label)); - case 'Image': - attrs = [['src', this.escape(inline.destination, true)], - ['alt', this.escape(this.renderInlines(inline.label))]]; - if (inline.title) { - attrs.push(['title', this.escape(inline.title, true)]); - } - return inTags('img', attrs, "", true); - case 'Code': - return inTags('code', [], this.escape(inline.c)); - default: - console.log("Uknown inline type " + inline.t); - return ""; - } -}; - -// Render a list of inlines. -var renderInlines = function(inlines) { - var result = ''; - for (var i=0; i < inlines.length; i++) { - result = result + this.renderInline(inlines[i]); - } - return result; -}; - -// Render a single block element. -var renderBlock = function(block, in_tight_list) { - var tag; - var attr; - var info_words; - switch (block.t) { - case 'Document': - var whole_doc = this.renderBlocks(block.children); - return (whole_doc === '' ? '' : whole_doc + '\n'); - case 'Paragraph': - if (in_tight_list) { - return this.renderInlines(block.inline_content); - } else { - return inTags('p', [], this.renderInlines(block.inline_content)); - } - break; - case 'BlockQuote': - var filling = this.renderBlocks(block.children); - return inTags('blockquote', [], filling === '' ? this.innersep : - this.innersep + this.renderBlocks(block.children) + this.innersep); - case 'ListItem': - return inTags('li', [], this.renderBlocks(block.children, in_tight_list).trim()); - case 'List': - tag = block.list_data.type == 'Bullet' ? 'ul' : 'ol'; - attr = (!block.list_data.start || block.list_data.start == 1) ? - [] : [['start', block.list_data.start.toString()]]; - return inTags(tag, attr, this.innersep + - this.renderBlocks(block.children, block.tight) + - this.innersep); - case 'ATXHeader': - case 'SetextHeader': - tag = 'h' + block.level; - return inTags(tag, [], this.renderInlines(block.inline_content)); - case 'IndentedCode': - return inTags('pre', [], - inTags('code', [], this.escape(block.string_content))); - case 'FencedCode': - info_words = block.info.split(/ +/); - attr = info_words.length === 0 || info_words[0].length === 0 ? - [] : [['class','language-' + - this.escape(info_words[0],true)]]; - return inTags('pre', [], - inTags('code', attr, this.escape(block.string_content))); - case 'HtmlBlock': - return block.string_content; - case 'ReferenceDef': - return ""; - case 'HorizontalRule': - return inTags('hr',[],"",true); - default: - console.log("Uknown block type " + block.t); - return ""; - } -}; - -// Render a list of block elements, separated by this.blocksep. -var renderBlocks = function(blocks, in_tight_list) { - var result = []; - for (var i=0; i < blocks.length; i++) { - if (blocks[i].t !== 'ReferenceDef') { - result.push(this.renderBlock(blocks[i], in_tight_list)); + + // HTML RENDERER + + // Helper function to produce content in a pair of HTML tags. + var inTags = function(tag, attribs, contents, selfclosing) { + var result = '<' + tag; + if (attribs) { + var i = 0; + var attrib; + while ((attrib = attribs[i]) !== undefined) { + result = result.concat(' ', attrib[0], '="', attrib[1], '"'); + i++; + } + } + if (contents) { + result = result.concat('>', contents, '</', tag, '>'); + } else if (selfclosing) { + result = result + ' />'; + } else { + result = result.concat('></', tag, '>'); + } + return result; + }; + + // Render an inline element as HTML. + var renderInline = function(inline) { + var attrs; + switch (inline.t) { + case 'Str': + return this.escape(inline.c); + case 'Softbreak': + return this.softbreak; + case 'Hardbreak': + return inTags('br',[],"",true) + '\n'; + case 'Emph': + return inTags('em', [], this.renderInlines(inline.c)); + case 'Strong': + return inTags('strong', [], this.renderInlines(inline.c)); + case 'Html': + return inline.c; + case 'Link': + attrs = [['href', this.escape(inline.destination, true)]]; + if (inline.title) { + attrs.push(['title', this.escape(inline.title, true)]); + } + return inTags('a', attrs, this.renderInlines(inline.label)); + case 'Image': + attrs = [['src', this.escape(inline.destination, true)], + ['alt', this.escape(this.renderInlines(inline.label))]]; + if (inline.title) { + attrs.push(['title', this.escape(inline.title, true)]); + } + return inTags('img', attrs, "", true); + case 'Code': + return inTags('code', [], this.escape(inline.c)); + default: + console.log("Unknown inline type " + inline.t); + return ""; + } + }; + + // Render a list of inlines. + var renderInlines = function(inlines) { + var result = ''; + for (var i=0; i < inlines.length; i++) { + result = result + this.renderInline(inlines[i]); + } + return result; + }; + + // Render a single block element. + var renderBlock = function(block, in_tight_list) { + var tag; + var attr; + var info_words; + switch (block.t) { + case 'Document': + var whole_doc = this.renderBlocks(block.children); + return (whole_doc === '' ? '' : whole_doc + '\n'); + case 'Paragraph': + if (in_tight_list) { + return this.renderInlines(block.inline_content); + } else { + return inTags('p', [], this.renderInlines(block.inline_content)); + } + break; + case 'BlockQuote': + var filling = this.renderBlocks(block.children); + return inTags('blockquote', [], filling === '' ? this.innersep : + this.innersep + filling + this.innersep); + case 'ListItem': + return inTags('li', [], this.renderBlocks(block.children, in_tight_list).trim()); + case 'List': + tag = block.list_data.type == 'Bullet' ? 'ul' : 'ol'; + attr = (!block.list_data.start || block.list_data.start == 1) ? + [] : [['start', block.list_data.start.toString()]]; + return inTags(tag, attr, this.innersep + + this.renderBlocks(block.children, block.tight) + + this.innersep); + case 'ATXHeader': + case 'SetextHeader': + tag = 'h' + block.level; + return inTags(tag, [], this.renderInlines(block.inline_content)); + case 'IndentedCode': + return inTags('pre', [], + inTags('code', [], this.escape(block.string_content))); + case 'FencedCode': + info_words = block.info.split(/ +/); + attr = info_words.length === 0 || info_words[0].length === 0 ? + [] : [['class','language-' + + this.escape(info_words[0],true)]]; + return inTags('pre', [], + inTags('code', attr, this.escape(block.string_content))); + case 'HtmlBlock': + return block.string_content; + case 'ReferenceDef': + return ""; + case 'HorizontalRule': + return inTags('hr',[],"",true); + default: + console.log("Unknown block type " + block.t); + return ""; + } + }; + + // Render a list of block elements, separated by this.blocksep. + var renderBlocks = function(blocks, in_tight_list) { + var result = []; + for (var i=0; i < blocks.length; i++) { + if (blocks[i].t !== 'ReferenceDef') { + result.push(this.renderBlock(blocks[i], in_tight_list)); + } + } + return result.join(this.blocksep); + }; + + // The HtmlRenderer object. + function HtmlRenderer(){ + return { + // default options: + blocksep: '\n', // space between blocks + innersep: '\n', // space between block container tag and contents + softbreak: '\n', // by default, soft breaks are rendered as newlines in HTML + // set to "<br />" to make them hard breaks + // set to " " if you want to ignore line wrapping in source + escape: function(s, preserve_entities) { + if (preserve_entities) { + return s.replace(/[&](?![#](x[a-f0-9]{1,8}|[0-9]{1,8});|[a-z][a-z0-9]{1,31};)/gi,'&') + .replace(/[<]/g,'<') + .replace(/[>]/g,'>') + .replace(/["]/g,'"'); + } else { + return s.replace(/[&]/g,'&') + .replace(/[<]/g,'<') + .replace(/[>]/g,'>') + .replace(/["]/g,'"'); + } + }, + renderInline: renderInline, + renderInlines: renderInlines, + renderBlock: renderBlock, + renderBlocks: renderBlocks, + render: renderBlock + }; } - } - return result.join(this.blocksep); -}; - -// The HtmlRenderer object. -function HtmlRenderer(){ - return { - // default options: - blocksep: '\n', // space between blocks - innersep: '\n', // space between block container tag and contents - softbreak: '\n', // by default, soft breaks are rendered as newlines in HTML - // set to "<br />" to make them hard breaks - // set to " " if you want to ignore line wrapping in source - escape: function(s, preserve_entities) { - if (preserve_entities) { - return s.replace(/[&](?![#](x[a-f0-9]{1,8}|[0-9]{1,8});|[a-z][a-z0-9]{1,31};)/gi,'&') - .replace(/[<]/g,'<') - .replace(/[>]/g,'>') - .replace(/["]/g,'"'); - } else { - return s.replace(/[&]/g,'&') - .replace(/[<]/g,'<') - .replace(/[>]/g,'>') - .replace(/["]/g,'"'); - } - }, - renderInline: renderInline, - renderInlines: renderInlines, - renderBlock: renderBlock, - renderBlocks: renderBlocks, - render: renderBlock - }; -} - -exports.DocParser = DocParser; -exports.HtmlRenderer = HtmlRenderer; + + exports.DocParser = DocParser; + exports.HtmlRenderer = HtmlRenderer; })(typeof exports === 'undefined' ? this.stmd = {} : exports); diff --git a/license.bstrlib.txt b/license.bstrlib.txt deleted file mode 100644 index cf78a98..0000000 --- a/license.bstrlib.txt +++ /dev/null @@ -1,29 +0,0 @@ -Copyright (c) 2002-2008 Paul Hsieh -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - Neither the name of bstrlib nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - diff --git a/license.uthash.txt b/license.uthash.txt deleted file mode 100644 index ad8e16a..0000000 --- a/license.uthash.txt +++ /dev/null @@ -1,21 +0,0 @@ -Copyright (c) 2005-2013, Troy D. Hanson http://troydhanson.github.com/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/narrative.md b/narrative.md index 2448ad8..0a86a88 100644 --- a/narrative.md +++ b/narrative.md @@ -4,7 +4,7 @@ title: CommonMark CommonMark is a [specification of Markdown syntax](http://jgm.github.io/stmd/spec.html), together with -BSD3-licensed implementations (`stmd`) in C and javascript. The source +BSD3-licensed implementations (`stmd`) in C and JavaScript. The source for the spec and the two implementations can be found in [this repository](http://github.com/jgm/stmd). @@ -12,7 +12,7 @@ The C implementation provides both a library and a standalone program `stmd` that converts Markdown to HTML. It is written in standard C99 and has no library dependencies. -The javascript implementation is a single javascript file, with no +The JavaScript implementation is a single JavaScript file, with no dependencies. [Try it now!](http://jgm.github.io/stmd/js/) [The spec](http://jgm.github.io/stmd/spec.html) contains over 400 @@ -129,3 +129,12 @@ working out the spec, I benefited greatly from collaboration with David Greenspan, and from extensive discussions with a group of industrial users of Markdown, including Jeff Atwood, Vincent Marti, and Neil Williams. + +### Contributing + +There is a [forum for discussing +CommonMark](http://talk.commonmark.org); you should use it instead of +github issues for questions and possibly open-ended discussions. +Use the [github issue tracker](http://github.com/jgm/stmd/issues) +only for simple, clear, actionable issues. + diff --git a/oldtests/Blockquotes/Indents.html b/oldtests/Blockquotes/Indents.html deleted file mode 100644 index fd98ee8..0000000 --- a/oldtests/Blockquotes/Indents.html +++ /dev/null @@ -1,12 +0,0 @@ -<blockquote> -<p>one -blockquote</p> -</blockquote> -<blockquote> -<blockquote> -<blockquote> -<p>triply nested -triply nested</p> -</blockquote> -</blockquote> -</blockquote> diff --git a/oldtests/Blockquotes/Indents.markdown b/oldtests/Blockquotes/Indents.markdown deleted file mode 100644 index f9342ff..0000000 --- a/oldtests/Blockquotes/Indents.markdown +++ /dev/null @@ -1,5 +0,0 @@ -> one - > blockquote - ->>> triply nested - > > > triply nested diff --git a/oldtests/Blockquotes/Nesting.html b/oldtests/Blockquotes/Nesting.html deleted file mode 100644 index f40e999..0000000 --- a/oldtests/Blockquotes/Nesting.html +++ /dev/null @@ -1,32 +0,0 @@ -<p>These are all equivalent:</p> -<blockquote> -<blockquote> -<p>nested -blockquote</p> -</blockquote> -</blockquote> -<blockquote> -<blockquote> -<p>nested -blockquote</p> -</blockquote> -</blockquote> -<blockquote> -<blockquote> -<p>nested -blockquote</p> -</blockquote> -</blockquote> -<blockquote> -<blockquote> -<p>nested -blockquote</p> -</blockquote> -</blockquote> -<p>This is not:</p> -<blockquote> -<p>nested</p> -<blockquote> -<p>blockquote</p> -</blockquote> -</blockquote> diff --git a/oldtests/Blockquotes/Nesting.markdown b/oldtests/Blockquotes/Nesting.markdown deleted file mode 100644 index 3d67843..0000000 --- a/oldtests/Blockquotes/Nesting.markdown +++ /dev/null @@ -1,22 +0,0 @@ -These are all equivalent: - -> > nested -> > blockquote - - ->> nested ->> blockquote - - -> > nested -blockquote - - -> > nested -> blockquote - - -This is not: - -> nested -> > blockquote diff --git a/oldtests/Blockquotes/Separation.html b/oldtests/Blockquotes/Separation.html deleted file mode 100644 index 910d545..0000000 --- a/oldtests/Blockquotes/Separation.html +++ /dev/null @@ -1,39 +0,0 @@ -<p>One blockquote, two paragraphs:</p> -<blockquote> -<p>one</p> -<p>two</p> -</blockquote> -<p>Two blockquotes:</p> -<blockquote> -<p>one</p> -</blockquote> -<blockquote> -<p>two</p> -</blockquote> -<p>Nested blockquote, two paragraphs:</p> -<blockquote> -<blockquote> -<p>one</p> -<p>two</p> -</blockquote> -</blockquote> -<p>Nested blockquote, two blockquotes:</p> -<blockquote> -<blockquote> -<p>one</p> -</blockquote> -<blockquote> -<p>two</p> -</blockquote> -</blockquote> -<p>Two nested blockquotes:</p> -<blockquote> -<blockquote> -<p>one</p> -</blockquote> -</blockquote> -<blockquote> -<blockquote> -<p>two</p> -</blockquote> -</blockquote> diff --git a/oldtests/Blockquotes/Separation.markdown b/oldtests/Blockquotes/Separation.markdown deleted file mode 100644 index 823d865..0000000 --- a/oldtests/Blockquotes/Separation.markdown +++ /dev/null @@ -1,29 +0,0 @@ -One blockquote, two paragraphs: - -> one -> -> two - -Two blockquotes: - -> one - -> two - -Nested blockquote, two paragraphs: - -> > one -> > -> > two - -Nested blockquote, two blockquotes: - -> > one -> -> > two - -Two nested blockquotes: - -> > one - -> > two diff --git a/oldtests/Code/BlankLines.html b/oldtests/Code/BlankLines.html deleted file mode 100644 index ae0abf7..0000000 --- a/oldtests/Code/BlankLines.html +++ /dev/null @@ -1,33 +0,0 @@ -<pre><code>foo - - - -bar -</code></pre> -<blockquote> -<pre><code>foo - - - -bar -</code></pre> -</blockquote> -<pre><code>foo - - - -bar -</code></pre> -<ol> -<li><p>One</p> -<pre><code>CodeA - -CodeB -</code></pre></li> -<li><p>Two</p> -<pre><code>CodeA -</code></pre></li> -</ol> -<ol> -<li>One</li> -</ol> diff --git a/oldtests/Code/BlankLines.markdown b/oldtests/Code/BlankLines.markdown deleted file mode 100644 index b0d5a0c..0000000 --- a/oldtests/Code/BlankLines.markdown +++ /dev/null @@ -1,28 +0,0 @@ - foo - - - - bar -> foo -> -> -> -> bar - foo - - - - bar - -1. One - - CodeA - - CodeB - -2. Two - - CodeA - - -1. One diff --git a/oldtests/Code/BlankLinesAtEnd.html b/oldtests/Code/BlankLinesAtEnd.html deleted file mode 100644 index ac803d9..0000000 --- a/oldtests/Code/BlankLinesAtEnd.html +++ /dev/null @@ -1,14 +0,0 @@ -<ul> -<li><p>List</p> -<pre><code>code -</code></pre></li> -</ul> -<ul> -<li>one</li> -<li>two</li> -</ul> -<ul> -<li><p>one -not code</p></li> -<li><p>two</p></li> -</ul> diff --git a/oldtests/Code/BlankLinesAtEnd.markdown b/oldtests/Code/BlankLinesAtEnd.markdown deleted file mode 100644 index 55879ae..0000000 --- a/oldtests/Code/BlankLinesAtEnd.markdown +++ /dev/null @@ -1,14 +0,0 @@ -* List - - code - - - * one - * two - - - -* one - not code - -* two diff --git a/oldtests/Code/FenceMatching.html b/oldtests/Code/FenceMatching.html deleted file mode 100644 index 4c7468e..0000000 --- a/oldtests/Code/FenceMatching.html +++ /dev/null @@ -1,8 +0,0 @@ -<pre class="abc"><code>``` -</code></pre> -<pre class="blah"><code> -````` - -```` - -</code></pre> diff --git a/oldtests/Code/FenceMatching.markdown b/oldtests/Code/FenceMatching.markdown deleted file mode 100644 index d86169a..0000000 --- a/oldtests/Code/FenceMatching.markdown +++ /dev/null @@ -1,10 +0,0 @@ -````abc -``` -```` -``````blah - -````` - -```` - -``````````` diff --git a/oldtests/Code/FencedCodeBlocks.html b/oldtests/Code/FencedCodeBlocks.html deleted file mode 100644 index 4813d72..0000000 --- a/oldtests/Code/FencedCodeBlocks.html +++ /dev/null @@ -1,24 +0,0 @@ -<p>This is a fenced code block:</p> -<pre class="haskell"><code>pairs :: [(Int,Char)] -pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']] -</code></pre> -<p>Here is one with tildes:</p> -<pre class="haskell"><code>pairs :: [(Int,Char)] -pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']] -</code></pre> -<p>More metadata:</p> -<pre class="haskell"><code>pairs :: [(Int,Char)] -pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']] -</code></pre> -<p>More backticks:</p> -<pre class="haskell"><code>pairs :: [(Int,Char)] -pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']] - -backticks :: String -backticks = "`````" -</code></pre> -<p>Without an end:</p> -<pre><code>code with -no end - -</code></pre> diff --git a/oldtests/Code/FencedCodeBlocks.markdown b/oldtests/Code/FencedCodeBlocks.markdown deleted file mode 100644 index 6ccc6be..0000000 --- a/oldtests/Code/FencedCodeBlocks.markdown +++ /dev/null @@ -1,35 +0,0 @@ -This is a fenced code block: -```haskell -pairs :: [(Int,Char)] -pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']] -``` -Here is one with tildes: - -~~~ haskell -pairs :: [(Int,Char)] -pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']] -~~~ - -More metadata: - -```haskell numberLines start=50 -pairs :: [(Int,Char)] -pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']] -``` - -More backticks: - -```````` haskell -pairs :: [(Int,Char)] -pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']] - -backticks :: String -backticks = "`````" -````````````` - -Without an end: - -``` -code with -no end - diff --git a/oldtests/Code/IndentedCodeBlocks.html b/oldtests/Code/IndentedCodeBlocks.html deleted file mode 100644 index 0b9b7e7..0000000 --- a/oldtests/Code/IndentedCodeBlocks.html +++ /dev/null @@ -1,22 +0,0 @@ -<p>Indented code with two space indent in first and last line:</p> -<pre><code> two spaces *hello* -{ more } - - and -</code></pre> -<p>Indented code requires a leading/trailing blank line: -quick-command --option "$*"</p> -<p>Indented code does not require a trailing blank line:</p> -<pre><code>code -</code></pre> -<p>and not code.</p> -<p>Code in blockquote:</p> -<blockquote> -<pre><code>code -</code></pre> -</blockquote> -<p>Code in list:</p> -<ol> -<li><pre><code>code -</code></pre></li> -</ol> diff --git a/oldtests/Code/IndentedCodeBlocks.markdown b/oldtests/Code/IndentedCodeBlocks.markdown deleted file mode 100644 index 2a99db0..0000000 --- a/oldtests/Code/IndentedCodeBlocks.markdown +++ /dev/null @@ -1,22 +0,0 @@ -Indented code with two space indent in first and last line: - - two spaces *hello* - { more } - - and - -Indented code requires a leading/trailing blank line: - quick-command --option "$*" - -Indented code does not require a trailing blank line: - - code -and not code. - -Code in blockquote: - -> code - -Code in list: - -1. code diff --git a/oldtests/Code/IndentedFences.html b/oldtests/Code/IndentedFences.html deleted file mode 100644 index 66e76da..0000000 --- a/oldtests/Code/IndentedFences.html +++ /dev/null @@ -1,20 +0,0 @@ -<pre><code>a -</code></pre> -<pre><code>z -</code></pre> -<pre><code>a -a -a - a -</code></pre> -<ul> -<li><p>foo</p> -<pre><code> Hello - -World -</code></pre></li> -</ul> -<blockquote> -<pre><code>a -</code></pre> -</blockquote> diff --git a/oldtests/Code/IndentedFences.markdown b/oldtests/Code/IndentedFences.markdown deleted file mode 100644 index 098545f..0000000 --- a/oldtests/Code/IndentedFences.markdown +++ /dev/null @@ -1,26 +0,0 @@ - ``` - a - ``` - - ``` -z -``` - - ``` -a - a - a - a - ``` - -* foo - - ``` - Hello - - World - ``` - -> ``` ->a ->``` diff --git a/oldtests/Code/IndentedInLists.html b/oldtests/Code/IndentedInLists.html deleted file mode 100644 index 76ed424..0000000 --- a/oldtests/Code/IndentedInLists.html +++ /dev/null @@ -1,22 +0,0 @@ -<ul> -<li><pre><code>code starts here -</code></pre></li> -</ul> -<ol> -<li><p>foo</p> -<pre><code>code starts here -</code></pre></li> -<li><p>foo</p> -<pre><code>code starts here -</code></pre></li> -</ol> -<ul> -<li><p>foo</p> -<pre><code>code starts here -</code></pre> -<ul> -<li><p>foo</p> -<pre><code>code starts here -</code></pre></li> -</ul></li> -</ul> diff --git a/oldtests/Code/IndentedInLists.markdown b/oldtests/Code/IndentedInLists.markdown deleted file mode 100644 index 54e1af1..0000000 --- a/oldtests/Code/IndentedInLists.markdown +++ /dev/null @@ -1,17 +0,0 @@ -- code starts here - -1. foo - - code starts here - -2. foo - - code starts here - -- foo - - code starts here - - - foo - - code starts here diff --git a/oldtests/Code/Inline.html b/oldtests/Code/Inline.html deleted file mode 100644 index 9c52790..0000000 --- a/oldtests/Code/Inline.html +++ /dev/null @@ -1,13 +0,0 @@ -<p>All of these are equivalent:</p> -<ul> -<li><code>*hi*</code></li> -<li><code>*hi*</code></li> -<li><code>*hi*</code></li> -<li><code>*hi*</code></li> -<li><code>*hi*</code></li> -</ul> -<p>Backticks in code spans:</p> -<ul> -<li><code>``code``</code></li> -<li><code>``code``</code></li> -</ul> diff --git a/oldtests/Code/Inline.markdown b/oldtests/Code/Inline.markdown deleted file mode 100644 index 38e5b0c..0000000 --- a/oldtests/Code/Inline.markdown +++ /dev/null @@ -1,13 +0,0 @@ -All of these are equivalent: - -- `*hi*` -- ` *hi* ` -- ``*hi* `` -- ````*hi*```` -- `*hi* - ` - -Backticks in code spans: - -- ``` ``code`` ``` -- ` ``code`` ` diff --git a/oldtests/Code/ListBreakAfter.html b/oldtests/Code/ListBreakAfter.html deleted file mode 100644 index 29d6d5e..0000000 --- a/oldtests/Code/ListBreakAfter.html +++ /dev/null @@ -1,30 +0,0 @@ -<ul> -<li><p>foo</p> -<ul> -<li><p>bar</p> -<pre><code>code1 -code2 -</code></pre> -<p>code?</p></li> -</ul></li> -<li><p>foo</p> -<ul> -<li><p>bar</p> -<pre><code>code1 -code2 -</code></pre></li> -</ul></li> -</ul> -<pre><code>code? -</code></pre> -<ul> -<li>foo -<ul> -<li><p>bar</p> -<pre><code>code1 -code2 -</code></pre></li> -</ul></li> -</ul> -<pre><code>code? -</code></pre> diff --git a/oldtests/Code/ListBreakAfter.markdown b/oldtests/Code/ListBreakAfter.markdown deleted file mode 100644 index 4fa79f1..0000000 --- a/oldtests/Code/ListBreakAfter.markdown +++ /dev/null @@ -1,26 +0,0 @@ -* foo - * bar - - code1 - code2 - - code? - -* foo - * bar - - code1 - code2 - - - code? - -* foo - * bar - - code1 - code2 - - - - code? diff --git a/oldtests/Code/WhiteLines.html b/oldtests/Code/WhiteLines.html deleted file mode 100644 index 7fa137f..0000000 --- a/oldtests/Code/WhiteLines.html +++ /dev/null @@ -1,7 +0,0 @@ -<pre><code>ABC - - - -DEF -</code></pre> -<p>GHI</p> diff --git a/oldtests/Code/WhiteLines.markdown b/oldtests/Code/WhiteLines.markdown deleted file mode 100644 index ea17af7..0000000 --- a/oldtests/Code/WhiteLines.markdown +++ /dev/null @@ -1,9 +0,0 @@ - ABC - - - - DEF - - - -GHI diff --git a/oldtests/Emphasis/Escapes.html b/oldtests/Emphasis/Escapes.html deleted file mode 100644 index 17c9e2d..0000000 --- a/oldtests/Emphasis/Escapes.html +++ /dev/null @@ -1 +0,0 @@ -<p><em>hi* there</em></p> diff --git a/oldtests/Emphasis/Escapes.markdown b/oldtests/Emphasis/Escapes.markdown deleted file mode 100644 index 4f14698..0000000 --- a/oldtests/Emphasis/Escapes.markdown +++ /dev/null @@ -1 +0,0 @@ -*hi\* there*
\ No newline at end of file diff --git a/oldtests/Emphasis/NestedEmphAndStrong.html b/oldtests/Emphasis/NestedEmphAndStrong.html deleted file mode 100644 index b41b527..0000000 --- a/oldtests/Emphasis/NestedEmphAndStrong.html +++ /dev/null @@ -1,66 +0,0 @@ -<ol> -<li><strong><em>test test</em></strong></li> -<li><strong><em>test test</em></strong></li> -<li><em>test <strong>test</strong></em></li> -<li><strong>test <em>test</em></strong></li> -<li><strong><em>test</em> test</strong></li> -<li><em><strong>test</strong> test</em></li> -<li><strong><em>test</em> test</strong></li> -<li><strong>test <em>test</em></strong></li> -<li><em>test <strong>test</strong></em></li> -<li><em>test <strong>test</strong></em></li> -<li><strong>test <em>test</em></strong></li> -<li><strong><em>test</em> test</strong></li> -<li><em><strong>test</strong> test</em></li> -<li><strong><em>test</em> test</strong></li> -<li><strong>test <em>test</em></strong></li> -<li><em>test <strong>test</strong></em></li> -</ol> -<p>Incorrect nesting:</p> -<ol> -<li>*test <strong>test* test</strong></li> -<li>_test <strong>test_ test</strong></li> -<li>**test <em>test</em>* test*</li> -<li>__test␣<em>test</em>_␣test_</li> -<li><em>test <em>test</em> test</em></li> -<li><em>test <em>test</em> test</em></li> -<li><strong>test <strong>test</strong> test</strong></li> -<li><strong>test <strong>test</strong> test</strong></li> -</ol> -<p>No emphasis:</p> -<ol> -<li>test* test *test</li> -<li>test** test **test</li> -<li>test_ test _test</li> -<li>test__ test __test</li> -</ol> -<p>Middle-word emphasis (asterisks):</p> -<ol> -<li><em>a</em>b</li> -<li>a<em>b</em></li> -<li>a<em>b</em>c</li> -<li><strong>a</strong>b</li> -<li>a<strong>b</strong></li> -<li>a<strong>b</strong>c</li> -</ol> -<p>Middle-word emphasis (underscore):</p> -<ol> -<li>_a_b</li> -<li>a_b_</li> -<li>a_b_c</li> -<li>__a__b</li> -<li>a__b__</li> -<li>a__b__c</li> -<li>my_precious_file.txt</li> -</ol> -<p>Tricky Cases:</p> -<ol> -<li>E**. <strong>Test</strong> TestTestTest</li> -<li>E**. <strong>Test</strong> Test Test Test</li> -</ol> -<p>Overlong emphasis:</p> -<p>Name: ____________<br /> -Organization: ____<br /> -Region/Country: __</p> -<p>_____Cut here_____</p> -<p>____Cut here____</p> diff --git a/oldtests/Emphasis/NestedEmphAndStrong.markdown b/oldtests/Emphasis/NestedEmphAndStrong.markdown deleted file mode 100644 index ec7da25..0000000 --- a/oldtests/Emphasis/NestedEmphAndStrong.markdown +++ /dev/null @@ -1,69 +0,0 @@ -1. ***test test*** -2. ___test test___ -3. *test **test*** -4. **test *test*** -5. ***test* test** -6. ***test** test* -7. ***test* test** -8. **test *test*** -9. *test **test*** -10. _test __test___ -11. __test _test___ -12. ___test_ test__ -13. ___test__ test_ -14. ___test_ test__ -15. __test _test___ -16. _test __test___ - -Incorrect nesting: - -1. *test **test* test** -2. _test __test_ test__ -3. **test *test** test* -4. __test _test__ test_ -5. *test *test* test* -6. _test _test_ test_ -7. **test **test** test** -8. __test __test__ test__ - -No emphasis: - -1. test* test *test -2. test** test **test -3. test_ test _test -4. test__ test __test - -Middle-word emphasis (asterisks): - -1. *a*b -2. a*b* -3. a*b*c -4. **a**b -5. a**b** -6. a**b**c - -Middle-word emphasis (underscore): - -1. _a_b -2. a_b_ -3. a_b_c -4. __a__b -5. a__b__ -6. a__b__c -7. my_precious_file.txt - -Tricky Cases: - -1. E**. **Test** TestTestTest -2. E**. **Test** Test Test Test - -Overlong emphasis: - -Name: ____________ -Organization: ____ -Region/Country: __ - -_____Cut here_____ - -____Cut here____ - diff --git a/oldtests/Emphasis/Pathological.html b/oldtests/Emphasis/Pathological.html deleted file mode 100644 index 37eb9fa..0000000 --- a/oldtests/Emphasis/Pathological.html +++ /dev/null @@ -1,24 +0,0 @@ -<p>This input can take a long time to parse in some implementations.</p> -<p>*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -aaaaa</p> -<p><em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a<strong>a<em>a</em><em>a</em>a</strong>a<em>a</em><em>a</em>a**</p> diff --git a/oldtests/Emphasis/Pathological.markdown b/oldtests/Emphasis/Pathological.markdown deleted file mode 100644 index 5deb95e..0000000 --- a/oldtests/Emphasis/Pathological.markdown +++ /dev/null @@ -1,26 +0,0 @@ -This input can take a long time to parse in some implementations. - -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -*a -aaaaa - -*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**a*a** diff --git a/oldtests/Emphasis/Punctuation.html b/oldtests/Emphasis/Punctuation.html deleted file mode 100644 index 6061b81..0000000 --- a/oldtests/Emphasis/Punctuation.html +++ /dev/null @@ -1,10 +0,0 @@ -<p>Here is a _ that is <em>cool</em>.</p> -<p><em>Foo.</em></p> -<p><strong>Foo.</strong></p> -<p><strong><em>Foo.</em></strong></p> -<p><em>Foo</em>.</p> -<p><strong>Foo</strong>.</p> -<p><strong><em>Foo</em></strong>.</p> -<p><em>Foo</em>. <em>Foo</em>? <em>Foo</em>! <em>Foo</em>: <em>Foo</em>; (<em>Foo</em>)</p> -<p><strong>Foo</strong>. <strong>Foo</strong>? <strong>Foo</strong>! <strong>Foo</strong>: <strong>Foo</strong>; (<strong>Foo</strong>)</p> -<p><strong><em>Foo</em></strong>. <strong><em>Foo</em></strong>? <strong><em>Foo</em></strong>! <strong><em>Foo</em></strong>: <strong><em>Foo</em></strong>; (<strong><em>Foo</em></strong>)</p> diff --git a/oldtests/Emphasis/Punctuation.markdown b/oldtests/Emphasis/Punctuation.markdown deleted file mode 100644 index e3f23b8..0000000 --- a/oldtests/Emphasis/Punctuation.markdown +++ /dev/null @@ -1,19 +0,0 @@ -Here is a _ that is _cool_. - -_Foo._ - -__Foo.__ - -___Foo.___ - -_Foo_. - -__Foo__. - -___Foo___. - -_Foo_. _Foo_? _Foo_! _Foo_: _Foo_; (_Foo_) - -__Foo__. __Foo__? __Foo__! __Foo__: __Foo__; (__Foo__) - -___Foo___. ___Foo___? ___Foo___! ___Foo___: ___Foo___; (___Foo___) diff --git a/oldtests/HTML/Blocks.html b/oldtests/HTML/Blocks.html deleted file mode 100644 index dc80335..0000000 --- a/oldtests/HTML/Blocks.html +++ /dev/null @@ -1,18 +0,0 @@ -<div> - <div> - *raw html* - </div> -</div> -<div> -<div> -<p><em>this is markdown</em></p> -</div> -</div> -<!-- comment -here --> -<!-- -<p><em>commented out markdown</em></p> ---> -<div> -* raw html with trailing space -</div> diff --git a/oldtests/HTML/Blocks.markdown b/oldtests/HTML/Blocks.markdown deleted file mode 100644 index a83fa66..0000000 --- a/oldtests/HTML/Blocks.markdown +++ /dev/null @@ -1,26 +0,0 @@ -<div> - <div> - *raw html* - </div> -</div> - -<div> -<div> - -*this is markdown* - -</div> -</div> - -<!-- comment -here --> - -<!-- - -*commented out markdown* - ---> - -<div> -* raw html with trailing space -</div> diff --git a/oldtests/HTML/Inline.html b/oldtests/HTML/Inline.html deleted file mode 100644 index 94d40ac..0000000 --- a/oldtests/HTML/Inline.html +++ /dev/null @@ -1,8 +0,0 @@ -<p><span>hi</span> -<span><code>hi</code></span> -<span class="foo bar" -title='whatever' blue=yes/> -Hello <!-- this -is a comment --> there. -A line<br />break. -<not a tag></p> diff --git a/oldtests/HTML/Inline.markdown b/oldtests/HTML/Inline.markdown deleted file mode 100644 index 2259421..0000000 --- a/oldtests/HTML/Inline.markdown +++ /dev/null @@ -1,8 +0,0 @@ -<span>hi</span> -<span>`hi`</span> -<span class="foo bar" -title='whatever' blue=yes/> -Hello <!-- this -is a comment --> there. -A line<br />break. -<not a tag> diff --git a/oldtests/HTML/UppercaseTags.html b/oldtests/HTML/UppercaseTags.html deleted file mode 100644 index 8d2d828..0000000 --- a/oldtests/HTML/UppercaseTags.html +++ /dev/null @@ -1,4 +0,0 @@ -<DIV> -this is a block -</DIV> -<p>Here is some <I>inline</I> html.</p> diff --git a/oldtests/HTML/UppercaseTags.markdown b/oldtests/HTML/UppercaseTags.markdown deleted file mode 100644 index b476ffb..0000000 --- a/oldtests/HTML/UppercaseTags.markdown +++ /dev/null @@ -1,5 +0,0 @@ -<DIV> -this is a block -</DIV> - -Here is some <I>inline</I> html.
\ No newline at end of file diff --git a/oldtests/Headers/ATX.html b/oldtests/Headers/ATX.html deleted file mode 100644 index f375b98..0000000 --- a/oldtests/Headers/ATX.html +++ /dev/null @@ -1,14 +0,0 @@ -<h1>One</h1> -<h2>Two</h2> -<h3>Three</h3> -<h4>Four</h4> -<h5>Five</h5> -<h6>Six</h6> -<p>####### Seven</p> -<h3>Three with</h3> -<h2>Spacing doesn't matter</h2> -<h2>Escaped final #</h2> -<p>## Not a header</p> -<p>#5 not a header</p> -<h2></h2> -<p>(empty header)</p> diff --git a/oldtests/Headers/ATX.markdown b/oldtests/Headers/ATX.markdown deleted file mode 100644 index f687aa5..0000000 --- a/oldtests/Headers/ATX.markdown +++ /dev/null @@ -1,20 +0,0 @@ -# One -## Two -### Three -#### Four -##### Five - -###### Six - -####### Seven - -### Three with ### -## Spacing doesn't matter ## -## Escaped final \## - -\## Not a header - -#5 not a header - -## -(empty header) diff --git a/oldtests/Headers/Setext.html b/oldtests/Headers/Setext.html deleted file mode 100644 index 787fb02..0000000 --- a/oldtests/Headers/Setext.html +++ /dev/null @@ -1,9 +0,0 @@ -<h1>Level one</h1> -<h2>Two</h2> -<p>In a paragraph</p> -<h2>Level two</h2> -<p>more text</p> -<p>====== -no empty headers</p> -<p>not a header</p> -<hr /> diff --git a/oldtests/Headers/Setext.markdown b/oldtests/Headers/Setext.markdown deleted file mode 100644 index da0c7e2..0000000 --- a/oldtests/Headers/Setext.markdown +++ /dev/null @@ -1,17 +0,0 @@ -Level one -========= - -Two ---- - -In a paragraph - -Level two ---------- -more text - -====== -no empty headers - -not a header ------------- ----- diff --git a/oldtests/Links/AngleBrackets.html b/oldtests/Links/AngleBrackets.html deleted file mode 100644 index 21ac00d..0000000 --- a/oldtests/Links/AngleBrackets.html +++ /dev/null @@ -1,3 +0,0 @@ -<p><a href="?}]*+|&)">silly URL with angle brackets</a>.</p> -<p><a href="url://with spaces" title="title">link</a>.</p> -<p><a href="url with spaces" title="title">link</a>.</p> diff --git a/oldtests/Links/AngleBrackets.markdown b/oldtests/Links/AngleBrackets.markdown deleted file mode 100644 index c2e06ff..0000000 --- a/oldtests/Links/AngleBrackets.markdown +++ /dev/null @@ -1,7 +0,0 @@ -[silly URL with angle brackets](<?}]*+|&)>). - -[link](<url://with spaces> "title"). - -[link][]. - -[link]: <url with spaces> "title" diff --git a/oldtests/Links/AutoLinks.html b/oldtests/Links/AutoLinks.html deleted file mode 100644 index 092353f..0000000 --- a/oldtests/Links/AutoLinks.html +++ /dev/null @@ -1,7 +0,0 @@ -<p><a href="http://google.com?query=blah&time=15">http://google.com?query=blah&time=15</a> -<a href="mailto:someone.else@somedomain.com">someone.else@somedomain.com</a> -<a href="ftp://old.ftp.server.edu">ftp://old.ftp.server.edu</a> -<a href="git://some.git.repo/project.git">git://some.git.repo/project.git</a> -<not autolink> -<http://not.an autolink> -<relative/not/autolink></p> diff --git a/oldtests/Links/AutoLinks.markdown b/oldtests/Links/AutoLinks.markdown deleted file mode 100644 index bf95b8d..0000000 --- a/oldtests/Links/AutoLinks.markdown +++ /dev/null @@ -1,7 +0,0 @@ -<http://google.com?query=blah&time=15> -<someone.else@somedomain.com> -<ftp://old.ftp.server.edu> -<git://some.git.repo/project.git> -<not autolink> -<http://not.an autolink> -<relative/not/autolink> diff --git a/oldtests/Links/BackticksInLinks.html b/oldtests/Links/BackticksInLinks.html deleted file mode 100644 index ff70383..0000000 --- a/oldtests/Links/BackticksInLinks.html +++ /dev/null @@ -1 +0,0 @@ -<p><a href="/url">the right bracket character (<code>]</code>)</a></p> diff --git a/oldtests/Links/BackticksInLinks.markdown b/oldtests/Links/BackticksInLinks.markdown deleted file mode 100644 index 539fd52..0000000 --- a/oldtests/Links/BackticksInLinks.markdown +++ /dev/null @@ -1 +0,0 @@ -[the right bracket character (`]`)](/url) diff --git a/oldtests/Links/CaseInsensitiveReferences.html b/oldtests/Links/CaseInsensitiveReferences.html deleted file mode 100644 index afe4557..0000000 --- a/oldtests/Links/CaseInsensitiveReferences.html +++ /dev/null @@ -1 +0,0 @@ -<p><a href="/url">Толпой</a> is a Russian word.</p> diff --git a/oldtests/Links/CaseInsensitiveReferences.markdown b/oldtests/Links/CaseInsensitiveReferences.markdown deleted file mode 100644 index f9653b9..0000000 --- a/oldtests/Links/CaseInsensitiveReferences.markdown +++ /dev/null @@ -1,3 +0,0 @@ -[Толпой] is a Russian word. - -[ТОЛПОЙ]: /url diff --git a/oldtests/Links/Entities.html b/oldtests/Links/Entities.html deleted file mode 100644 index 252dadb..0000000 --- a/oldtests/Links/Entities.html +++ /dev/null @@ -1,2 +0,0 @@ -<p><a href="http://göögle.com">http://göögle.com</a></p> -<p><a href="/url" title="göögle & yahoo">hi</a></p> diff --git a/oldtests/Links/Entities.markdown b/oldtests/Links/Entities.markdown deleted file mode 100644 index d81ee36..0000000 --- a/oldtests/Links/Entities.markdown +++ /dev/null @@ -1,3 +0,0 @@ -<http://göögle.com> - -[hi](/url "göögle & yahoo") diff --git a/oldtests/Links/InlineLinks.html b/oldtests/Links/InlineLinks.html deleted file mode 100644 index ae33f33..0000000 --- a/oldtests/Links/InlineLinks.html +++ /dev/null @@ -1,10 +0,0 @@ -<ol> -<li><a href="/url">link</a></li> -<li><a href="/url" title="title">link</a></li> -<li><a href="/url" title="title">link</a></li> -<li><a href="/url with spaces" title="title -with linebreak">link <em>with -linebreak</em></a>.</li> -<li><a href="/url(withparens)" title="and single quoted title">link</a></li> -<li>[not a link] (/url)</li> -</ol> diff --git a/oldtests/Links/InlineLinks.markdown b/oldtests/Links/InlineLinks.markdown deleted file mode 100644 index a822c4d..0000000 --- a/oldtests/Links/InlineLinks.markdown +++ /dev/null @@ -1,9 +0,0 @@ -1. [link](/url) -2. [link](/url "title") -3. [link](/url - "title") -4. [link *with -linebreak*](</url with spaces> "title -with linebreak"). -5. [link](/url(withparens) 'and single quoted title') -6. [not a link] (/url) diff --git a/oldtests/Links/ParensInURLs.html b/oldtests/Links/ParensInURLs.html deleted file mode 100644 index 9cd6de7..0000000 --- a/oldtests/Links/ParensInURLs.html +++ /dev/null @@ -1,6 +0,0 @@ -<p><a href="/url(test)" title="title">Inline link 1 with parens</a>.</p> -<p><a href="/url(test)" title="title">Inline link 2 with parens</a>.</p> -<p><a href="/url(test)" title="title">Inline link 3 with non-escaped parens</a>.</p> -<p><a href="/url(test)" title="title">Inline link 4 with non-escaped parens</a>.</p> -<p><a href="/url(test)" title="title">Reference link 1 with parens</a>.</p> -<p><a href="/url(test)" title="title">Reference link 2 with parens</a>.</p> diff --git a/oldtests/Links/ParensInURLs.markdown b/oldtests/Links/ParensInURLs.markdown deleted file mode 100644 index bb7be4f..0000000 --- a/oldtests/Links/ParensInURLs.markdown +++ /dev/null @@ -1,14 +0,0 @@ -[Inline link 1 with parens](/url\(test\) "title"). - -[Inline link 2 with parens](</url\(test\)> "title"). - -[Inline link 3 with non-escaped parens](/url(test) "title"). - -[Inline link 4 with non-escaped parens](</url(test)> "title"). - -[Reference link 1 with parens][1]. - -[Reference link 2 with parens][2]. - - [1]: /url(test) "title" - [2]: </url(test)> "title" diff --git a/oldtests/Links/ReferenceLinks.html b/oldtests/Links/ReferenceLinks.html deleted file mode 100644 index 397cdb2..0000000 --- a/oldtests/Links/ReferenceLinks.html +++ /dev/null @@ -1,7 +0,0 @@ -<ol> -<li><p><a href="/url" title="even in a list item">Link references</a> can be defined anywhere.</p></li> -</ol> -<blockquote> -<p><a href="/foo" title="can break -lines">another</a> one</p> -</blockquote> diff --git a/oldtests/Links/ReferenceLinks.markdown b/oldtests/Links/ReferenceLinks.markdown deleted file mode 100644 index ebcf5a9..0000000 --- a/oldtests/Links/ReferenceLinks.markdown +++ /dev/null @@ -1,10 +0,0 @@ -1. [Link references] can be defined anywhere. - - [Link references]: /url - (even in a list item) - -> [another] one -> -> [another]: -> /foo "can break -> lines" diff --git a/oldtests/Lists/CodeBlocksInLists.html b/oldtests/Lists/CodeBlocksInLists.html deleted file mode 100644 index fcd3e2a..0000000 --- a/oldtests/Lists/CodeBlocksInLists.html +++ /dev/null @@ -1,14 +0,0 @@ -<ol> -<li><p>list item -code</p></li> -<li><p>list item</p> -<pre><code>code -</code></pre></li> -<li><pre><code>code -</code></pre></li> -<li><pre><code>code -</code></pre></li> -<li><pre><code>code -code -</code></pre></li> -</ol> diff --git a/oldtests/Lists/CodeBlocksInLists.markdown b/oldtests/Lists/CodeBlocksInLists.markdown deleted file mode 100644 index 7730808..0000000 --- a/oldtests/Lists/CodeBlocksInLists.markdown +++ /dev/null @@ -1,18 +0,0 @@ -1. list item - code - -2. list item - ~~~ - code - ~~~ - -3. ~~~ - code - ~~~ - -4. ~~~ - code - ~~~ - -5. code - code diff --git a/oldtests/Lists/ConsecutiveLists.html b/oldtests/Lists/ConsecutiveLists.html deleted file mode 100644 index f8f9098..0000000 --- a/oldtests/Lists/ConsecutiveLists.html +++ /dev/null @@ -1,20 +0,0 @@ -<ul> -<li>one</li> -<li>one</li> -</ul> -<ul> -<li>two</li> -<li>two</li> -</ul> -<ul> -<li>three</li> -<li>three</li> -</ul> -<ol> -<li>four</li> -<li>four</li> -</ol> -<ol> -<li>five</li> -<li>five</li> -</ol> diff --git a/oldtests/Lists/ConsecutiveLists.markdown b/oldtests/Lists/ConsecutiveLists.markdown deleted file mode 100644 index c4faa54..0000000 --- a/oldtests/Lists/ConsecutiveLists.markdown +++ /dev/null @@ -1,10 +0,0 @@ -* one -* one -+ two -+ two -- three -- three -1. four -1. four -1) five -1) five diff --git a/oldtests/Lists/EmptyListItem.html b/oldtests/Lists/EmptyListItem.html deleted file mode 100644 index 2c23fe1..0000000 --- a/oldtests/Lists/EmptyListItem.html +++ /dev/null @@ -1,10 +0,0 @@ -<ul> -<li>one</li> -<li></li> -<li>three</li> -</ul> -<ol> -<li>one</li> -<li></li> -<li>three</li> -</ol> diff --git a/oldtests/Lists/EmptyListItem.markdown b/oldtests/Lists/EmptyListItem.markdown deleted file mode 100644 index d30cbc3..0000000 --- a/oldtests/Lists/EmptyListItem.markdown +++ /dev/null @@ -1,7 +0,0 @@ -- one -- -- three - -1. one -2. -3. three diff --git a/oldtests/Lists/InBlockquote.html b/oldtests/Lists/InBlockquote.html deleted file mode 100644 index da233e8..0000000 --- a/oldtests/Lists/InBlockquote.html +++ /dev/null @@ -1,22 +0,0 @@ -<blockquote> -<ul> -<li>tight</li> -<li>tight</li> -</ul> -</blockquote> -<blockquote> -<ul> -<li><p>loose</p></li> -<li><p>loose</p></li> -</ul> -</blockquote> -<blockquote> -<ul> -<li>one-item list</li> -</ul> -</blockquote> -<blockquote> -<ul> -<li>one-item list</li> -</ul> -</blockquote> diff --git a/oldtests/Lists/InBlockquote.markdown b/oldtests/Lists/InBlockquote.markdown deleted file mode 100644 index 511563b..0000000 --- a/oldtests/Lists/InBlockquote.markdown +++ /dev/null @@ -1,12 +0,0 @@ -> - tight -> - tight - - -> - loose -> -> - loose - - -> - one-item list - -> - one-item list diff --git a/oldtests/Lists/Indents.html b/oldtests/Lists/Indents.html deleted file mode 100644 index a11a5a6..0000000 --- a/oldtests/Lists/Indents.html +++ /dev/null @@ -1,22 +0,0 @@ -<blockquote> -<ul> -<li><p>foo</p> -<p>bar</p></li> -</ul> -</blockquote> -<ul> -<li>one</li> -<li>two</li> -</ul> -<ul> -<li>one</li> -<li>two</li> -<li>three</li> -</ul> -<ul> -<li>one -<ul> -<li>two</li> -</ul></li> -<li>three</li> -</ul> diff --git a/oldtests/Lists/Indents.markdown b/oldtests/Lists/Indents.markdown deleted file mode 100644 index 293d112..0000000 --- a/oldtests/Lists/Indents.markdown +++ /dev/null @@ -1,17 +0,0 @@ - > * foo -> -> bar - - - - one - - two - - -- one - - two -- three - - -- one - - two -- three diff --git a/oldtests/Lists/ListsAndHRs.html b/oldtests/Lists/ListsAndHRs.html deleted file mode 100644 index 40826f7..0000000 --- a/oldtests/Lists/ListsAndHRs.html +++ /dev/null @@ -1,7 +0,0 @@ -<ul> -<li>item 1 -<ul> -<li>item 2</li> -</ul></li> -</ul> -<hr /> diff --git a/oldtests/Lists/ListsAndHRs.markdown b/oldtests/Lists/ListsAndHRs.markdown deleted file mode 100644 index 19c07e7..0000000 --- a/oldtests/Lists/ListsAndHRs.markdown +++ /dev/null @@ -1,3 +0,0 @@ -* item 1 - * item 2 -* * * * * diff --git a/oldtests/Lists/ListsAndSetextHeaders.html b/oldtests/Lists/ListsAndSetextHeaders.html deleted file mode 100644 index c6af9eb..0000000 --- a/oldtests/Lists/ListsAndSetextHeaders.html +++ /dev/null @@ -1,6 +0,0 @@ -<ol> -<li>item</li> -<li>item -Not header</li> -</ol> -<hr /> diff --git a/oldtests/Lists/ListsAndSetextHeaders.markdown b/oldtests/Lists/ListsAndSetextHeaders.markdown deleted file mode 100644 index acfa655..0000000 --- a/oldtests/Lists/ListsAndSetextHeaders.markdown +++ /dev/null @@ -1,4 +0,0 @@ -1. item -2. item -Not header ----------- diff --git a/oldtests/Lists/MultipleBlankLines.html b/oldtests/Lists/MultipleBlankLines.html deleted file mode 100644 index d894db1..0000000 --- a/oldtests/Lists/MultipleBlankLines.html +++ /dev/null @@ -1,56 +0,0 @@ -<ol> -<li><p>First Item</p> -<ul> -<li><p>one</p> -<ul> -<li>two</li> -</ul></li> -<li><p>one</p> -<ul> -<li>two</li> -</ul></li> -</ul></li> -<li><p>Second Item</p> -<ul> -<li>one -<ul> -<li>two</li> -</ul></li> -</ul></li> -</ol> -<ul> -<li>one -<ul> -<li>two</li> -</ul></li> -</ul> -<ol> -<li><p>Third Item</p> -<ul> -<li>one -<ul> -<li>two</li> -</ul></li> -</ul></li> -</ol> -<ul> -<li>one -<ul> -<li>two</li> -</ul></li> -</ul> -<ol> -<li><p>Fourth Item</p> -<ul> -<li>one -<ul> -<li>two</li> -</ul></li> -</ul></li> -</ol> -<ul> -<li>one -<ul> -<li>two</li> -</ul></li> -</ul> diff --git a/oldtests/Lists/MultipleBlankLines.markdown b/oldtests/Lists/MultipleBlankLines.markdown deleted file mode 100644 index e24a4f2..0000000 --- a/oldtests/Lists/MultipleBlankLines.markdown +++ /dev/null @@ -1,37 +0,0 @@ -1. First Item - - * one - * two - - * one - * two - -1. Second Item - - * one - * two - - - * one - * two - -1. Third Item - - * one - * two - - - - * one - * two - -1. Fourth Item - - * one - * two - - - - - * one - * two diff --git a/oldtests/Lists/Start.html b/oldtests/Lists/Start.html deleted file mode 100644 index 46e0550..0000000 --- a/oldtests/Lists/Start.html +++ /dev/null @@ -1,11 +0,0 @@ -<ol start="4"> -<li>this list starts with 4.</li> -<li>and continues</li> -<li>the continuation number is irrelevant.</li> -</ol> -<ol start="2001"> -<li>a space odyssey</li> -</ol> -<ol> -<li>standard lists get no start attribute</li> -</ol> diff --git a/oldtests/Lists/Start.markdown b/oldtests/Lists/Start.markdown deleted file mode 100644 index 175226f..0000000 --- a/oldtests/Lists/Start.markdown +++ /dev/null @@ -1,7 +0,0 @@ -4. this list starts with 4. -5. and continues -1. the continuation number is irrelevant. - -2001) a space odyssey - -1. standard lists get no start attribute diff --git a/oldtests/Lists/Sublists.html b/oldtests/Lists/Sublists.html deleted file mode 100644 index af62915..0000000 --- a/oldtests/Lists/Sublists.html +++ /dev/null @@ -1,49 +0,0 @@ -<p>Four levels:</p> -<ul> -<li>one -<ul> -<li>two -<ul> -<li>three -<ul> -<li>four</li> -</ul></li> -</ul></li> -</ul></li> -</ul> -<ol> -<li>one -<ol> -<li>two -<ol> -<li>three -<ol> -<li>four</li> -</ol></li> -</ol></li> -</ol></li> -</ol> -<ol> -<li>one -<ul> -<li>two -<ol> -<li>three -<ul> -<li>four</li> -</ul></li> -</ol></li> -</ul></li> -</ol> -<ul> -<li>one -<ul> -<li>two -<ol> -<li>three -<ol> -<li>four</li> -</ol></li> -</ol></li> -</ul></li> -</ul> diff --git a/oldtests/Lists/Sublists.markdown b/oldtests/Lists/Sublists.markdown deleted file mode 100644 index 9eced9e..0000000 --- a/oldtests/Lists/Sublists.markdown +++ /dev/null @@ -1,24 +0,0 @@ -Four levels: - -- one - - two - - three - - four - - -1. one - 1. two - 1. three - 1. four - - -1) one - - two - 1) three - - four - - -- one - - two - 1. three - 1) four diff --git a/oldtests/Lists/TightAndLoose.html b/oldtests/Lists/TightAndLoose.html deleted file mode 100644 index 7792ebb..0000000 --- a/oldtests/Lists/TightAndLoose.html +++ /dev/null @@ -1,49 +0,0 @@ -<ol> -<li>tight</li> -</ol> -<ul> -<li>tight</li> -<li>list</li> -</ul> -<ul> -<li><p>loose</p></li> -<li><p>list</p></li> -</ul> -<ol> -<li>tight</li> -<li>list</li> -</ol> -<ol> -<li><p>loose</p></li> -<li><p>list</p></li> -</ol> -<ol> -<li><p>loose</p> -<ul> -<li>sublist</li> -</ul></li> -</ol> -<ol> -<li>tight -<ul> -<li>sublist</li> -</ul></li> -</ol> -<ul> -<li>tight -<blockquote> -<p>blockquote -and</p> -</blockquote> -<pre><code>code -</code></pre></li> -<li>tight</li> -</ul> -<ul> -<li>tight -<ul> -<li><p>with loose</p></li> -<li><p>sublist</p></li> -</ul></li> -<li>tight</li> -</ul> diff --git a/oldtests/Lists/TightAndLoose.markdown b/oldtests/Lists/TightAndLoose.markdown deleted file mode 100644 index 263a34c..0000000 --- a/oldtests/Lists/TightAndLoose.markdown +++ /dev/null @@ -1,45 +0,0 @@ -1. tight - - -- tight -- list - - -- loose - -- list - - -1. tight -2. list - - -1. loose - -2. list - - -1. loose - - - sublist - - - -1. tight - - sublist - - -- tight - > blockquote - and - ``` - code - ``` -- tight - - -- tight - - with loose - - - sublist -- tight diff --git a/oldtests/Lists/TightLooseBlockquote.html b/oldtests/Lists/TightLooseBlockquote.html deleted file mode 100644 index 7e78214..0000000 --- a/oldtests/Lists/TightLooseBlockquote.html +++ /dev/null @@ -1,32 +0,0 @@ -<ul> -<li>tight I -<blockquote> -<p>bq</p> -</blockquote></li> -<li>tight I</li> -</ul> -<ul> -<li>tight II -<blockquote> -<p>bq</p> -</blockquote> -foo</li> -<li>tight II</li> -</ul> -<ol> -<li>Blank lines in bq don't break list -<blockquote> -<p>bq</p> -</blockquote></li> -<li>Should say (2) in output</li> -</ol> -<ul> -<li>Blank lines in bq don't break LI -<ul> -<li>item A -<blockquote> -<p>bq</p> -</blockquote></li> -<li>item B</li> -</ul></li> -</ul> diff --git a/oldtests/Lists/TightLooseBlockquote.markdown b/oldtests/Lists/TightLooseBlockquote.markdown deleted file mode 100644 index 08200cc..0000000 --- a/oldtests/Lists/TightLooseBlockquote.markdown +++ /dev/null @@ -1,25 +0,0 @@ -* tight I - > bq - > -* tight I - - -* tight II - > bq - > - foo -* tight II - -1. Blank lines in bq don't break list - > bq - > - > -1. Should say (2) in output - -* Blank lines in bq don't break LI - * item A - > bq - > - > - * item B -
\ No newline at end of file diff --git a/oldtests/Lists/TightLooseMore.html b/oldtests/Lists/TightLooseMore.html deleted file mode 100644 index f26f457..0000000 --- a/oldtests/Lists/TightLooseMore.html +++ /dev/null @@ -1,7 +0,0 @@ -<ul> -<li><p>foo</p> -<ul> -<li>bar</li> -</ul> -<p>blah</p></li> -</ul> diff --git a/oldtests/Lists/TightLooseMore.markdown b/oldtests/Lists/TightLooseMore.markdown deleted file mode 100644 index 7ace63f..0000000 --- a/oldtests/Lists/TightLooseMore.markdown +++ /dev/null @@ -1,4 +0,0 @@ -* foo - * bar - - blah
\ No newline at end of file diff --git a/oldtests/Lists/TwoBlankLinesEndList.html b/oldtests/Lists/TwoBlankLinesEndList.html deleted file mode 100644 index 629add1..0000000 --- a/oldtests/Lists/TwoBlankLinesEndList.html +++ /dev/null @@ -1,21 +0,0 @@ -<ol> -<li><p>one</p></li> -<li><p>two</p></li> -</ol> -<ol> -<li>new list</li> -</ol> -<blockquote> -<ul> -<li><p>one</p></li> -<li><p>two</p></li> -</ul> -<ul> -<li>new list</li> -</ul> -</blockquote> -<ol> -<li>one</li> -</ol> -<pre><code>code -</code></pre> diff --git a/oldtests/Lists/TwoBlankLinesEndList.markdown b/oldtests/Lists/TwoBlankLinesEndList.markdown deleted file mode 100644 index 2984a19..0000000 --- a/oldtests/Lists/TwoBlankLinesEndList.markdown +++ /dev/null @@ -1,20 +0,0 @@ -1. one - -2. two - - -1. new list - - -> - one -> -> - two -> -> -> - new list - - -1. one - - - code diff --git a/oldtests/Makefile b/oldtests/Makefile deleted file mode 100644 index c8a30bd..0000000 --- a/oldtests/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -SHELL=/bin/bash -TESTDIR ?= * -PATT ?= . -TESTS=$(shell ls $(TESTDIR)/*.markdown | grep $(PATT)) -DIFFS=$(patsubst %.markdown,%.diff,$(TESTS)) -PROG ?= ../stmd -FILTER ?= perl -pe 's/ /␣/g' -TIDYCMD ?= tidy -asxhtml -utf8 --show-body-only yes --show-warnings no -quiet -DETAILS ?= 1 - -# Check to see if echo supports -e option to allow backslash escapes -ifeq ($(shell echo -e),-e) -ECHO=echo -else -ECHO=echo -e -endif - -all: $(DIFFS) - PASS=0;TESTS=0; \ - for f in $(DIFFS); do \ - let TESTS=TESTS+1; \ - [ -s $$f ] || let PASS=PASS+1; \ - done; \ - $(ECHO) "\033[1m$$PASS of $$TESTS tests passed.\033[0m"; \ - if [ $$TESTS -eq $$PASS ]; then exit 0; else exit 1; fi - -%.actual.html: %.markdown -ifeq ($(TIDY),1) - -cat $< | $(PROG) | $(TIDYCMD) > $@ -else - -cat $< | $(PROG) > $@ -endif - -%.expected.html: %.html -ifeq ($(TIDY),1) - -$(TIDYCMD) $< > $@ -else - cp $< $@ -endif - -%.diff: %.expected.html %.actual.html - diff --unified=1 <(cat $(word 1,$^) | $(FILTER)) <(cat $(word 2,$^) | $(FILTER)) > $@ ; \ - if [ -s $@ ]; then \ - $(ECHO) "\033[1;31m✘ $(patsubst %.diff,%,$@)\033[0m"; \ - if [ $(DETAILS) == "1" ]; then \ - $(ECHO) "\033[0;36m" ; cat $@; $(ECHO) "\033[0m"; \ - fi \ - else \ - $(ECHO) "\033[1;32m✓ $(patsubst %.diff,%,$@)\033[0m"; \ - fi - -.PHONY: all clean - -clean: - -@rm */*.{diff,actual.html,expected.html} diff --git a/oldtests/Misc/BackslashEscapes.html b/oldtests/Misc/BackslashEscapes.html deleted file mode 100644 index 3eb2aed..0000000 --- a/oldtests/Misc/BackslashEscapes.html +++ /dev/null @@ -1,14 +0,0 @@ -<p>*not emphasized* -\<em>emphasis</em> -**not bold** -<br/> not a tag -[link](/foo) not a link -<a href="/foo)" title="title"">link</a> -`not code`</p> -<p>1. not a list item</p> -<p>* not a list.</p> -<p># Not a header</p> -<p>[foo]: /url "not a reference"</p> -<p>$ ^ ; can be escaped. -\a \b \T cannot. -unicode letters and symbols cannot: \π \‥.</p> diff --git a/oldtests/Misc/BackslashEscapes.markdown b/oldtests/Misc/BackslashEscapes.markdown deleted file mode 100644 index 23496dc..0000000 --- a/oldtests/Misc/BackslashEscapes.markdown +++ /dev/null @@ -1,19 +0,0 @@ -\*not emphasized* -\\*emphasis* -\*\*not bold** -\<br/> not a tag -\[link](/foo) not a link -[link](/foo\) "title\"") -\`not code` - -1\. not a list item - -\* not a list. - -\# Not a header - -\[foo]: /url "not a reference" - -\$ \^ \; can be escaped. -\a \b \T cannot. -unicode letters and symbols cannot: \π \‥. diff --git a/oldtests/Misc/Laziness.html b/oldtests/Misc/Laziness.html deleted file mode 100644 index e130eb5..0000000 --- a/oldtests/Misc/Laziness.html +++ /dev/null @@ -1,22 +0,0 @@ -<blockquote> -<ol> -<li>one -two</li> -</ol> -</blockquote> -<p>Laziness only affects paragraph continuations:</p> -<blockquote> -<pre><code>code -</code></pre> -</blockquote> -<pre><code>not same code block -</code></pre> -<ol> -<li>hello</li> -</ol> -<hr /> -<blockquote> -<pre><code></code></pre> -</blockquote> -<p>code</p> -<pre><code></code></pre> diff --git a/oldtests/Misc/Laziness.markdown b/oldtests/Misc/Laziness.markdown deleted file mode 100644 index 2c32870..0000000 --- a/oldtests/Misc/Laziness.markdown +++ /dev/null @@ -1,14 +0,0 @@ -> 1. one -> two - -Laziness only affects paragraph continuations: - -> code - not same code block - -1. hello ------ - -> ``` -code -``` diff --git a/oldtests/Misc/LineBreaks.html b/oldtests/Misc/LineBreaks.html deleted file mode 100644 index 2d85e85..0000000 --- a/oldtests/Misc/LineBreaks.html +++ /dev/null @@ -1,11 +0,0 @@ -<p>Two spaces<br /> -break a line. Or more than two<br /> -and spaces in the following line are absorbed.</p> -<p>You can also break lines with<br /> -a backslash.</p> -<p>Two spaces at the end of a paragraph are -not a line break.</p> -<p>A backslash at the end of a paragraph is -not a line break.\</p> -<h2>Similarly with setext headers</h2> -<h2>And with backslashes\</h2> diff --git a/oldtests/Misc/LineBreaks.markdown b/oldtests/Misc/LineBreaks.markdown deleted file mode 100644 index 3632dcb..0000000 --- a/oldtests/Misc/LineBreaks.markdown +++ /dev/null @@ -1,18 +0,0 @@ -Two spaces -break a line. Or more than two - and spaces in the following line are absorbed. - -You can also break lines with\ -a backslash. - -Two spaces at the end of a paragraph are -not a line break. - -A backslash at the end of a paragraph is -not a line break.\ - -Similarly with setext headers -------------------------------- - -And with backslashes\ ---------------------- diff --git a/oldtests/Misc/Transitions.html b/oldtests/Misc/Transitions.html deleted file mode 100644 index fceff9f..0000000 --- a/oldtests/Misc/Transitions.html +++ /dev/null @@ -1,26 +0,0 @@ -<blockquote> -<p>blockquote</p> -<blockquote> -<p>blockquote</p> -</blockquote> -</blockquote> -<ol> -<li>list</li> -<li>list -<ul> -<li>sublist</li> -</ul></li> -</ol> -<hr /> -<p>paragraph</p> -<h2>header</h2> -<h3>header</h3> -<pre><code>code -</code></pre> -<pre><code>code -</code></pre> -<div> - <div> -# not a header - </div> -</div> diff --git a/oldtests/Misc/Transitions.markdown b/oldtests/Misc/Transitions.markdown deleted file mode 100644 index 5f3a9d3..0000000 --- a/oldtests/Misc/Transitions.markdown +++ /dev/null @@ -1,20 +0,0 @@ -> blockquote -> > blockquote -1. list -2. list - - sublist -* * * * * -paragraph - -header ------- -### header - code -``` -code -``` -<div> - <div> -# not a header - </div> -</div> diff --git a/oldtests/Original/Amps_and_angle_encoding.html b/oldtests/Original/Amps_and_angle_encoding.html deleted file mode 100644 index fc1b2c3..0000000 --- a/oldtests/Original/Amps_and_angle_encoding.html +++ /dev/null @@ -1,9 +0,0 @@ -<p>AT&T has an ampersand in their name.</p> -<p>AT&T is another way to write it.</p> -<p>This & that.</p> -<p>4 < 5.</p> -<p>6 > 5.</p> -<p>Here's a <a href="http://example.com/?foo=1&bar=2">link</a> with an ampersand in the URL.</p> -<p>Here's a link with an amersand in the link text: <a href="http://att.com/" title="AT&T">AT&T</a>.</p> -<p>Here's an inline <a href="/script?foo=1&bar=2">link</a>.</p> -<p>Here's an inline <a href="/script?foo=1&bar=2">link</a>.</p> diff --git a/oldtests/Original/Amps_and_angle_encoding.markdown b/oldtests/Original/Amps_and_angle_encoding.markdown deleted file mode 100644 index 0e9527f..0000000 --- a/oldtests/Original/Amps_and_angle_encoding.markdown +++ /dev/null @@ -1,21 +0,0 @@ -AT&T has an ampersand in their name. - -AT&T is another way to write it. - -This & that. - -4 < 5. - -6 > 5. - -Here's a [link] [1] with an ampersand in the URL. - -Here's a link with an amersand in the link text: [AT&T] [2]. - -Here's an inline [link](/script?foo=1&bar=2). - -Here's an inline [link](</script?foo=1&bar=2>). - - -[1]: http://example.com/?foo=1&bar=2 -[2]: http://att.com/ "AT&T"
\ No newline at end of file diff --git a/oldtests/Original/Auto_links.html b/oldtests/Original/Auto_links.html deleted file mode 100644 index f517fe6..0000000 --- a/oldtests/Original/Auto_links.html +++ /dev/null @@ -1,13 +0,0 @@ -<p>Link: <a href="http://example.com/">http://example.com/</a>.</p> -<p>With an ampersand: <a href="http://example.com/?foo=1&bar=2">http://example.com/?foo=1&bar=2</a></p> -<ul> -<li>In a list?</li> -<li><a href="http://example.com/">http://example.com/</a></li> -<li>It should.</li> -</ul> -<blockquote> -<p>Blockquoted: <a href="http://example.com/">http://example.com/</a></p> -</blockquote> -<p>Auto-links should not occur here: <code><http://example.com/></code></p> -<pre><code>or here: <http://example.com/> -</code></pre> diff --git a/oldtests/Original/Auto_links.markdown b/oldtests/Original/Auto_links.markdown deleted file mode 100644 index abbc488..0000000 --- a/oldtests/Original/Auto_links.markdown +++ /dev/null @@ -1,13 +0,0 @@ -Link: <http://example.com/>. - -With an ampersand: <http://example.com/?foo=1&bar=2> - -* In a list? -* <http://example.com/> -* It should. - -> Blockquoted: <http://example.com/> - -Auto-links should not occur here: `<http://example.com/>` - - or here: <http://example.com/>
\ No newline at end of file diff --git a/oldtests/Original/Backslash_escapes.html b/oldtests/Original/Backslash_escapes.html deleted file mode 100644 index 9a83379..0000000 --- a/oldtests/Original/Backslash_escapes.html +++ /dev/null @@ -1,75 +0,0 @@ -<p>These should all get escaped:</p> -<p>Backslash: \</p> -<p>Backtick: `</p> -<p>Asterisk: *</p> -<p>Underscore: _</p> -<p>Left brace: {</p> -<p>Right brace: }</p> -<p>Left bracket: [</p> -<p>Right bracket: ]</p> -<p>Left paren: (</p> -<p>Right paren: )</p> -<p>Greater-than: ></p> -<p>Hash: #</p> -<p>Period: .</p> -<p>Bang: !</p> -<p>Plus: +</p> -<p>Minus: -</p> -<p>These should not, because they occur within a code block:</p> -<pre><code>Backslash: \\ - -Backtick: \` - -Asterisk: \* - -Underscore: \_ - -Left brace: \{ - -Right brace: \} - -Left bracket: \[ - -Right bracket: \] - -Left paren: \( - -Right paren: \) - -Greater-than: \> - -Hash: \# - -Period: \. - -Bang: \! - -Plus: \+ - -Minus: \- -</code></pre> -<p>Nor should these, which occur in code spans:</p> -<p>Backslash: <code>\\</code></p> -<p>Backtick: <code>\`</code></p> -<p>Asterisk: <code>\*</code></p> -<p>Underscore: <code>\_</code></p> -<p>Left brace: <code>\{</code></p> -<p>Right brace: <code>\}</code></p> -<p>Left bracket: <code>\[</code></p> -<p>Right bracket: <code>\]</code></p> -<p>Left paren: <code>\(</code></p> -<p>Right paren: <code>\)</code></p> -<p>Greater-than: <code>\></code></p> -<p>Hash: <code>\#</code></p> -<p>Period: <code>\.</code></p> -<p>Bang: <code>\!</code></p> -<p>Plus: <code>\+</code></p> -<p>Minus: <code>\-</code></p> -<p>These should get escaped, even though they're matching pairs for -other Markdown constructs:</p> -<p>*asterisks*</p> -<p>_underscores_</p> -<p>`backticks`</p> -<p>This is a code span with a literal backslash-backtick sequence: <code>\`</code></p> -<p>This is a tag with unescaped backticks <span attr='`ticks`'>bar</span>.</p> -<p>This is a tag with backslashes <span attr='\\backslashes\\'>bar</span>.</p> diff --git a/oldtests/Original/Backslash_escapes.markdown b/oldtests/Original/Backslash_escapes.markdown deleted file mode 100644 index 5b014cb..0000000 --- a/oldtests/Original/Backslash_escapes.markdown +++ /dev/null @@ -1,120 +0,0 @@ -These should all get escaped: - -Backslash: \\ - -Backtick: \` - -Asterisk: \* - -Underscore: \_ - -Left brace: \{ - -Right brace: \} - -Left bracket: \[ - -Right bracket: \] - -Left paren: \( - -Right paren: \) - -Greater-than: \> - -Hash: \# - -Period: \. - -Bang: \! - -Plus: \+ - -Minus: \- - - - -These should not, because they occur within a code block: - - Backslash: \\ - - Backtick: \` - - Asterisk: \* - - Underscore: \_ - - Left brace: \{ - - Right brace: \} - - Left bracket: \[ - - Right bracket: \] - - Left paren: \( - - Right paren: \) - - Greater-than: \> - - Hash: \# - - Period: \. - - Bang: \! - - Plus: \+ - - Minus: \- - - -Nor should these, which occur in code spans: - -Backslash: `\\` - -Backtick: `` \` `` - -Asterisk: `\*` - -Underscore: `\_` - -Left brace: `\{` - -Right brace: `\}` - -Left bracket: `\[` - -Right bracket: `\]` - -Left paren: `\(` - -Right paren: `\)` - -Greater-than: `\>` - -Hash: `\#` - -Period: `\.` - -Bang: `\!` - -Plus: `\+` - -Minus: `\-` - - -These should get escaped, even though they're matching pairs for -other Markdown constructs: - -\*asterisks\* - -\_underscores\_ - -\`backticks\` - -This is a code span with a literal backslash-backtick sequence: `` \` `` - -This is a tag with unescaped backticks <span attr='`ticks`'>bar</span>. - -This is a tag with backslashes <span attr='\\backslashes\\'>bar</span>. diff --git a/oldtests/Original/Blockquotes_with_code_blocks.html b/oldtests/Original/Blockquotes_with_code_blocks.html deleted file mode 100644 index fd1cb1b..0000000 --- a/oldtests/Original/Blockquotes_with_code_blocks.html +++ /dev/null @@ -1,12 +0,0 @@ -<blockquote> -<p>Example:</p> -<pre><code>sub status { - print "working"; -} -</code></pre> -<p>Or:</p> -<pre><code>sub status { - return "working"; -} -</code></pre> -</blockquote> diff --git a/oldtests/Original/Blockquotes_with_code_blocks.markdown b/oldtests/Original/Blockquotes_with_code_blocks.markdown deleted file mode 100644 index c31d171..0000000 --- a/oldtests/Original/Blockquotes_with_code_blocks.markdown +++ /dev/null @@ -1,11 +0,0 @@ -> Example: -> -> sub status { -> print "working"; -> } -> -> Or: -> -> sub status { -> return "working"; -> } diff --git a/oldtests/Original/Code_Blocks.html b/oldtests/Original/Code_Blocks.html deleted file mode 100644 index 7d89615..0000000 --- a/oldtests/Original/Code_Blocks.html +++ /dev/null @@ -1,12 +0,0 @@ -<pre><code>code block on the first line -</code></pre> -<p>Regular text.</p> -<pre><code>code block indented by spaces -</code></pre> -<p>Regular text.</p> -<pre><code>the lines in this block -all contain trailing spaces -</code></pre> -<p>Regular Text.</p> -<pre><code>code block on the last line -</code></pre> diff --git a/oldtests/Original/Code_Blocks.markdown b/oldtests/Original/Code_Blocks.markdown deleted file mode 100644 index b54b092..0000000 --- a/oldtests/Original/Code_Blocks.markdown +++ /dev/null @@ -1,14 +0,0 @@ - code block on the first line - -Regular text. - - code block indented by spaces - -Regular text. - - the lines in this block - all contain trailing spaces - -Regular Text. - - code block on the last line
\ No newline at end of file diff --git a/oldtests/Original/Code_Spans.html b/oldtests/Original/Code_Spans.html deleted file mode 100644 index 27acea1..0000000 --- a/oldtests/Original/Code_Spans.html +++ /dev/null @@ -1,3 +0,0 @@ -<p><code><test a="</code> content of attribute <code>"></code></p> -<p>Fix for backticks within HTML tag: <span attr='`ticks`'>like this</span></p> -<p>Here's how you put <code>`backticks`</code> in a code span.</p> diff --git a/oldtests/Original/Code_Spans.markdown b/oldtests/Original/Code_Spans.markdown deleted file mode 100644 index 5c229c7..0000000 --- a/oldtests/Original/Code_Spans.markdown +++ /dev/null @@ -1,5 +0,0 @@ -`<test a="` content of attribute `">` - -Fix for backticks within HTML tag: <span attr='`ticks`'>like this</span> - -Here's how you put `` `backticks` `` in a code span.
\ No newline at end of file diff --git a/oldtests/Original/Horizontal_rules.html b/oldtests/Original/Horizontal_rules.html deleted file mode 100644 index a89efdb..0000000 --- a/oldtests/Original/Horizontal_rules.html +++ /dev/null @@ -1,39 +0,0 @@ -<p>Dashes:</p> -<hr /> -<hr /> -<hr /> -<hr /> -<pre><code>--- -</code></pre> -<hr /> -<hr /> -<hr /> -<hr /> -<pre><code>- - - -</code></pre> -<p>Asterisks:</p> -<hr /> -<hr /> -<hr /> -<hr /> -<pre><code>*** -</code></pre> -<hr /> -<hr /> -<hr /> -<hr /> -<pre><code>* * * -</code></pre> -<p>Underscores:</p> -<hr /> -<hr /> -<hr /> -<hr /> -<pre><code>___ -</code></pre> -<hr /> -<hr /> -<hr /> -<hr /> -<pre><code>_ _ _ -</code></pre> diff --git a/oldtests/Original/Horizontal_rules.markdown b/oldtests/Original/Horizontal_rules.markdown deleted file mode 100644 index 1594bda..0000000 --- a/oldtests/Original/Horizontal_rules.markdown +++ /dev/null @@ -1,67 +0,0 @@ -Dashes: - ---- - - --- - - --- - - --- - - --- - -- - - - - - - - - - - - - - - - - - - - - - - - - -Asterisks: - -*** - - *** - - *** - - *** - - *** - -* * * - - * * * - - * * * - - * * * - - * * * - - -Underscores: - -___ - - ___ - - ___ - - ___ - - ___ - -_ _ _ - - _ _ _ - - _ _ _ - - _ _ _ - - _ _ _ diff --git a/oldtests/Original/Images.html b/oldtests/Original/Images.html deleted file mode 100644 index bd5a7e0..0000000 --- a/oldtests/Original/Images.html +++ /dev/null @@ -1,11 +0,0 @@ -<p><img src="/path/to/img.jpg" alt="Alt text" /></p> -<p><img src="/path/to/img.jpg" alt="Alt text" title="Optional title" /></p> -<p>Inline within a paragraph: <a href="/url/">alt text</a>.</p> -<p><img src="/url/" alt="alt text" title="title preceded by two spaces" /></p> -<p><img src="/url/" alt="alt text" title="title has spaces afterward" /></p> -<p><img src="/url/" alt="alt text" /></p> -<p><img src="/url/" alt="alt text" title="with a title" />.</p> -<p><img src="" alt="Empty" /></p> -<p><img src="http://example.com/(parens).jpg" alt="this is a stupid URL" /></p> -<p><img src="/url/" alt="alt text" /></p> -<p><img src="/url/" alt="alt text" title="Title here" /></p> diff --git a/oldtests/Original/Images.markdown b/oldtests/Original/Images.markdown deleted file mode 100644 index 5707590..0000000 --- a/oldtests/Original/Images.markdown +++ /dev/null @@ -1,26 +0,0 @@ -![Alt text](/path/to/img.jpg) - -![Alt text](/path/to/img.jpg "Optional title") - -Inline within a paragraph: [alt text](/url/). - -![alt text](/url/ "title preceded by two spaces") - -![alt text](/url/ "title has spaces afterward" ) - -![alt text](</url/>) - -![alt text](</url/> "with a title"). - -![Empty]() - -![this is a stupid URL](http://example.com/(parens).jpg) - - -![alt text][foo] - - [foo]: /url/ - -![alt text][bar] - - [bar]: /url/ "Title here"
\ No newline at end of file diff --git a/oldtests/Original/Inline_HTML_Advanced.html b/oldtests/Original/Inline_HTML_Advanced.html deleted file mode 100644 index 631c135..0000000 --- a/oldtests/Original/Inline_HTML_Advanced.html +++ /dev/null @@ -1,23 +0,0 @@ -<p>Simple block on one line:</p> -<div>foo</div> -<p>And nested without indentation:</p> -<div> -<div> -<div> -foo -</div> -<div style=">"/> -</div> -<div>bar</div> -</div> -<p>And with attributes:</p> -<div> - <div id="foo"> - </div> -</div> -<p>This was broken in 1.0.2b7:</p> -<div class="inlinepage"> -<div class="toggleableend"> -foo -</div> -</div> diff --git a/oldtests/Original/Inline_HTML_Advanced.markdown b/oldtests/Original/Inline_HTML_Advanced.markdown deleted file mode 100644 index 3633f81..0000000 --- a/oldtests/Original/Inline_HTML_Advanced.markdown +++ /dev/null @@ -1,30 +0,0 @@ -Simple block on one line: - -<div>foo</div> - -And nested without indentation: - -<div> -<div> -<div> -foo -</div> -<div style=">"/> -</div> -<div>bar</div> -</div> - -And with attributes: - -<div> - <div id="foo"> - </div> -</div> - -This was broken in 1.0.2b7: - -<div class="inlinepage"> -<div class="toggleableend"> -foo -</div> -</div> diff --git a/oldtests/Original/Inline_HTML_Simple.html b/oldtests/Original/Inline_HTML_Simple.html deleted file mode 100644 index 923a18c..0000000 --- a/oldtests/Original/Inline_HTML_Simple.html +++ /dev/null @@ -1,45 +0,0 @@ -<p>Here's a simple block:</p> -<div> - foo -</div> -<p>This should be a code block, though:</p> -<pre><code><div> - foo -</div> -</code></pre> -<p>As should this:</p> -<pre><code><div>foo</div> -</code></pre> -<p>Now, nested:</p> -<div> - <div> - <div> - foo - </div> - </div> -</div> -<p>This should just be an HTML comment:</p> -<!-- Comment --> -<p>Multiline:</p> -<!-- -Blah -Blah ---> -<p>Code block:</p> -<pre><code><!-- Comment --> -</code></pre> -<p>Just plain comment, with trailing spaces on the line:</p> -<!-- foo --> -<p>Code:</p> -<pre><code><hr /> -</code></pre> -<p>Hr's:</p> -<hr> -<hr/> -<hr /> -<hr> -<hr/> -<hr /> -<hr class="foo" id="bar" /> -<hr class="foo" id="bar"/> -<hr class="foo" id="bar" > diff --git a/oldtests/Original/Inline_HTML_Simple.markdown b/oldtests/Original/Inline_HTML_Simple.markdown deleted file mode 100644 index 14aa2dc..0000000 --- a/oldtests/Original/Inline_HTML_Simple.markdown +++ /dev/null @@ -1,69 +0,0 @@ -Here's a simple block: - -<div> - foo -</div> - -This should be a code block, though: - - <div> - foo - </div> - -As should this: - - <div>foo</div> - -Now, nested: - -<div> - <div> - <div> - foo - </div> - </div> -</div> - -This should just be an HTML comment: - -<!-- Comment --> - -Multiline: - -<!-- -Blah -Blah ---> - -Code block: - - <!-- Comment --> - -Just plain comment, with trailing spaces on the line: - -<!-- foo --> - -Code: - - <hr /> - -Hr's: - -<hr> - -<hr/> - -<hr /> - -<hr> - -<hr/> - -<hr /> - -<hr class="foo" id="bar" /> - -<hr class="foo" id="bar"/> - -<hr class="foo" id="bar" > - diff --git a/oldtests/Original/Inline_HTML_comments.html b/oldtests/Original/Inline_HTML_comments.html deleted file mode 100644 index ebc4818..0000000 --- a/oldtests/Original/Inline_HTML_comments.html +++ /dev/null @@ -1,8 +0,0 @@ -<p>Paragraph one.</p> -<!-- This is a simple comment --> -<!-- - This is another comment. ---> -<p>Paragraph two.</p> -<!-- one comment block -- -- with two comments --> -<p>The end.</p> diff --git a/oldtests/Original/Inline_HTML_comments.markdown b/oldtests/Original/Inline_HTML_comments.markdown deleted file mode 100644 index 41d830d..0000000 --- a/oldtests/Original/Inline_HTML_comments.markdown +++ /dev/null @@ -1,13 +0,0 @@ -Paragraph one. - -<!-- This is a simple comment --> - -<!-- - This is another comment. ---> - -Paragraph two. - -<!-- one comment block -- -- with two comments --> - -The end. diff --git a/oldtests/Original/Links_inline_style.html b/oldtests/Original/Links_inline_style.html deleted file mode 100644 index feb4637..0000000 --- a/oldtests/Original/Links_inline_style.html +++ /dev/null @@ -1,12 +0,0 @@ -<p>Just a <a href="/url/">URL</a>.</p> -<p><a href="/url/" title="title">URL and title</a>.</p> -<p><a href="/url/" title="title preceded by two spaces">URL and title</a>.</p> -<p><a href="/url/" title="title preceded by a tab">URL and title</a>.</p> -<p><a href="/url/" title="title has spaces afterward">URL and title</a>.</p> -<p><a href="/url/">URL wrapped in angle brackets</a>.</p> -<p><a href="/url/" title="Here's the title">URL w/ angle brackets + title</a>.</p> -<p><a href="">Empty</a>.</p> -<p><a href="http://en.wikipedia.org/wiki/WIMP_(computing)">With parens in the URL</a></p> -<p>(With outer parens and <a href="/foo(bar)">parens in url</a>)</p> -<p><a href="/foo(bar)" title="and a title">With parens in the URL</a></p> -<p>(With outer parens and <a href="/foo(bar)" title="and a title">parens in url</a>)</p> diff --git a/oldtests/Original/Links_inline_style.markdown b/oldtests/Original/Links_inline_style.markdown deleted file mode 100644 index aba9658..0000000 --- a/oldtests/Original/Links_inline_style.markdown +++ /dev/null @@ -1,24 +0,0 @@ -Just a [URL](/url/). - -[URL and title](/url/ "title"). - -[URL and title](/url/ "title preceded by two spaces"). - -[URL and title](/url/ "title preceded by a tab"). - -[URL and title](/url/ "title has spaces afterward" ). - -[URL wrapped in angle brackets](</url/>). - -[URL w/ angle brackets + title](</url/> "Here's the title"). - -[Empty](). - -[With parens in the URL](http://en.wikipedia.org/wiki/WIMP_(computing)) - -(With outer parens and [parens in url](/foo(bar))) - - -[With parens in the URL](/foo(bar) "and a title") - -(With outer parens and [parens in url](/foo(bar) "and a title")) diff --git a/oldtests/Original/Links_reference_style.html b/oldtests/Original/Links_reference_style.html deleted file mode 100644 index 6d78b96..0000000 --- a/oldtests/Original/Links_reference_style.html +++ /dev/null @@ -1,28 +0,0 @@ -<p>Foo <a href="/url/" title="Title">bar</a>.</p> -<p>Foo <a href="/url/" title="Title">bar</a>.</p> -<p>Foo <a href="/url/" title="Title">bar</a>.</p> -<p>With <a href="/url/">embedded [brackets]</a>.</p> -<p>Indented <a href="/url">once</a>.</p> -<p>Indented <a href="/url">twice</a>.</p> -<p>Indented <a href="/url">thrice</a>.</p> -<p>Indented [four][] times.</p> -<pre><code>[four]: /url -</code></pre> -<hr /> -<p><a href="foo">this</a> should work</p> -<p>So should <a href="foo">this</a>.</p> -<p>And <a href="foo">this</a>.</p> -<p>And <a href="foo">this</a>.</p> -<p>And <a href="foo">this</a>.</p> -<p>But not [that] [].</p> -<p>Nor [that][].</p> -<p>Nor [that].</p> -<p>[Something in brackets like <a href="foo">this</a> should work]</p> -<p>[Same with <a href="foo">this</a>.]</p> -<p>In this case, <a href="/somethingelse/">this</a> points to something else.</p> -<p>Backslashing should suppress [this] and [this].</p> -<hr /> -<p>Here's one where the <a href="/url/">link -breaks</a> across lines.</p> -<p>Here's another where the <a href="/url/">link -breaks</a> across lines, but with a line-ending space.</p> diff --git a/oldtests/Original/Links_reference_style.markdown b/oldtests/Original/Links_reference_style.markdown deleted file mode 100644 index 341ec88..0000000 --- a/oldtests/Original/Links_reference_style.markdown +++ /dev/null @@ -1,71 +0,0 @@ -Foo [bar] [1]. - -Foo [bar][1]. - -Foo [bar] -[1]. - -[1]: /url/ "Title" - - -With [embedded [brackets]] [b]. - - -Indented [once][]. - -Indented [twice][]. - -Indented [thrice][]. - -Indented [four][] times. - - [once]: /url - - [twice]: /url - - [thrice]: /url - - [four]: /url - - -[b]: /url/ - -* * * - -[this] [this] should work - -So should [this][this]. - -And [this] []. - -And [this][]. - -And [this]. - -But not [that] []. - -Nor [that][]. - -Nor [that]. - -[Something in brackets like [this][] should work] - -[Same with [this].] - -In this case, [this](/somethingelse/) points to something else. - -Backslashing should suppress \[this] and [this\]. - -[this]: foo - - -* * * - -Here's one where the [link -breaks] across lines. - -Here's another where the [link -breaks] across lines, but with a line-ending space. - - -[link breaks]: /url/ diff --git a/oldtests/Original/Links_shortcut_references.html b/oldtests/Original/Links_shortcut_references.html deleted file mode 100644 index 8163ade..0000000 --- a/oldtests/Original/Links_shortcut_references.html +++ /dev/null @@ -1,6 +0,0 @@ -<p>This is the <a href="/simple">simple case</a>.</p> -<p>This one has a <a href="/foo">line -break</a>.</p> -<p>This one has a <a href="/foo">line -break</a> with a line-ending space.</p> -<p><a href="/that">this</a> and the <a href="/other">other</a></p> diff --git a/oldtests/Original/Links_shortcut_references.markdown b/oldtests/Original/Links_shortcut_references.markdown deleted file mode 100644 index 8c44c98..0000000 --- a/oldtests/Original/Links_shortcut_references.markdown +++ /dev/null @@ -1,20 +0,0 @@ -This is the [simple case]. - -[simple case]: /simple - - - -This one has a [line -break]. - -This one has a [line -break] with a line-ending space. - -[line break]: /foo - - -[this] [that] and the [other] - -[this]: /this -[that]: /that -[other]: /other diff --git a/oldtests/Original/Literal_quotes_in_titles.html b/oldtests/Original/Literal_quotes_in_titles.html deleted file mode 100644 index 62e8641..0000000 --- a/oldtests/Original/Literal_quotes_in_titles.html +++ /dev/null @@ -1,2 +0,0 @@ -<p>Foo <a href="/url/" title="Title with "quotes" inside">bar</a>.</p> -<p>Foo <a href="/url/" title="Title with "quotes" inside">bar</a>.</p> diff --git a/oldtests/Original/Literal_quotes_in_titles.markdown b/oldtests/Original/Literal_quotes_in_titles.markdown deleted file mode 100644 index 29d0e42..0000000 --- a/oldtests/Original/Literal_quotes_in_titles.markdown +++ /dev/null @@ -1,7 +0,0 @@ -Foo [bar][]. - -Foo [bar](/url/ "Title with "quotes" inside"). - - - [bar]: /url/ "Title with "quotes" inside" - diff --git a/oldtests/Original/Markdown_Documentation_Basics.html b/oldtests/Original/Markdown_Documentation_Basics.html deleted file mode 100644 index 0dee67f..0000000 --- a/oldtests/Original/Markdown_Documentation_Basics.html +++ /dev/null @@ -1,242 +0,0 @@ -<h1>Markdown: Basics</h1> -<ul id="ProjectSubmenu"> - <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li> - <li><a class="selected" title="Markdown Basics">Basics</a></li> - <li><a href="/projects/markdown/syntax" title="Markdown Syntax Documentation">Syntax</a></li> - <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li> - <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li> -</ul> -<h2>Getting the Gist of Markdown's Formatting Syntax</h2> -<p>This page offers a brief overview of what it's like to use Markdown. -The <a href="/projects/markdown/syntax" title="Markdown Syntax">syntax page</a> provides complete, detailed documentation for -every feature, but Markdown should be very easy to pick up simply by -looking at a few examples of it in action. The examples on this page -are written in a before/after style, showing example syntax and the -HTML output produced by Markdown.</p> -<p>It's also helpful to simply try Markdown out; the <a href="/projects/markdown/dingus" title="Markdown Dingus">Dingus</a> is a -web application that allows you type your own Markdown-formatted text -and translate it to XHTML.</p> -<p><strong>Note:</strong> This document is itself written using Markdown; you -can <a href="/projects/markdown/basics.text">see the source for it by adding '.text' to the URL</a>.</p> -<h2>Paragraphs, Headers, Blockquotes</h2> -<p>A paragraph is simply one or more consecutive lines of text, separated -by one or more blank lines. (A blank line is any line that looks like a -blank line -- a line containing nothing spaces or tabs is considered -blank.) Normal paragraphs should not be intended with spaces or tabs.</p> -<p>Markdown offers two styles of headers: <em>Setext</em> and <em>atx</em>. -Setext-style headers for <code><h1></code> and <code><h2></code> are created by -"underlining" with equal signs (<code>=</code>) and hyphens (<code>-</code>), respectively. -To create an atx-style header, you put 1-6 hash marks (<code>#</code>) at the -beginning of the line -- the number of hashes equals the resulting -HTML header level.</p> -<p>Blockquotes are indicated using email-style '<code>></code>' angle brackets.</p> -<p>Markdown:</p> -<pre><code>A First Level Header -==================== - -A Second Level Header ---------------------- - -Now is the time for all good men to come to -the aid of their country. This is just a -regular paragraph. - -The quick brown fox jumped over the lazy -dog's back. - -### Header 3 - -> This is a blockquote. -> -> This is the second paragraph in the blockquote. -> -> ## This is an H2 in a blockquote -</code></pre> -<p>Output:</p> -<pre><code><h1>A First Level Header</h1> - -<h2>A Second Level Header</h2> - -<p>Now is the time for all good men to come to -the aid of their country. This is just a -regular paragraph.</p> - -<p>The quick brown fox jumped over the lazy -dog's back.</p> - -<h3>Header 3</h3> - -<blockquote> - <p>This is a blockquote.</p> - - <p>This is the second paragraph in the blockquote.</p> - - <h2>This is an H2 in a blockquote</h2> -</blockquote> -</code></pre> -<h3>Phrase Emphasis</h3> -<p>Markdown uses asterisks and underscores to indicate spans of emphasis.</p> -<p>Markdown:</p> -<pre><code>Some of these words *are emphasized*. -Some of these words _are emphasized also_. - -Use two asterisks for **strong emphasis**. -Or, if you prefer, __use two underscores instead__. -</code></pre> -<p>Output:</p> -<pre><code><p>Some of these words <em>are emphasized</em>. -Some of these words <em>are emphasized also</em>.</p> - -<p>Use two asterisks for <strong>strong emphasis</strong>. -Or, if you prefer, <strong>use two underscores instead</strong>.</p> -</code></pre> -<h2>Lists</h2> -<p>Unordered (bulleted) lists use asterisks, pluses, and hyphens (<code>*</code>, -<code>+</code>, and <code>-</code>) as list markers. These three markers are -interchangable; this:</p> -<pre><code>* Candy. -* Gum. -* Booze. -</code></pre> -<p>this:</p> -<pre><code>+ Candy. -+ Gum. -+ Booze. -</code></pre> -<p>and this:</p> -<pre><code>- Candy. -- Gum. -- Booze. -</code></pre> -<p>all produce the same output:</p> -<pre><code><ul> -<li>Candy.</li> -<li>Gum.</li> -<li>Booze.</li> -</ul> -</code></pre> -<p>Ordered (numbered) lists use regular numbers, followed by periods, as -list markers:</p> -<pre><code>1. Red -2. Green -3. Blue -</code></pre> -<p>Output:</p> -<pre><code><ol> -<li>Red</li> -<li>Green</li> -<li>Blue</li> -</ol> -</code></pre> -<p>If you put blank lines between items, you'll get <code><p></code> tags for the -list item text. You can create multi-paragraph list items by indenting -the paragraphs by 4 spaces or 1 tab:</p> -<pre><code>* A list item. - - With multiple paragraphs. - -* Another item in the list. -</code></pre> -<p>Output:</p> -<pre><code><ul> -<li><p>A list item.</p> -<p>With multiple paragraphs.</p></li> -<li><p>Another item in the list.</p></li> -</ul> -</code></pre> -<h3>Links</h3> -<p>Markdown supports two styles for creating links: <em>inline</em> and -<em>reference</em>. With both styles, you use square brackets to delimit the -text you want to turn into a link.</p> -<p>Inline-style links use parentheses immediately after the link text. -For example:</p> -<pre><code>This is an [example link](http://example.com/). -</code></pre> -<p>Output:</p> -<pre><code><p>This is an <a href="http://example.com/"> -example link</a>.</p> -</code></pre> -<p>Optionally, you may include a title attribute in the parentheses:</p> -<pre><code>This is an [example link](http://example.com/ "With a Title"). -</code></pre> -<p>Output:</p> -<pre><code><p>This is an <a href="http://example.com/" title="With a Title"> -example link</a>.</p> -</code></pre> -<p>Reference-style links allow you to refer to your links by names, which -you define elsewhere in your document:</p> -<pre><code>I get 10 times more traffic from [Google][1] than from -[Yahoo][2] or [MSN][3]. - -[1]: http://google.com/ "Google" -[2]: http://search.yahoo.com/ "Yahoo Search" -[3]: http://search.msn.com/ "MSN Search" -</code></pre> -<p>Output:</p> -<pre><code><p>I get 10 times more traffic from <a href="http://google.com/" -title="Google">Google</a> than from <a href="http://search.yahoo.com/" -title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/" -title="MSN Search">MSN</a>.</p> -</code></pre> -<p>The title attribute is optional. Link names may contain letters, -numbers and spaces, but are <em>not</em> case sensitive:</p> -<pre><code>I start my morning with a cup of coffee and -[The New York Times][NY Times]. - -[ny times]: http://www.nytimes.com/ -</code></pre> -<p>Output:</p> -<pre><code><p>I start my morning with a cup of coffee and -<a href="http://www.nytimes.com/">The New York Times</a>.</p> -</code></pre> -<h3>Images</h3> -<p>Image syntax is very much like link syntax.</p> -<p>Inline (titles are optional):</p> -<pre><code>![alt text](/path/to/img.jpg "Title") -</code></pre> -<p>Reference-style:</p> -<pre><code>![alt text][id] - -[id]: /path/to/img.jpg "Title" -</code></pre> -<p>Both of the above examples produce the same output:</p> -<pre><code><img src="/path/to/img.jpg" alt="alt text" title="Title" /> -</code></pre> -<h3>Code</h3> -<p>In a regular paragraph, you can create code span by wrapping text in -backtick quotes. Any ampersands (<code>&</code>) and angle brackets (<code><</code> or -<code>></code>) will automatically be translated into HTML entities. This makes -it easy to use Markdown to write about HTML example code:</p> -<pre><code>I strongly recommend against using any `<blink>` tags. - -I wish SmartyPants used named entities like `&mdash;` -instead of decimal-encoded entites like `&#8212;`. -</code></pre> -<p>Output:</p> -<pre><code><p>I strongly recommend against using any -<code>&lt;blink&gt;</code> tags.</p> - -<p>I wish SmartyPants used named entities like -<code>&amp;mdash;</code> instead of decimal-encoded -entites like <code>&amp;#8212;</code>.</p> -</code></pre> -<p>To specify an entire block of pre-formatted code, indent every line of -the block by 4 spaces or 1 tab. Just like with code spans, <code>&</code>, <code><</code>, -and <code>></code> characters will be escaped automatically.</p> -<p>Markdown:</p> -<pre><code>If you want your page to validate under XHTML 1.0 Strict, -you've got to put paragraph tags in your blockquotes: - - <blockquote> - <p>For example.</p> - </blockquote> -</code></pre> -<p>Output:</p> -<pre><code><p>If you want your page to validate under XHTML 1.0 Strict, -you've got to put paragraph tags in your blockquotes:</p> - -<pre><code>&lt;blockquote&gt; - &lt;p&gt;For example.&lt;/p&gt; -&lt;/blockquote&gt; -</code></pre> -</code></pre> diff --git a/oldtests/Original/Markdown_Documentation_Basics.markdown b/oldtests/Original/Markdown_Documentation_Basics.markdown deleted file mode 100644 index 24eba65..0000000 --- a/oldtests/Original/Markdown_Documentation_Basics.markdown +++ /dev/null @@ -1,306 +0,0 @@ -Markdown: Basics -================ - -<ul id="ProjectSubmenu"> - <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li> - <li><a class="selected" title="Markdown Basics">Basics</a></li> - <li><a href="/projects/markdown/syntax" title="Markdown Syntax Documentation">Syntax</a></li> - <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li> - <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li> -</ul> - - -Getting the Gist of Markdown's Formatting Syntax ------------------------------------------------- - -This page offers a brief overview of what it's like to use Markdown. -The [syntax page] [s] provides complete, detailed documentation for -every feature, but Markdown should be very easy to pick up simply by -looking at a few examples of it in action. The examples on this page -are written in a before/after style, showing example syntax and the -HTML output produced by Markdown. - -It's also helpful to simply try Markdown out; the [Dingus] [d] is a -web application that allows you type your own Markdown-formatted text -and translate it to XHTML. - -**Note:** This document is itself written using Markdown; you -can [see the source for it by adding '.text' to the URL] [src]. - - [s]: /projects/markdown/syntax "Markdown Syntax" - [d]: /projects/markdown/dingus "Markdown Dingus" - [src]: /projects/markdown/basics.text - - -## Paragraphs, Headers, Blockquotes ## - -A paragraph is simply one or more consecutive lines of text, separated -by one or more blank lines. (A blank line is any line that looks like a -blank line -- a line containing nothing spaces or tabs is considered -blank.) Normal paragraphs should not be intended with spaces or tabs. - -Markdown offers two styles of headers: *Setext* and *atx*. -Setext-style headers for `<h1>` and `<h2>` are created by -"underlining" with equal signs (`=`) and hyphens (`-`), respectively. -To create an atx-style header, you put 1-6 hash marks (`#`) at the -beginning of the line -- the number of hashes equals the resulting -HTML header level. - -Blockquotes are indicated using email-style '`>`' angle brackets. - -Markdown: - - A First Level Header - ==================== - - A Second Level Header - --------------------- - - Now is the time for all good men to come to - the aid of their country. This is just a - regular paragraph. - - The quick brown fox jumped over the lazy - dog's back. - - ### Header 3 - - > This is a blockquote. - > - > This is the second paragraph in the blockquote. - > - > ## This is an H2 in a blockquote - - -Output: - - <h1>A First Level Header</h1> - - <h2>A Second Level Header</h2> - - <p>Now is the time for all good men to come to - the aid of their country. This is just a - regular paragraph.</p> - - <p>The quick brown fox jumped over the lazy - dog's back.</p> - - <h3>Header 3</h3> - - <blockquote> - <p>This is a blockquote.</p> - - <p>This is the second paragraph in the blockquote.</p> - - <h2>This is an H2 in a blockquote</h2> - </blockquote> - - - -### Phrase Emphasis ### - -Markdown uses asterisks and underscores to indicate spans of emphasis. - -Markdown: - - Some of these words *are emphasized*. - Some of these words _are emphasized also_. - - Use two asterisks for **strong emphasis**. - Or, if you prefer, __use two underscores instead__. - -Output: - - <p>Some of these words <em>are emphasized</em>. - Some of these words <em>are emphasized also</em>.</p> - - <p>Use two asterisks for <strong>strong emphasis</strong>. - Or, if you prefer, <strong>use two underscores instead</strong>.</p> - - - -## Lists ## - -Unordered (bulleted) lists use asterisks, pluses, and hyphens (`*`, -`+`, and `-`) as list markers. These three markers are -interchangable; this: - - * Candy. - * Gum. - * Booze. - -this: - - + Candy. - + Gum. - + Booze. - -and this: - - - Candy. - - Gum. - - Booze. - -all produce the same output: - - <ul> - <li>Candy.</li> - <li>Gum.</li> - <li>Booze.</li> - </ul> - -Ordered (numbered) lists use regular numbers, followed by periods, as -list markers: - - 1. Red - 2. Green - 3. Blue - -Output: - - <ol> - <li>Red</li> - <li>Green</li> - <li>Blue</li> - </ol> - -If you put blank lines between items, you'll get `<p>` tags for the -list item text. You can create multi-paragraph list items by indenting -the paragraphs by 4 spaces or 1 tab: - - * A list item. - - With multiple paragraphs. - - * Another item in the list. - -Output: - - <ul> - <li><p>A list item.</p> - <p>With multiple paragraphs.</p></li> - <li><p>Another item in the list.</p></li> - </ul> - - - -### Links ### - -Markdown supports two styles for creating links: *inline* and -*reference*. With both styles, you use square brackets to delimit the -text you want to turn into a link. - -Inline-style links use parentheses immediately after the link text. -For example: - - This is an [example link](http://example.com/). - -Output: - - <p>This is an <a href="http://example.com/"> - example link</a>.</p> - -Optionally, you may include a title attribute in the parentheses: - - This is an [example link](http://example.com/ "With a Title"). - -Output: - - <p>This is an <a href="http://example.com/" title="With a Title"> - example link</a>.</p> - -Reference-style links allow you to refer to your links by names, which -you define elsewhere in your document: - - I get 10 times more traffic from [Google][1] than from - [Yahoo][2] or [MSN][3]. - - [1]: http://google.com/ "Google" - [2]: http://search.yahoo.com/ "Yahoo Search" - [3]: http://search.msn.com/ "MSN Search" - -Output: - - <p>I get 10 times more traffic from <a href="http://google.com/" - title="Google">Google</a> than from <a href="http://search.yahoo.com/" - title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/" - title="MSN Search">MSN</a>.</p> - -The title attribute is optional. Link names may contain letters, -numbers and spaces, but are *not* case sensitive: - - I start my morning with a cup of coffee and - [The New York Times][NY Times]. - - [ny times]: http://www.nytimes.com/ - -Output: - - <p>I start my morning with a cup of coffee and - <a href="http://www.nytimes.com/">The New York Times</a>.</p> - - -### Images ### - -Image syntax is very much like link syntax. - -Inline (titles are optional): - - ![alt text](/path/to/img.jpg "Title") - -Reference-style: - - ![alt text][id] - - [id]: /path/to/img.jpg "Title" - -Both of the above examples produce the same output: - - <img src="/path/to/img.jpg" alt="alt text" title="Title" /> - - - -### Code ### - -In a regular paragraph, you can create code span by wrapping text in -backtick quotes. Any ampersands (`&`) and angle brackets (`<` or -`>`) will automatically be translated into HTML entities. This makes -it easy to use Markdown to write about HTML example code: - - I strongly recommend against using any `<blink>` tags. - - I wish SmartyPants used named entities like `—` - instead of decimal-encoded entites like `—`. - -Output: - - <p>I strongly recommend against using any - <code><blink></code> tags.</p> - - <p>I wish SmartyPants used named entities like - <code>&mdash;</code> instead of decimal-encoded - entites like <code>&#8212;</code>.</p> - - -To specify an entire block of pre-formatted code, indent every line of -the block by 4 spaces or 1 tab. Just like with code spans, `&`, `<`, -and `>` characters will be escaped automatically. - -Markdown: - - If you want your page to validate under XHTML 1.0 Strict, - you've got to put paragraph tags in your blockquotes: - - <blockquote> - <p>For example.</p> - </blockquote> - -Output: - - <p>If you want your page to validate under XHTML 1.0 Strict, - you've got to put paragraph tags in your blockquotes:</p> - - <pre><code><blockquote> - <p>For example.</p> - </blockquote> - </code></pre> diff --git a/oldtests/Original/Markdown_Documentation_Syntax.html b/oldtests/Original/Markdown_Documentation_Syntax.html deleted file mode 100644 index f379dcf..0000000 --- a/oldtests/Original/Markdown_Documentation_Syntax.html +++ /dev/null @@ -1,708 +0,0 @@ -<h1>Markdown: Syntax</h1> -<ul id="ProjectSubmenu"> - <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li> - <li><a href="/projects/markdown/basics" title="Markdown Basics">Basics</a></li> - <li><a class="selected" title="Markdown Syntax Documentation">Syntax</a></li> - <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li> - <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li> -</ul> -<ul> -<li><a href="#overview">Overview</a> -<ul> -<li><a href="#philosophy">Philosophy</a></li> -<li><a href="#html">Inline HTML</a></li> -<li><a href="#autoescape">Automatic Escaping for Special Characters</a></li> -</ul></li> -<li><a href="#block">Block Elements</a> -<ul> -<li><a href="#p">Paragraphs and Line Breaks</a></li> -<li><a href="#header">Headers</a></li> -<li><a href="#blockquote">Blockquotes</a></li> -<li><a href="#list">Lists</a></li> -<li><a href="#precode">Code Blocks</a></li> -<li><a href="#hr">Horizontal Rules</a></li> -</ul></li> -<li><a href="#span">Span Elements</a> -<ul> -<li><a href="#link">Links</a></li> -<li><a href="#em">Emphasis</a></li> -<li><a href="#code">Code</a></li> -<li><a href="#img">Images</a></li> -</ul></li> -<li><a href="#misc">Miscellaneous</a> -<ul> -<li><a href="#backslash">Backslash Escapes</a></li> -<li><a href="#autolink">Automatic Links</a></li> -</ul></li> -</ul> -<p><strong>Note:</strong> This document is itself written using Markdown; you -can <a href="/projects/markdown/syntax.text">see the source for it by adding '.text' to the URL</a>.</p> -<hr /> -<h2 id="overview">Overview</h2> -<h3 id="philosophy">Philosophy</h3> -<p>Markdown is intended to be as easy-to-read and easy-to-write as is feasible.</p> -<p>Readability, however, is emphasized above all else. A Markdown-formatted -document should be publishable as-is, as plain text, without looking -like it's been marked up with tags or formatting instructions. While -Markdown's syntax has been influenced by several existing text-to-HTML -filters -- including <a href="http://docutils.sourceforge.net/mirror/setext.html">Setext</a>, <a href="http://www.aaronsw.com/2002/atx/">atx</a>, <a href="http://textism.com/tools/textile/">Textile</a>, <a href="http://docutils.sourceforge.net/rst.html">reStructuredText</a>, -<a href="http://www.triptico.com/software/grutatxt.html">Grutatext</a>, and <a href="http://ettext.taint.org/doc/">EtText</a> -- the single biggest source of -inspiration for Markdown's syntax is the format of plain text email.</p> -<p>To this end, Markdown's syntax is comprised entirely of punctuation -characters, which punctuation characters have been carefully chosen so -as to look like what they mean. E.g., asterisks around a word actually -look like *emphasis*. Markdown lists look like, well, lists. Even -blockquotes look like quoted passages of text, assuming you've ever -used email.</p> -<h3 id="html">Inline HTML</h3> -<p>Markdown's syntax is intended for one purpose: to be used as a -format for <em>writing</em> for the web.</p> -<p>Markdown is not a replacement for HTML, or even close to it. Its -syntax is very small, corresponding only to a very small subset of -HTML tags. The idea is <em>not</em> to create a syntax that makes it easier -to insert HTML tags. In my opinion, HTML tags are already easy to -insert. The idea for Markdown is to make it easy to read, write, and -edit prose. HTML is a <em>publishing</em> format; Markdown is a <em>writing</em> -format. Thus, Markdown's formatting syntax only addresses issues that -can be conveyed in plain text.</p> -<p>For any markup that is not covered by Markdown's syntax, you simply -use HTML itself. There's no need to preface it or delimit it to -indicate that you're switching from Markdown to HTML; you just use -the tags.</p> -<p>The only restrictions are that block-level HTML elements -- e.g. <code><div></code>, -<code><table></code>, <code><pre></code>, <code><p></code>, etc. -- must be separated from surrounding -content by blank lines, and the start and end tags of the block should -not be indented with tabs or spaces. Markdown is smart enough not -to add extra (unwanted) <code><p></code> tags around HTML block-level tags.</p> -<p>For example, to add an HTML table to a Markdown article:</p> -<pre><code>This is a regular paragraph. - -<table> - <tr> - <td>Foo</td> - </tr> -</table> - -This is another regular paragraph. -</code></pre> -<p>Note that Markdown formatting syntax is not processed within block-level -HTML tags. E.g., you can't use Markdown-style <code>*emphasis*</code> inside an -HTML block.</p> -<p>Span-level HTML tags -- e.g. <code><span></code>, <code><cite></code>, or <code><del></code> -- can be -used anywhere in a Markdown paragraph, list item, or header. If you -want, you can even use HTML tags instead of Markdown formatting; e.g. if -you'd prefer to use HTML <code><a></code> or <code><img></code> tags instead of Markdown's -link or image syntax, go right ahead.</p> -<p>Unlike block-level HTML tags, Markdown syntax <em>is</em> processed within -span-level tags.</p> -<h3 id="autoescape">Automatic Escaping for Special Characters</h3> -<p>In HTML, there are two characters that demand special treatment: <code><</code> -and <code>&</code>. Left angle brackets are used to start tags; ampersands are -used to denote HTML entities. If you want to use them as literal -characters, you must escape them as entities, e.g. <code>&lt;</code>, and -<code>&amp;</code>.</p> -<p>Ampersands in particular are bedeviling for web writers. If you want to -write about 'AT&T', you need to write '<code>AT&amp;T</code>'. You even need to -escape ampersands within URLs. Thus, if you want to link to:</p> -<pre><code>http://images.google.com/images?num=30&q=larry+bird -</code></pre> -<p>you need to encode the URL as:</p> -<pre><code>http://images.google.com/images?num=30&amp;q=larry+bird -</code></pre> -<p>in your anchor tag <code>href</code> attribute. Needless to say, this is easy to -forget, and is probably the single most common source of HTML validation -errors in otherwise well-marked-up web sites.</p> -<p>Markdown allows you to use these characters naturally, taking care of -all the necessary escaping for you. If you use an ampersand as part of -an HTML entity, it remains unchanged; otherwise it will be translated -into <code>&amp;</code>.</p> -<p>So, if you want to include a copyright symbol in your article, you can write:</p> -<pre><code>&copy; -</code></pre> -<p>and Markdown will leave it alone. But if you write:</p> -<pre><code>AT&T -</code></pre> -<p>Markdown will translate it to:</p> -<pre><code>AT&amp;T -</code></pre> -<p>Similarly, because Markdown supports <a href="#html">inline HTML</a>, if you use -angle brackets as delimiters for HTML tags, Markdown will treat them as -such. But if you write:</p> -<pre><code>4 < 5 -</code></pre> -<p>Markdown will translate it to:</p> -<pre><code>4 &lt; 5 -</code></pre> -<p>However, inside Markdown code spans and blocks, angle brackets and -ampersands are <em>always</em> encoded automatically. This makes it easy to use -Markdown to write about HTML code. (As opposed to raw HTML, which is a -terrible format for writing about HTML syntax, because every single <code><</code> -and <code>&</code> in your example code needs to be escaped.)</p> -<hr /> -<h2 id="block">Block Elements</h2> -<h3 id="p">Paragraphs and Line Breaks</h3> -<p>A paragraph is simply one or more consecutive lines of text, separated -by one or more blank lines. (A blank line is any line that looks like a -blank line -- a line containing nothing but spaces or tabs is considered -blank.) Normal paragraphs should not be intended with spaces or tabs.</p> -<p>The implication of the "one or more consecutive lines of text" rule is -that Markdown supports "hard-wrapped" text paragraphs. This differs -significantly from most other text-to-HTML formatters (including Movable -Type's "Convert Line Breaks" option) which translate every line break -character in a paragraph into a <code><br /></code> tag.</p> -<p>When you <em>do</em> want to insert a <code><br /></code> break tag using Markdown, you -end a line with two or more spaces, then type return.</p> -<p>Yes, this takes a tad more effort to create a <code><br /></code>, but a simplistic -"every line break is a <code><br /></code>" rule wouldn't work for Markdown. -Markdown's email-style <a href="#blockquote">blockquoting</a> and multi-paragraph <a href="#list">list items</a> -work best -- and look better -- when you format them with hard breaks.</p> -<h3 id="header">Headers</h3> -<p>Markdown supports two styles of headers, <a href="http://docutils.sourceforge.net/mirror/setext.html">Setext</a> and <a href="http://www.aaronsw.com/2002/atx/">atx</a>.</p> -<p>Setext-style headers are "underlined" using equal signs (for first-level -headers) and dashes (for second-level headers). For example:</p> -<pre><code>This is an H1 -============= - -This is an H2 -------------- -</code></pre> -<p>Any number of underlining <code>=</code>'s or <code>-</code>'s will work.</p> -<p>Atx-style headers use 1-6 hash characters at the start of the line, -corresponding to header levels 1-6. For example:</p> -<pre><code># This is an H1 - -## This is an H2 - -###### This is an H6 -</code></pre> -<p>Optionally, you may "close" atx-style headers. This is purely -cosmetic -- you can use this if you think it looks better. The -closing hashes don't even need to match the number of hashes -used to open the header. (The number of opening hashes -determines the header level.) :</p> -<pre><code># This is an H1 # - -## This is an H2 ## - -### This is an H3 ###### -</code></pre> -<h3 id="blockquote">Blockquotes</h3> -<p>Markdown uses email-style <code>></code> characters for blockquoting. If you're -familiar with quoting passages of text in an email message, then you -know how to create a blockquote in Markdown. It looks best if you hard -wrap the text and put a <code>></code> before every line:</p> -<pre><code>> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, -> consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. -> Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. -> -> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse -> id sem consectetuer libero luctus adipiscing. -</code></pre> -<p>Markdown allows you to be lazy and only put the <code>></code> before the first -line of a hard-wrapped paragraph:</p> -<pre><code>> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, -consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. -Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. - -> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse -id sem consectetuer libero luctus adipiscing. -</code></pre> -<p>Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by -adding additional levels of <code>></code>:</p> -<pre><code>> This is the first level of quoting. -> -> > This is nested blockquote. -> -> Back to the first level. -</code></pre> -<p>Blockquotes can contain other Markdown elements, including headers, lists, -and code blocks:</p> -<pre><code>> ## This is a header. -> -> 1. This is the first list item. -> 2. This is the second list item. -> -> Here's some example code: -> -> return shell_exec("echo $input | $markdown_script"); -</code></pre> -<p>Any decent text editor should make email-style quoting easy. For -example, with BBEdit, you can make a selection and choose Increase -Quote Level from the Text menu.</p> -<h3 id="list">Lists</h3> -<p>Markdown supports ordered (numbered) and unordered (bulleted) lists.</p> -<p>Unordered lists use asterisks, pluses, and hyphens -- interchangably --- as list markers:</p> -<pre><code>* Red -* Green -* Blue -</code></pre> -<p>is equivalent to:</p> -<pre><code>+ Red -+ Green -+ Blue -</code></pre> -<p>and:</p> -<pre><code>- Red -- Green -- Blue -</code></pre> -<p>Ordered lists use numbers followed by periods:</p> -<pre><code>1. Bird -2. McHale -3. Parish -</code></pre> -<p>It's important to note that the actual numbers you use to mark the -list have no effect on the HTML output Markdown produces. The HTML -Markdown produces from the above list is:</p> -<pre><code><ol> -<li>Bird</li> -<li>McHale</li> -<li>Parish</li> -</ol> -</code></pre> -<p>If you instead wrote the list in Markdown like this:</p> -<pre><code>1. Bird -1. McHale -1. Parish -</code></pre> -<p>or even:</p> -<pre><code>3. Bird -1. McHale -8. Parish -</code></pre> -<p>you'd get the exact same HTML output. The point is, if you want to, -you can use ordinal numbers in your ordered Markdown lists, so that -the numbers in your source match the numbers in your published HTML. -But if you want to be lazy, you don't have to.</p> -<p>If you do use lazy list numbering, however, you should still start the -list with the number 1. At some point in the future, Markdown may support -starting ordered lists at an arbitrary number.</p> -<p>List markers typically start at the left margin, but may be indented by -up to three spaces. List markers must be followed by one or more spaces -or a tab.</p> -<p>To make lists look nice, you can wrap items with hanging indents:</p> -<pre><code>* Lorem ipsum dolor sit amet, consectetuer adipiscing elit. - Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, - viverra nec, fringilla in, laoreet vitae, risus. -* Donec sit amet nisl. Aliquam semper ipsum sit amet velit. - Suspendisse id sem consectetuer libero luctus adipiscing. -</code></pre> -<p>But if you want to be lazy, you don't have to:</p> -<pre><code>* Lorem ipsum dolor sit amet, consectetuer adipiscing elit. -Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, -viverra nec, fringilla in, laoreet vitae, risus. -* Donec sit amet nisl. Aliquam semper ipsum sit amet velit. -Suspendisse id sem consectetuer libero luctus adipiscing. -</code></pre> -<p>If list items are separated by blank lines, Markdown will wrap the -items in <code><p></code> tags in the HTML output. For example, this input:</p> -<pre><code>* Bird -* Magic -</code></pre> -<p>will turn into:</p> -<pre><code><ul> -<li>Bird</li> -<li>Magic</li> -</ul> -</code></pre> -<p>But this:</p> -<pre><code>* Bird - -* Magic -</code></pre> -<p>will turn into:</p> -<pre><code><ul> -<li><p>Bird</p></li> -<li><p>Magic</p></li> -</ul> -</code></pre> -<p>List items may consist of multiple paragraphs. Each subsequent -paragraph in a list item must be intended by either 4 spaces -or one tab:</p> -<pre><code>1. This is a list item with two paragraphs. Lorem ipsum dolor - sit amet, consectetuer adipiscing elit. Aliquam hendrerit - mi posuere lectus. - - Vestibulum enim wisi, viverra nec, fringilla in, laoreet - vitae, risus. Donec sit amet nisl. Aliquam semper ipsum - sit amet velit. - -2. Suspendisse id sem consectetuer libero luctus adipiscing. -</code></pre> -<p>It looks nice if you indent every line of the subsequent -paragraphs, but here again, Markdown will allow you to be -lazy:</p> -<pre><code>* This is a list item with two paragraphs. - - This is the second paragraph in the list item. You're -only required to indent the first line. Lorem ipsum dolor -sit amet, consectetuer adipiscing elit. - -* Another item in the same list. -</code></pre> -<p>To put a blockquote within a list item, the blockquote's <code>></code> -delimiters need to be indented:</p> -<pre><code>* A list item with a blockquote: - - > This is a blockquote - > inside a list item. -</code></pre> -<p>To put a code block within a list item, the code block needs -to be indented <em>twice</em> -- 8 spaces or two tabs:</p> -<pre><code>* A list item with a code block: - - <code goes here> -</code></pre> -<p>It's worth noting that it's possible to trigger an ordered list by -accident, by writing something like this:</p> -<pre><code>1986. What a great season. -</code></pre> -<p>In other words, a <em>number-period-space</em> sequence at the beginning of a -line. To avoid this, you can backslash-escape the period:</p> -<pre><code>1986\. What a great season. -</code></pre> -<h3 id="precode">Code Blocks</h3> -<p>Pre-formatted code blocks are used for writing about programming or -markup source code. Rather than forming normal paragraphs, the lines -of a code block are interpreted literally. Markdown wraps a code block -in both <code><pre></code> and <code><code></code> tags.</p> -<p>To produce a code block in Markdown, simply indent every line of the -block by at least 4 spaces or 1 tab. For example, given this input:</p> -<pre><code>This is a normal paragraph: - - This is a code block. -</code></pre> -<p>Markdown will generate:</p> -<pre><code><p>This is a normal paragraph:</p> - -<pre><code>This is a code block. -</code></pre> -</code></pre> -<p>One level of indentation -- 4 spaces or 1 tab -- is removed from each -line of the code block. For example, this:</p> -<pre><code>Here is an example of AppleScript: - - tell application "Foo" - beep - end tell -</code></pre> -<p>will turn into:</p> -<pre><code><p>Here is an example of AppleScript:</p> - -<pre><code>tell application "Foo" - beep -end tell -</code></pre> -</code></pre> -<p>A code block continues until it reaches a line that is not indented -(or the end of the article).</p> -<p>Within a code block, ampersands (<code>&</code>) and angle brackets (<code><</code> and <code>></code>) -are automatically converted into HTML entities. This makes it very -easy to include example HTML source code using Markdown -- just paste -it and indent it, and Markdown will handle the hassle of encoding the -ampersands and angle brackets. For example, this:</p> -<pre><code> <div class="footer"> - &copy; 2004 Foo Corporation - </div> -</code></pre> -<p>will turn into:</p> -<pre><code><pre><code>&lt;div class="footer"&gt; - &amp;copy; 2004 Foo Corporation -&lt;/div&gt; -</code></pre> -</code></pre> -<p>Regular Markdown syntax is not processed within code blocks. E.g., -asterisks are just literal asterisks within a code block. This means -it's also easy to use Markdown to write about Markdown's own syntax.</p> -<h3 id="hr">Horizontal Rules</h3> -<p>You can produce a horizontal rule tag (<code><hr /></code>) by placing three or -more hyphens, asterisks, or underscores on a line by themselves. If you -wish, you may use spaces between the hyphens or asterisks. Each of the -following lines will produce a horizontal rule:</p> -<pre><code>* * * - -*** - -***** - -- - - - ---------------------------------------- - -_ _ _ -</code></pre> -<hr /> -<h2 id="span">Span Elements</h2> -<h3 id="link">Links</h3> -<p>Markdown supports two style of links: <em>inline</em> and <em>reference</em>.</p> -<p>In both styles, the link text is delimited by [square brackets].</p> -<p>To create an inline link, use a set of regular parentheses immediately -after the link text's closing square bracket. Inside the parentheses, -put the URL where you want the link to point, along with an <em>optional</em> -title for the link, surrounded in quotes. For example:</p> -<pre><code>This is [an example](http://example.com/ "Title") inline link. - -[This link](http://example.net/) has no title attribute. -</code></pre> -<p>Will produce:</p> -<pre><code><p>This is <a href="http://example.com/" title="Title"> -an example</a> inline link.</p> - -<p><a href="http://example.net/">This link</a> has no -title attribute.</p> -</code></pre> -<p>If you're referring to a local resource on the same server, you can -use relative paths:</p> -<pre><code>See my [About](/about/) page for details. -</code></pre> -<p>Reference-style links use a second set of square brackets, inside -which you place a label of your choosing to identify the link:</p> -<pre><code>This is [an example][id] reference-style link. -</code></pre> -<p>You can optionally use a space to separate the sets of brackets:</p> -<pre><code>This is [an example] [id] reference-style link. -</code></pre> -<p>Then, anywhere in the document, you define your link label like this, -on a line by itself:</p> -<pre><code>[id]: http://example.com/ "Optional Title Here" -</code></pre> -<p>That is:</p> -<ul> -<li>Square brackets containing the link identifier (optionally -indented from the left margin using up to three spaces);</li> -<li>followed by a colon;</li> -<li>followed by one or more spaces (or tabs);</li> -<li>followed by the URL for the link;</li> -<li>optionally followed by a title attribute for the link, enclosed -in double or single quotes.</li> -</ul> -<p>The link URL may, optionally, be surrounded by angle brackets:</p> -<pre><code>[id]: <http://example.com/> "Optional Title Here" -</code></pre> -<p>You can put the title attribute on the next line and use extra spaces -or tabs for padding, which tends to look better with longer URLs:</p> -<pre><code>[id]: http://example.com/longish/path/to/resource/here - "Optional Title Here" -</code></pre> -<p>Link definitions are only used for creating links during Markdown -processing, and are stripped from your document in the HTML output.</p> -<p>Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are <em>not</em> case sensitive. E.g. these two links:</p> -<pre><code>[link text][a] -[link text][A] -</code></pre> -<p>are equivalent.</p> -<p>The <em>implicit link name</em> shortcut allows you to omit the name of the -link, in which case the link text itself is used as the name. -Just use an empty set of square brackets -- e.g., to link the word -"Google" to the google.com web site, you could simply write:</p> -<pre><code>[Google][] -</code></pre> -<p>And then define the link:</p> -<pre><code>[Google]: http://google.com/ -</code></pre> -<p>Because link names may contain spaces, this shortcut even works for -multiple words in the link text:</p> -<pre><code>Visit [Daring Fireball][] for more information. -</code></pre> -<p>And then define the link:</p> -<pre><code>[Daring Fireball]: http://daringfireball.net/ -</code></pre> -<p>Link definitions can be placed anywhere in your Markdown document. I -tend to put them immediately after each paragraph in which they're -used, but if you want, you can put them all at the end of your -document, sort of like footnotes.</p> -<p>Here's an example of reference links in action:</p> -<pre><code>I get 10 times more traffic from [Google] [1] than from -[Yahoo] [2] or [MSN] [3]. - - [1]: http://google.com/ "Google" - [2]: http://search.yahoo.com/ "Yahoo Search" - [3]: http://search.msn.com/ "MSN Search" -</code></pre> -<p>Using the implicit link name shortcut, you could instead write:</p> -<pre><code>I get 10 times more traffic from [Google][] than from -[Yahoo][] or [MSN][]. - - [google]: http://google.com/ "Google" - [yahoo]: http://search.yahoo.com/ "Yahoo Search" - [msn]: http://search.msn.com/ "MSN Search" -</code></pre> -<p>Both of the above examples will produce the following HTML output:</p> -<pre><code><p>I get 10 times more traffic from <a href="http://google.com/" -title="Google">Google</a> than from -<a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a> -or <a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p> -</code></pre> -<p>For comparison, here is the same paragraph written using -Markdown's inline link style:</p> -<pre><code>I get 10 times more traffic from [Google](http://google.com/ "Google") -than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or -[MSN](http://search.msn.com/ "MSN Search"). -</code></pre> -<p>The point of reference-style links is not that they're easier to -write. The point is that with reference-style links, your document -source is vastly more readable. Compare the above examples: using -reference-style links, the paragraph itself is only 81 characters -long; with inline-style links, it's 176 characters; and as raw HTML, -it's 234 characters. In the raw HTML, there's more markup than there -is text.</p> -<p>With Markdown's reference-style links, a source document much more -closely resembles the final output, as rendered in a browser. By -allowing you to move the markup-related metadata out of the paragraph, -you can add links without interrupting the narrative flow of your -prose.</p> -<h3 id="em">Emphasis</h3> -<p>Markdown treats asterisks (<code>*</code>) and underscores (<code>_</code>) as indicators of -emphasis. Text wrapped with one <code>*</code> or <code>_</code> will be wrapped with an -HTML <code><em></code> tag; double <code>*</code>'s or <code>_</code>'s will be wrapped with an HTML -<code><strong></code> tag. E.g., this input:</p> -<pre><code>*single asterisks* - -_single underscores_ - -**double asterisks** - -__double underscores__ -</code></pre> -<p>will produce:</p> -<pre><code><em>single asterisks</em> - -<em>single underscores</em> - -<strong>double asterisks</strong> - -<strong>double underscores</strong> -</code></pre> -<p>You can use whichever style you prefer; the lone restriction is that -the same character must be used to open and close an emphasis span.</p> -<p>Emphasis can be used in the middle of a word:</p> -<pre><code>un*fucking*believable -</code></pre> -<p>But if you surround an <code>*</code> or <code>_</code> with spaces, it'll be treated as a -literal asterisk or underscore.</p> -<p>To produce a literal asterisk or underscore at a position where it -would otherwise be used as an emphasis delimiter, you can backslash -escape it:</p> -<pre><code>\*this text is surrounded by literal asterisks\* -</code></pre> -<h3 id="code">Code</h3> -<p>To indicate a span of code, wrap it with backtick quotes (<code>`</code>). -Unlike a pre-formatted code block, a code span indicates code within a -normal paragraph. For example:</p> -<pre><code>Use the `printf()` function. -</code></pre> -<p>will produce:</p> -<pre><code><p>Use the <code>printf()</code> function.</p> -</code></pre> -<p>To include a literal backtick character within a code span, you can use -multiple backticks as the opening and closing delimiters:</p> -<pre><code>``There is a literal backtick (`) here.`` -</code></pre> -<p>which will produce this:</p> -<pre><code><p><code>There is a literal backtick (`) here.</code></p> -</code></pre> -<p>The backtick delimiters surrounding a code span may include spaces -- -one after the opening, one before the closing. This allows you to place -literal backtick characters at the beginning or end of a code span:</p> -<pre><code>A single backtick in a code span: `` ` `` - -A backtick-delimited string in a code span: `` `foo` `` -</code></pre> -<p>will produce:</p> -<pre><code><p>A single backtick in a code span: <code>`</code></p> - -<p>A backtick-delimited string in a code span: <code>`foo`</code></p> -</code></pre> -<p>With a code span, ampersands and angle brackets are encoded as HTML -entities automatically, which makes it easy to include example HTML -tags. Markdown will turn this:</p> -<pre><code>Please don't use any `<blink>` tags. -</code></pre> -<p>into:</p> -<pre><code><p>Please don't use any <code>&lt;blink&gt;</code> tags.</p> -</code></pre> -<p>You can write this:</p> -<pre><code>`&#8212;` is the decimal-encoded equivalent of `&mdash;`. -</code></pre> -<p>to produce:</p> -<pre><code><p><code>&amp;#8212;</code> is the decimal-encoded -equivalent of <code>&amp;mdash;</code>.</p> -</code></pre> -<h3 id="img">Images</h3> -<p>Admittedly, it's fairly difficult to devise a "natural" syntax for -placing images into a plain text document format.</p> -<p>Markdown uses an image syntax that is intended to resemble the syntax -for links, allowing for two styles: <em>inline</em> and <em>reference</em>.</p> -<p>Inline image syntax looks like this:</p> -<pre><code>![Alt text](/path/to/img.jpg) - -![Alt text](/path/to/img.jpg "Optional title") -</code></pre> -<p>That is:</p> -<ul> -<li>An exclamation mark: <code>!</code>;</li> -<li>followed by a set of square brackets, containing the <code>alt</code> -attribute text for the image;</li> -<li>followed by a set of parentheses, containing the URL or path to -the image, and an optional <code>title</code> attribute enclosed in double -or single quotes.</li> -</ul> -<p>Reference-style image syntax looks like this:</p> -<pre><code>![Alt text][id] -</code></pre> -<p>Where "id" is the name of a defined image reference. Image references -are defined using syntax identical to link references:</p> -<pre><code>[id]: url/to/image "Optional title attribute" -</code></pre> -<p>As of this writing, Markdown has no syntax for specifying the -dimensions of an image; if this is important to you, you can simply -use regular HTML <code><img></code> tags.</p> -<hr /> -<h2 id="misc">Miscellaneous</h2> -<h3 id="autolink">Automatic Links</h3> -<p>Markdown supports a shortcut style for creating "automatic" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this:</p> -<pre><code><http://example.com/> -</code></pre> -<p>Markdown will turn this into:</p> -<pre><code><a href="http://example.com/">http://example.com/</a> -</code></pre> -<p>Automatic links for email addresses work similarly, except that -Markdown will also perform a bit of randomized decimal and hex -entity-encoding to help obscure your address from address-harvesting -spambots. For example, Markdown will turn this:</p> -<pre><code><address@example.com> -</code></pre> -<p>into something like this:</p> -<pre><code><a href="&#x6D;&#x61;i&#x6C;&#x74;&#x6F;:&#x61;&#x64;&#x64;&#x72;&#x65; -&#115;&#115;&#64;&#101;&#120;&#x61;&#109;&#x70;&#x6C;e&#x2E;&#99;&#111; -&#109;">&#x61;&#x64;&#x64;&#x72;&#x65;&#115;&#115;&#64;&#101;&#120;&#x61; -&#109;&#x70;&#x6C;e&#x2E;&#99;&#111;&#109;</a> -</code></pre> -<p>which will render in a browser as a clickable link to "address@example.com".</p> -<p>(This sort of entity-encoding trick will indeed fool many, if not -most, address-harvesting bots, but it definitely won't fool all of -them. It's better than nothing, but an address published in this way -will probably eventually start receiving spam.)</p> -<h3 id="backslash">Backslash Escapes</h3> -<p>Markdown allows you to use backslash escapes to generate literal -characters which would otherwise have special meaning in Markdown's -formatting syntax. For example, if you wanted to surround a word with -literal asterisks (instead of an HTML <code><em></code> tag), you can backslashes -before the asterisks, like this:</p> -<pre><code>\*literal asterisks\* -</code></pre> -<p>Markdown provides backslash escapes for the following characters:</p> -<pre><code>\ backslash -` backtick -* asterisk -_ underscore -{} curly braces -[] square brackets -() parentheses -# hash mark -+ plus sign -- minus sign (hyphen) -. dot -! exclamation mark -</code></pre> diff --git a/oldtests/Original/Markdown_Documentation_Syntax.markdown b/oldtests/Original/Markdown_Documentation_Syntax.markdown deleted file mode 100644 index 57360a1..0000000 --- a/oldtests/Original/Markdown_Documentation_Syntax.markdown +++ /dev/null @@ -1,888 +0,0 @@ -Markdown: Syntax -================ - -<ul id="ProjectSubmenu"> - <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li> - <li><a href="/projects/markdown/basics" title="Markdown Basics">Basics</a></li> - <li><a class="selected" title="Markdown Syntax Documentation">Syntax</a></li> - <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li> - <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li> -</ul> - - -* [Overview](#overview) - * [Philosophy](#philosophy) - * [Inline HTML](#html) - * [Automatic Escaping for Special Characters](#autoescape) -* [Block Elements](#block) - * [Paragraphs and Line Breaks](#p) - * [Headers](#header) - * [Blockquotes](#blockquote) - * [Lists](#list) - * [Code Blocks](#precode) - * [Horizontal Rules](#hr) -* [Span Elements](#span) - * [Links](#link) - * [Emphasis](#em) - * [Code](#code) - * [Images](#img) -* [Miscellaneous](#misc) - * [Backslash Escapes](#backslash) - * [Automatic Links](#autolink) - - -**Note:** This document is itself written using Markdown; you -can [see the source for it by adding '.text' to the URL][src]. - - [src]: /projects/markdown/syntax.text - -* * * - -<h2 id="overview">Overview</h2> - -<h3 id="philosophy">Philosophy</h3> - -Markdown is intended to be as easy-to-read and easy-to-write as is feasible. - -Readability, however, is emphasized above all else. A Markdown-formatted -document should be publishable as-is, as plain text, without looking -like it's been marked up with tags or formatting instructions. While -Markdown's syntax has been influenced by several existing text-to-HTML -filters -- including [Setext] [1], [atx] [2], [Textile] [3], [reStructuredText] [4], -[Grutatext] [5], and [EtText] [6] -- the single biggest source of -inspiration for Markdown's syntax is the format of plain text email. - - [1]: http://docutils.sourceforge.net/mirror/setext.html - [2]: http://www.aaronsw.com/2002/atx/ - [3]: http://textism.com/tools/textile/ - [4]: http://docutils.sourceforge.net/rst.html - [5]: http://www.triptico.com/software/grutatxt.html - [6]: http://ettext.taint.org/doc/ - -To this end, Markdown's syntax is comprised entirely of punctuation -characters, which punctuation characters have been carefully chosen so -as to look like what they mean. E.g., asterisks around a word actually -look like \*emphasis\*. Markdown lists look like, well, lists. Even -blockquotes look like quoted passages of text, assuming you've ever -used email. - - - -<h3 id="html">Inline HTML</h3> - -Markdown's syntax is intended for one purpose: to be used as a -format for *writing* for the web. - -Markdown is not a replacement for HTML, or even close to it. Its -syntax is very small, corresponding only to a very small subset of -HTML tags. The idea is *not* to create a syntax that makes it easier -to insert HTML tags. In my opinion, HTML tags are already easy to -insert. The idea for Markdown is to make it easy to read, write, and -edit prose. HTML is a *publishing* format; Markdown is a *writing* -format. Thus, Markdown's formatting syntax only addresses issues that -can be conveyed in plain text. - -For any markup that is not covered by Markdown's syntax, you simply -use HTML itself. There's no need to preface it or delimit it to -indicate that you're switching from Markdown to HTML; you just use -the tags. - -The only restrictions are that block-level HTML elements -- e.g. `<div>`, -`<table>`, `<pre>`, `<p>`, etc. -- must be separated from surrounding -content by blank lines, and the start and end tags of the block should -not be indented with tabs or spaces. Markdown is smart enough not -to add extra (unwanted) `<p>` tags around HTML block-level tags. - -For example, to add an HTML table to a Markdown article: - - This is a regular paragraph. - - <table> - <tr> - <td>Foo</td> - </tr> - </table> - - This is another regular paragraph. - -Note that Markdown formatting syntax is not processed within block-level -HTML tags. E.g., you can't use Markdown-style `*emphasis*` inside an -HTML block. - -Span-level HTML tags -- e.g. `<span>`, `<cite>`, or `<del>` -- can be -used anywhere in a Markdown paragraph, list item, or header. If you -want, you can even use HTML tags instead of Markdown formatting; e.g. if -you'd prefer to use HTML `<a>` or `<img>` tags instead of Markdown's -link or image syntax, go right ahead. - -Unlike block-level HTML tags, Markdown syntax *is* processed within -span-level tags. - - -<h3 id="autoescape">Automatic Escaping for Special Characters</h3> - -In HTML, there are two characters that demand special treatment: `<` -and `&`. Left angle brackets are used to start tags; ampersands are -used to denote HTML entities. If you want to use them as literal -characters, you must escape them as entities, e.g. `<`, and -`&`. - -Ampersands in particular are bedeviling for web writers. If you want to -write about 'AT&T', you need to write '`AT&T`'. You even need to -escape ampersands within URLs. Thus, if you want to link to: - - http://images.google.com/images?num=30&q=larry+bird - -you need to encode the URL as: - - http://images.google.com/images?num=30&q=larry+bird - -in your anchor tag `href` attribute. Needless to say, this is easy to -forget, and is probably the single most common source of HTML validation -errors in otherwise well-marked-up web sites. - -Markdown allows you to use these characters naturally, taking care of -all the necessary escaping for you. If you use an ampersand as part of -an HTML entity, it remains unchanged; otherwise it will be translated -into `&`. - -So, if you want to include a copyright symbol in your article, you can write: - - © - -and Markdown will leave it alone. But if you write: - - AT&T - -Markdown will translate it to: - - AT&T - -Similarly, because Markdown supports [inline HTML](#html), if you use -angle brackets as delimiters for HTML tags, Markdown will treat them as -such. But if you write: - - 4 < 5 - -Markdown will translate it to: - - 4 < 5 - -However, inside Markdown code spans and blocks, angle brackets and -ampersands are *always* encoded automatically. This makes it easy to use -Markdown to write about HTML code. (As opposed to raw HTML, which is a -terrible format for writing about HTML syntax, because every single `<` -and `&` in your example code needs to be escaped.) - - -* * * - - -<h2 id="block">Block Elements</h2> - - -<h3 id="p">Paragraphs and Line Breaks</h3> - -A paragraph is simply one or more consecutive lines of text, separated -by one or more blank lines. (A blank line is any line that looks like a -blank line -- a line containing nothing but spaces or tabs is considered -blank.) Normal paragraphs should not be intended with spaces or tabs. - -The implication of the "one or more consecutive lines of text" rule is -that Markdown supports "hard-wrapped" text paragraphs. This differs -significantly from most other text-to-HTML formatters (including Movable -Type's "Convert Line Breaks" option) which translate every line break -character in a paragraph into a `<br />` tag. - -When you *do* want to insert a `<br />` break tag using Markdown, you -end a line with two or more spaces, then type return. - -Yes, this takes a tad more effort to create a `<br />`, but a simplistic -"every line break is a `<br />`" rule wouldn't work for Markdown. -Markdown's email-style [blockquoting][bq] and multi-paragraph [list items][l] -work best -- and look better -- when you format them with hard breaks. - - [bq]: #blockquote - [l]: #list - - - -<h3 id="header">Headers</h3> - -Markdown supports two styles of headers, [Setext] [1] and [atx] [2]. - -Setext-style headers are "underlined" using equal signs (for first-level -headers) and dashes (for second-level headers). For example: - - This is an H1 - ============= - - This is an H2 - ------------- - -Any number of underlining `=`'s or `-`'s will work. - -Atx-style headers use 1-6 hash characters at the start of the line, -corresponding to header levels 1-6. For example: - - # This is an H1 - - ## This is an H2 - - ###### This is an H6 - -Optionally, you may "close" atx-style headers. This is purely -cosmetic -- you can use this if you think it looks better. The -closing hashes don't even need to match the number of hashes -used to open the header. (The number of opening hashes -determines the header level.) : - - # This is an H1 # - - ## This is an H2 ## - - ### This is an H3 ###### - - -<h3 id="blockquote">Blockquotes</h3> - -Markdown uses email-style `>` characters for blockquoting. If you're -familiar with quoting passages of text in an email message, then you -know how to create a blockquote in Markdown. It looks best if you hard -wrap the text and put a `>` before every line: - - > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, - > consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. - > Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. - > - > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse - > id sem consectetuer libero luctus adipiscing. - -Markdown allows you to be lazy and only put the `>` before the first -line of a hard-wrapped paragraph: - - > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, - consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. - Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. - - > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse - id sem consectetuer libero luctus adipiscing. - -Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by -adding additional levels of `>`: - - > This is the first level of quoting. - > - > > This is nested blockquote. - > - > Back to the first level. - -Blockquotes can contain other Markdown elements, including headers, lists, -and code blocks: - - > ## This is a header. - > - > 1. This is the first list item. - > 2. This is the second list item. - > - > Here's some example code: - > - > return shell_exec("echo $input | $markdown_script"); - -Any decent text editor should make email-style quoting easy. For -example, with BBEdit, you can make a selection and choose Increase -Quote Level from the Text menu. - - -<h3 id="list">Lists</h3> - -Markdown supports ordered (numbered) and unordered (bulleted) lists. - -Unordered lists use asterisks, pluses, and hyphens -- interchangably --- as list markers: - - * Red - * Green - * Blue - -is equivalent to: - - + Red - + Green - + Blue - -and: - - - Red - - Green - - Blue - -Ordered lists use numbers followed by periods: - - 1. Bird - 2. McHale - 3. Parish - -It's important to note that the actual numbers you use to mark the -list have no effect on the HTML output Markdown produces. The HTML -Markdown produces from the above list is: - - <ol> - <li>Bird</li> - <li>McHale</li> - <li>Parish</li> - </ol> - -If you instead wrote the list in Markdown like this: - - 1. Bird - 1. McHale - 1. Parish - -or even: - - 3. Bird - 1. McHale - 8. Parish - -you'd get the exact same HTML output. The point is, if you want to, -you can use ordinal numbers in your ordered Markdown lists, so that -the numbers in your source match the numbers in your published HTML. -But if you want to be lazy, you don't have to. - -If you do use lazy list numbering, however, you should still start the -list with the number 1. At some point in the future, Markdown may support -starting ordered lists at an arbitrary number. - -List markers typically start at the left margin, but may be indented by -up to three spaces. List markers must be followed by one or more spaces -or a tab. - -To make lists look nice, you can wrap items with hanging indents: - - * Lorem ipsum dolor sit amet, consectetuer adipiscing elit. - Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, - viverra nec, fringilla in, laoreet vitae, risus. - * Donec sit amet nisl. Aliquam semper ipsum sit amet velit. - Suspendisse id sem consectetuer libero luctus adipiscing. - -But if you want to be lazy, you don't have to: - - * Lorem ipsum dolor sit amet, consectetuer adipiscing elit. - Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, - viverra nec, fringilla in, laoreet vitae, risus. - * Donec sit amet nisl. Aliquam semper ipsum sit amet velit. - Suspendisse id sem consectetuer libero luctus adipiscing. - -If list items are separated by blank lines, Markdown will wrap the -items in `<p>` tags in the HTML output. For example, this input: - - * Bird - * Magic - -will turn into: - - <ul> - <li>Bird</li> - <li>Magic</li> - </ul> - -But this: - - * Bird - - * Magic - -will turn into: - - <ul> - <li><p>Bird</p></li> - <li><p>Magic</p></li> - </ul> - -List items may consist of multiple paragraphs. Each subsequent -paragraph in a list item must be intended by either 4 spaces -or one tab: - - 1. This is a list item with two paragraphs. Lorem ipsum dolor - sit amet, consectetuer adipiscing elit. Aliquam hendrerit - mi posuere lectus. - - Vestibulum enim wisi, viverra nec, fringilla in, laoreet - vitae, risus. Donec sit amet nisl. Aliquam semper ipsum - sit amet velit. - - 2. Suspendisse id sem consectetuer libero luctus adipiscing. - -It looks nice if you indent every line of the subsequent -paragraphs, but here again, Markdown will allow you to be -lazy: - - * This is a list item with two paragraphs. - - This is the second paragraph in the list item. You're - only required to indent the first line. Lorem ipsum dolor - sit amet, consectetuer adipiscing elit. - - * Another item in the same list. - -To put a blockquote within a list item, the blockquote's `>` -delimiters need to be indented: - - * A list item with a blockquote: - - > This is a blockquote - > inside a list item. - -To put a code block within a list item, the code block needs -to be indented *twice* -- 8 spaces or two tabs: - - * A list item with a code block: - - <code goes here> - - -It's worth noting that it's possible to trigger an ordered list by -accident, by writing something like this: - - 1986. What a great season. - -In other words, a *number-period-space* sequence at the beginning of a -line. To avoid this, you can backslash-escape the period: - - 1986\. What a great season. - - - -<h3 id="precode">Code Blocks</h3> - -Pre-formatted code blocks are used for writing about programming or -markup source code. Rather than forming normal paragraphs, the lines -of a code block are interpreted literally. Markdown wraps a code block -in both `<pre>` and `<code>` tags. - -To produce a code block in Markdown, simply indent every line of the -block by at least 4 spaces or 1 tab. For example, given this input: - - This is a normal paragraph: - - This is a code block. - -Markdown will generate: - - <p>This is a normal paragraph:</p> - - <pre><code>This is a code block. - </code></pre> - -One level of indentation -- 4 spaces or 1 tab -- is removed from each -line of the code block. For example, this: - - Here is an example of AppleScript: - - tell application "Foo" - beep - end tell - -will turn into: - - <p>Here is an example of AppleScript:</p> - - <pre><code>tell application "Foo" - beep - end tell - </code></pre> - -A code block continues until it reaches a line that is not indented -(or the end of the article). - -Within a code block, ampersands (`&`) and angle brackets (`<` and `>`) -are automatically converted into HTML entities. This makes it very -easy to include example HTML source code using Markdown -- just paste -it and indent it, and Markdown will handle the hassle of encoding the -ampersands and angle brackets. For example, this: - - <div class="footer"> - © 2004 Foo Corporation - </div> - -will turn into: - - <pre><code><div class="footer"> - &copy; 2004 Foo Corporation - </div> - </code></pre> - -Regular Markdown syntax is not processed within code blocks. E.g., -asterisks are just literal asterisks within a code block. This means -it's also easy to use Markdown to write about Markdown's own syntax. - - - -<h3 id="hr">Horizontal Rules</h3> - -You can produce a horizontal rule tag (`<hr />`) by placing three or -more hyphens, asterisks, or underscores on a line by themselves. If you -wish, you may use spaces between the hyphens or asterisks. Each of the -following lines will produce a horizontal rule: - - * * * - - *** - - ***** - - - - - - - --------------------------------------- - - _ _ _ - - -* * * - -<h2 id="span">Span Elements</h2> - -<h3 id="link">Links</h3> - -Markdown supports two style of links: *inline* and *reference*. - -In both styles, the link text is delimited by [square brackets]. - -To create an inline link, use a set of regular parentheses immediately -after the link text's closing square bracket. Inside the parentheses, -put the URL where you want the link to point, along with an *optional* -title for the link, surrounded in quotes. For example: - - This is [an example](http://example.com/ "Title") inline link. - - [This link](http://example.net/) has no title attribute. - -Will produce: - - <p>This is <a href="http://example.com/" title="Title"> - an example</a> inline link.</p> - - <p><a href="http://example.net/">This link</a> has no - title attribute.</p> - -If you're referring to a local resource on the same server, you can -use relative paths: - - See my [About](/about/) page for details. - -Reference-style links use a second set of square brackets, inside -which you place a label of your choosing to identify the link: - - This is [an example][id] reference-style link. - -You can optionally use a space to separate the sets of brackets: - - This is [an example] [id] reference-style link. - -Then, anywhere in the document, you define your link label like this, -on a line by itself: - - [id]: http://example.com/ "Optional Title Here" - -That is: - -* Square brackets containing the link identifier (optionally - indented from the left margin using up to three spaces); -* followed by a colon; -* followed by one or more spaces (or tabs); -* followed by the URL for the link; -* optionally followed by a title attribute for the link, enclosed - in double or single quotes. - -The link URL may, optionally, be surrounded by angle brackets: - - [id]: <http://example.com/> "Optional Title Here" - -You can put the title attribute on the next line and use extra spaces -or tabs for padding, which tends to look better with longer URLs: - - [id]: http://example.com/longish/path/to/resource/here - "Optional Title Here" - -Link definitions are only used for creating links during Markdown -processing, and are stripped from your document in the HTML output. - -Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are *not* case sensitive. E.g. these two links: - - [link text][a] - [link text][A] - -are equivalent. - -The *implicit link name* shortcut allows you to omit the name of the -link, in which case the link text itself is used as the name. -Just use an empty set of square brackets -- e.g., to link the word -"Google" to the google.com web site, you could simply write: - - [Google][] - -And then define the link: - - [Google]: http://google.com/ - -Because link names may contain spaces, this shortcut even works for -multiple words in the link text: - - Visit [Daring Fireball][] for more information. - -And then define the link: - - [Daring Fireball]: http://daringfireball.net/ - -Link definitions can be placed anywhere in your Markdown document. I -tend to put them immediately after each paragraph in which they're -used, but if you want, you can put them all at the end of your -document, sort of like footnotes. - -Here's an example of reference links in action: - - I get 10 times more traffic from [Google] [1] than from - [Yahoo] [2] or [MSN] [3]. - - [1]: http://google.com/ "Google" - [2]: http://search.yahoo.com/ "Yahoo Search" - [3]: http://search.msn.com/ "MSN Search" - -Using the implicit link name shortcut, you could instead write: - - I get 10 times more traffic from [Google][] than from - [Yahoo][] or [MSN][]. - - [google]: http://google.com/ "Google" - [yahoo]: http://search.yahoo.com/ "Yahoo Search" - [msn]: http://search.msn.com/ "MSN Search" - -Both of the above examples will produce the following HTML output: - - <p>I get 10 times more traffic from <a href="http://google.com/" - title="Google">Google</a> than from - <a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a> - or <a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p> - -For comparison, here is the same paragraph written using -Markdown's inline link style: - - I get 10 times more traffic from [Google](http://google.com/ "Google") - than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or - [MSN](http://search.msn.com/ "MSN Search"). - -The point of reference-style links is not that they're easier to -write. The point is that with reference-style links, your document -source is vastly more readable. Compare the above examples: using -reference-style links, the paragraph itself is only 81 characters -long; with inline-style links, it's 176 characters; and as raw HTML, -it's 234 characters. In the raw HTML, there's more markup than there -is text. - -With Markdown's reference-style links, a source document much more -closely resembles the final output, as rendered in a browser. By -allowing you to move the markup-related metadata out of the paragraph, -you can add links without interrupting the narrative flow of your -prose. - - -<h3 id="em">Emphasis</h3> - -Markdown treats asterisks (`*`) and underscores (`_`) as indicators of -emphasis. Text wrapped with one `*` or `_` will be wrapped with an -HTML `<em>` tag; double `*`'s or `_`'s will be wrapped with an HTML -`<strong>` tag. E.g., this input: - - *single asterisks* - - _single underscores_ - - **double asterisks** - - __double underscores__ - -will produce: - - <em>single asterisks</em> - - <em>single underscores</em> - - <strong>double asterisks</strong> - - <strong>double underscores</strong> - -You can use whichever style you prefer; the lone restriction is that -the same character must be used to open and close an emphasis span. - -Emphasis can be used in the middle of a word: - - un*fucking*believable - -But if you surround an `*` or `_` with spaces, it'll be treated as a -literal asterisk or underscore. - -To produce a literal asterisk or underscore at a position where it -would otherwise be used as an emphasis delimiter, you can backslash -escape it: - - \*this text is surrounded by literal asterisks\* - - - -<h3 id="code">Code</h3> - -To indicate a span of code, wrap it with backtick quotes (`` ` ``). -Unlike a pre-formatted code block, a code span indicates code within a -normal paragraph. For example: - - Use the `printf()` function. - -will produce: - - <p>Use the <code>printf()</code> function.</p> - -To include a literal backtick character within a code span, you can use -multiple backticks as the opening and closing delimiters: - - ``There is a literal backtick (`) here.`` - -which will produce this: - - <p><code>There is a literal backtick (`) here.</code></p> - -The backtick delimiters surrounding a code span may include spaces -- -one after the opening, one before the closing. This allows you to place -literal backtick characters at the beginning or end of a code span: - - A single backtick in a code span: `` ` `` - - A backtick-delimited string in a code span: `` `foo` `` - -will produce: - - <p>A single backtick in a code span: <code>`</code></p> - - <p>A backtick-delimited string in a code span: <code>`foo`</code></p> - -With a code span, ampersands and angle brackets are encoded as HTML -entities automatically, which makes it easy to include example HTML -tags. Markdown will turn this: - - Please don't use any `<blink>` tags. - -into: - - <p>Please don't use any <code><blink></code> tags.</p> - -You can write this: - - `—` is the decimal-encoded equivalent of `—`. - -to produce: - - <p><code>&#8212;</code> is the decimal-encoded - equivalent of <code>&mdash;</code>.</p> - - - -<h3 id="img">Images</h3> - -Admittedly, it's fairly difficult to devise a "natural" syntax for -placing images into a plain text document format. - -Markdown uses an image syntax that is intended to resemble the syntax -for links, allowing for two styles: *inline* and *reference*. - -Inline image syntax looks like this: - - ![Alt text](/path/to/img.jpg) - - ![Alt text](/path/to/img.jpg "Optional title") - -That is: - -* An exclamation mark: `!`; -* followed by a set of square brackets, containing the `alt` - attribute text for the image; -* followed by a set of parentheses, containing the URL or path to - the image, and an optional `title` attribute enclosed in double - or single quotes. - -Reference-style image syntax looks like this: - - ![Alt text][id] - -Where "id" is the name of a defined image reference. Image references -are defined using syntax identical to link references: - - [id]: url/to/image "Optional title attribute" - -As of this writing, Markdown has no syntax for specifying the -dimensions of an image; if this is important to you, you can simply -use regular HTML `<img>` tags. - - -* * * - - -<h2 id="misc">Miscellaneous</h2> - -<h3 id="autolink">Automatic Links</h3> - -Markdown supports a shortcut style for creating "automatic" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this: - - <http://example.com/> - -Markdown will turn this into: - - <a href="http://example.com/">http://example.com/</a> - -Automatic links for email addresses work similarly, except that -Markdown will also perform a bit of randomized decimal and hex -entity-encoding to help obscure your address from address-harvesting -spambots. For example, Markdown will turn this: - - <address@example.com> - -into something like this: - - <a href="mailto:addre - ss@example.co - m">address@exa - mple.com</a> - -which will render in a browser as a clickable link to "address@example.com". - -(This sort of entity-encoding trick will indeed fool many, if not -most, address-harvesting bots, but it definitely won't fool all of -them. It's better than nothing, but an address published in this way -will probably eventually start receiving spam.) - - - -<h3 id="backslash">Backslash Escapes</h3> - -Markdown allows you to use backslash escapes to generate literal -characters which would otherwise have special meaning in Markdown's -formatting syntax. For example, if you wanted to surround a word with -literal asterisks (instead of an HTML `<em>` tag), you can backslashes -before the asterisks, like this: - - \*literal asterisks\* - -Markdown provides backslash escapes for the following characters: - - \ backslash - ` backtick - * asterisk - _ underscore - {} curly braces - [] square brackets - () parentheses - # hash mark - + plus sign - - minus sign (hyphen) - . dot - ! exclamation mark - diff --git a/oldtests/Original/Nested_blockquotes.html b/oldtests/Original/Nested_blockquotes.html deleted file mode 100644 index 02efc59..0000000 --- a/oldtests/Original/Nested_blockquotes.html +++ /dev/null @@ -1,7 +0,0 @@ -<blockquote> -<p>foo</p> -<blockquote> -<p>bar</p> -</blockquote> -<p>foo</p> -</blockquote> diff --git a/oldtests/Original/Nested_blockquotes.markdown b/oldtests/Original/Nested_blockquotes.markdown deleted file mode 100644 index ed3c624..0000000 --- a/oldtests/Original/Nested_blockquotes.markdown +++ /dev/null @@ -1,5 +0,0 @@ -> foo -> -> > bar -> -> foo diff --git a/oldtests/Original/Ordered_and_unordered_lists.html b/oldtests/Original/Ordered_and_unordered_lists.html deleted file mode 100644 index 78d752e..0000000 --- a/oldtests/Original/Ordered_and_unordered_lists.html +++ /dev/null @@ -1,112 +0,0 @@ -<h2>Unordered</h2> -<p>Asterisks tight:</p> -<ul> -<li>asterisk 1</li> -<li>asterisk 2</li> -<li>asterisk 3</li> -</ul> -<p>Asterisks loose:</p> -<ul> -<li><p>asterisk 1</p></li> -<li><p>asterisk 2</p></li> -<li><p>asterisk 3</p></li> -</ul> -<hr /> -<p>Pluses tight:</p> -<ul> -<li>Plus 1</li> -<li>Plus 2</li> -<li>Plus 3</li> -</ul> -<p>Pluses loose:</p> -<ul> -<li><p>Plus 1</p></li> -<li><p>Plus 2</p></li> -<li><p>Plus 3</p></li> -</ul> -<hr /> -<p>Minuses tight:</p> -<ul> -<li>Minus 1</li> -<li>Minus 2</li> -<li>Minus 3</li> -</ul> -<p>Minuses loose:</p> -<ul> -<li><p>Minus 1</p></li> -<li><p>Minus 2</p></li> -<li><p>Minus 3</p></li> -</ul> -<h2>Ordered</h2> -<p>Tight:</p> -<ol> -<li>First</li> -<li>Second</li> -<li>Third</li> -</ol> -<p>and:</p> -<ol> -<li>One</li> -<li>Two</li> -<li>Three</li> -</ol> -<p>Loose using tabs:</p> -<ol> -<li><p>First</p></li> -<li><p>Second</p></li> -<li><p>Third</p></li> -</ol> -<p>and using spaces:</p> -<ol> -<li><p>One</p></li> -<li><p>Two</p></li> -<li><p>Three</p></li> -</ol> -<p>Multiple paragraphs:</p> -<ol> -<li><p>Item 1, graf one.</p> -<p>Item 2. graf two. The quick brown fox jumped over the lazy dog's -back.</p></li> -<li><p>Item 2.</p></li> -<li><p>Item 3.</p></li> -</ol> -<h2>Nested</h2> -<ul> -<li>Tab -<ul> -<li>Tab -<ul> -<li>Tab</li> -</ul></li> -</ul></li> -</ul> -<p>Here's another:</p> -<ol> -<li>First</li> -<li>Second: -<ul> -<li>Fee</li> -<li>Fie</li> -<li>Foe</li> -</ul></li> -<li>Third</li> -</ol> -<p>Same thing but with paragraphs:</p> -<ol> -<li><p>First</p></li> -<li><p>Second:</p> -<ul> -<li>Fee</li> -<li>Fie</li> -<li>Foe</li> -</ul></li> -<li><p>Third</p></li> -</ol> -<p>This was an error in Markdown 1.0.1:</p> -<ul> -<li><p>this</p> -<ul> -<li>sub</li> -</ul> -<p>that</p></li> -</ul> diff --git a/oldtests/Original/Ordered_and_unordered_lists.markdown b/oldtests/Original/Ordered_and_unordered_lists.markdown deleted file mode 100644 index 7f3b497..0000000 --- a/oldtests/Original/Ordered_and_unordered_lists.markdown +++ /dev/null @@ -1,131 +0,0 @@ -## Unordered - -Asterisks tight: - -* asterisk 1 -* asterisk 2 -* asterisk 3 - - -Asterisks loose: - -* asterisk 1 - -* asterisk 2 - -* asterisk 3 - -* * * - -Pluses tight: - -+ Plus 1 -+ Plus 2 -+ Plus 3 - - -Pluses loose: - -+ Plus 1 - -+ Plus 2 - -+ Plus 3 - -* * * - - -Minuses tight: - -- Minus 1 -- Minus 2 -- Minus 3 - - -Minuses loose: - -- Minus 1 - -- Minus 2 - -- Minus 3 - - -## Ordered - -Tight: - -1. First -2. Second -3. Third - -and: - -1. One -2. Two -3. Three - - -Loose using tabs: - -1. First - -2. Second - -3. Third - -and using spaces: - -1. One - -2. Two - -3. Three - -Multiple paragraphs: - -1. Item 1, graf one. - - Item 2. graf two. The quick brown fox jumped over the lazy dog's - back. - -2. Item 2. - -3. Item 3. - - - -## Nested - -* Tab - * Tab - * Tab - -Here's another: - -1. First -2. Second: - * Fee - * Fie - * Foe -3. Third - -Same thing but with paragraphs: - -1. First - -2. Second: - * Fee - * Fie - * Foe - -3. Third - - -This was an error in Markdown 1.0.1: - -* this - - * sub - - that diff --git a/oldtests/Original/README b/oldtests/Original/README deleted file mode 100644 index 5143258..0000000 --- a/oldtests/Original/README +++ /dev/null @@ -1,15 +0,0 @@ -These are from John Gruber's original markdown test suite, via -Michel Fortin's mdtest. - -The html files have been modified slightly in ways that do not affect the -semantics. For example, entities are used for quotes in text, and -blank lines are omitted between block-level tags. - -Trailing blank spaces are removed from lines in raw HTML blocks. - -The one (insignificant) semantic change is switching the order -of emph and strong tags in the output for ***strong and emph***. - -We have removed Hard-wrapped_paragraphs_with_list-like_lines tests, -because the new implementation no longer requires a blank line -before a list. diff --git a/oldtests/Original/Strong_and_em_together.html b/oldtests/Original/Strong_and_em_together.html deleted file mode 100644 index 2629594..0000000 --- a/oldtests/Original/Strong_and_em_together.html +++ /dev/null @@ -1,4 +0,0 @@ -<p><strong><em>This is strong and em.</em></strong></p> -<p>So is <strong><em>this</em></strong> word.</p> -<p><strong><em>This is strong and em.</em></strong></p> -<p>So is <strong><em>this</em></strong> word.</p> diff --git a/oldtests/Original/Strong_and_em_together.markdown b/oldtests/Original/Strong_and_em_together.markdown deleted file mode 100644 index 95ee690..0000000 --- a/oldtests/Original/Strong_and_em_together.markdown +++ /dev/null @@ -1,7 +0,0 @@ -***This is strong and em.*** - -So is ***this*** word. - -___This is strong and em.___ - -So is ___this___ word. diff --git a/oldtests/Original/Tabs.html b/oldtests/Original/Tabs.html deleted file mode 100644 index 5389bdf..0000000 --- a/oldtests/Original/Tabs.html +++ /dev/null @@ -1,19 +0,0 @@ -<ul> -<li><p>this is a list item -indented with tabs</p></li> -<li><p>this is a list item -indented with spaces</p></li> -</ul> -<p>Code:</p> -<pre><code>this code block is indented by one tab -</code></pre> -<p>And:</p> -<pre><code> this code block is indented by two tabs -</code></pre> -<p>And:</p> -<pre><code>+ this is an example list item - indented with tabs - -+ this is an example list item - indented with spaces -</code></pre> diff --git a/oldtests/Original/Tabs.markdown b/oldtests/Original/Tabs.markdown deleted file mode 100644 index 589d113..0000000 --- a/oldtests/Original/Tabs.markdown +++ /dev/null @@ -1,21 +0,0 @@ -+ this is a list item - indented with tabs - -+ this is a list item - indented with spaces - -Code: - - this code block is indented by one tab - -And: - - this code block is indented by two tabs - -And: - - + this is an example list item - indented with tabs - - + this is an example list item - indented with spaces diff --git a/oldtests/Original/Tidyness.html b/oldtests/Original/Tidyness.html deleted file mode 100644 index f2a8ce7..0000000 --- a/oldtests/Original/Tidyness.html +++ /dev/null @@ -1,8 +0,0 @@ -<blockquote> -<p>A list within a blockquote:</p> -<ul> -<li>asterisk 1</li> -<li>asterisk 2</li> -<li>asterisk 3</li> -</ul> -</blockquote> diff --git a/oldtests/Original/Tidyness.markdown b/oldtests/Original/Tidyness.markdown deleted file mode 100644 index 5f18b8d..0000000 --- a/oldtests/Original/Tidyness.markdown +++ /dev/null @@ -1,5 +0,0 @@ -> A list within a blockquote: -> -> * asterisk 1 -> * asterisk 2 -> * asterisk 3 diff --git a/oldtests/Tabs/TabConversionUnicode.html b/oldtests/Tabs/TabConversionUnicode.html deleted file mode 100644 index f596f6a..0000000 --- a/oldtests/Tabs/TabConversionUnicode.html +++ /dev/null @@ -1 +0,0 @@ -<p><code>То лпой</code> is a Russian word with a tab inside.</p> diff --git a/oldtests/Tabs/TabConversionUnicode.markdown b/oldtests/Tabs/TabConversionUnicode.markdown deleted file mode 100644 index 0bd7b52..0000000 --- a/oldtests/Tabs/TabConversionUnicode.markdown +++ /dev/null @@ -1 +0,0 @@ -`То лпой` is a Russian word with a tab inside. diff --git a/runtests.pl b/runtests.pl index f3e91ca..0bff360 100644 --- a/runtests.pl +++ b/runtests.pl @@ -51,6 +51,7 @@ sub tidy s/ */ /; # collapse space before /> in tag s/ *\/>/\/>/; + s/>\n$/>/; # skip blank line if (/^$/) { next; @@ -93,8 +94,10 @@ sub dotest print $markdown; print "=== expected ===============\n"; print $html; + print "\n"; print "=== got ====================\n"; print $actual; + print "\n"; print color "black"; return 0; } @@ -2,8 +2,8 @@ title: CommonMark Spec author: - John MacFarlane -version: 1 -date: 2014-09-06 +version: 2 +date: 2014-09-19 ... # Introduction @@ -1058,7 +1058,7 @@ a blank line either before or after. The content of a code fence is treated as literal text, not parsed as inlines. The first word of the info string is typically used to specify the language of the code sample, and rendered in the `class` -attribute of the `pre` tag. However, this spec does not mandate any +attribute of the `code` tag. However, this spec does not mandate any particular treatment of the info string. Here is a simple example with backticks: @@ -1682,7 +1682,7 @@ them. [Foo bar] . -<p><a href="my url" title="title">Foo bar</a></p> +<p><a href="my%20url" title="title">Foo bar</a></p> . The title may be omitted: @@ -1745,7 +1745,7 @@ case-insensitive (see [matches](#matches)). [αγω] . -<p><a href="/φου">αγω</a></p> +<p><a href="/%CF%86%CE%BF%CF%85">αγω</a></p> . Here is a link reference definition with no corresponding link. @@ -1994,11 +1994,11 @@ form of the definition is: > transforming X in such-and-such a way is a container of type Y > with these blocks as its content. -So, we explain what counts as a block quote or list item by -explaining how these can be *generated* from their contents. -This should suffice to define the syntax, although it does not -give a recipe for *parsing* these constructions. (A recipe is -provided below in the section entitled [A parsing strategy].) +So, we explain what counts as a block quote or list item by explaining +how these can be *generated* from their contents. This should suffice +to define the syntax, although it does not give a recipe for *parsing* +these constructions. (A recipe is provided below in the section entitled +[A parsing strategy](#appendix-a-a-parsing-strategy).) ## Block quotes @@ -2010,9 +2010,9 @@ The following rules define [block quotes](#block-quote): <a id="block-quote"></a> 1. **Basic case.** If a string of lines *Ls* constitute a sequence - of blocks *Bs*, then the result of appending a [block quote marker] - to the beginning of each line in *Ls* is a [block quote](#block-quote) - containing *Bs*. + of blocks *Bs*, then the result of prepending a [block quote + marker](#block-quote-marker) to the beginning of each line in *Ls* + is a [block quote](#block-quote) containing *Bs*. 2. **Laziness.** If a string of lines *Ls* constitute a [block quote](#block-quote) with contents *Bs*, then the result of deleting @@ -3686,9 +3686,9 @@ raw HTML: . . -<http://google.com?find=\*> +<http://example.com?find=\*> . -<p><a href="http://google.com?find=\*">http://google.com?find=\*</a></p> +<p><a href="http://example.com?find=%5C*">http://example.com?find=\*</a></p> . . @@ -3727,47 +3727,65 @@ foo ## Entities -Entities are parsed as entities, not as literal text, in all contexts -except code spans and code blocks. Three kinds of entities are recognized. +With the goal of making this standard as HTML-agnostic as possible, all +valid HTML entities in any context are recognized as such and +converted into unicode characters before they are stored in the AST. + +This allows implementations that target HTML output to trivially escape +the entities when generating HTML, and simplifies the job of +implementations targetting other languages, as these will only need to +handle the unicode chars and need not be HTML-entity aware. [Named entities](#name-entities) <a id="named-entities"></a> consist of `&` -+ a string of 2-32 alphanumerics beginning with a letter + `;`. ++ any of the valid HTML5 entity names + `;`. The +[following document](http://www.whatwg.org/specs/web-apps/current-work/multipage/entities.json) +is used as an authoritative source of the valid entity names and their +corresponding codepoints. + +Conforming implementations that target HTML don't need to generate +entities for all the valid named entities that exist, with the exception +of `"` (`"`), `&` (`&`), `<` (`<`) and `>` (`>`), which +always need to be written as entities for security reasons. . & © Æ Ď ¾ ℋ ⅆ ∲ . -<p> & © Æ Ď ¾ ℋ ⅆ ∲</p> +<p> & © Æ Ď ¾ ℋ ⅆ ∲</p> . [Decimal entities](#decimal-entities) <a id="decimal-entities"></a> -consist of `&#` + a string of 1--8 arabic digits + `;`. +consist of `&#` + a string of 1--8 arabic digits + `;`. Again, these +entities need to be recognised and tranformed into their corresponding +UTF8 codepoints. Invalid Unicode codepoints will be written as the +"unknown codepoint" character (`0xFFFD`) . - # Ӓ Ϡ � +# Ӓ Ϡ � . -<p> # Ӓ Ϡ �</p> +<p># Ӓ Ϡ �</p> . [Hexadecimal entities](#hexadecimal-entities) <a id="hexadecimal-entities"></a> consist of `&#` + either `X` or `x` + a string of 1-8 hexadecimal digits -+ `;`. ++ `;`. They will also be parsed and turned into their corresponding UTF8 values in the AST. . - " ആ ಫ +" ആ ಫ . -<p> " ആ ಫ</p> +<p>" ആ ಫ</p> . Here are some nonentities: . -  &x; &#; &#x; � &ThisIsWayTooLongToBeAnEntityIsntIt; &hi?; +  &x; &#; &#x; &ThisIsWayTooLongToBeAnEntityIsntIt; &hi?; . -<p>&nbsp &x; &#; &#x; &#123456789; &ThisIsWayTooLongToBeAnEntityIsntIt; &hi?;</p> +<p>&nbsp &x; &#; &#x; &ThisIsWayTooLongToBeAnEntityIsntIt; &hi?;</p> . Although HTML5 does accept some entities without a trailing semicolon -(such as `©`), these are not recognized as entities here: +(such as `©`), these are not recognized as entities here, because it +makes the grammar too ambiguous: . © @@ -3775,13 +3793,13 @@ Although HTML5 does accept some entities without a trailing semicolon <p>&copy</p> . -On the other hand, many strings that are not on the list of HTML5 -named entities are recognized as entities here: +Strings that are not on the list of HTML5 named entities are not +recognized as entities either: . &MadeUpEntity; . -<p>&MadeUpEntity;</p> +<p>&MadeUpEntity;</p> . Entities are recognized in any context besides code spans or @@ -3797,7 +3815,7 @@ code blocks, including raw HTML, URLs, [link titles](#link-title), and . [foo](/föö "föö") . -<p><a href="/föö" title="föö">foo</a></p> +<p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p> . . @@ -3805,7 +3823,7 @@ code blocks, including raw HTML, URLs, [link titles](#link-title), and [foo]: /föö "föö" . -<p><a href="/föö" title="föö">foo</a></p> +<p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p> . . @@ -3813,7 +3831,7 @@ code blocks, including raw HTML, URLs, [link titles](#link-title), and foo ``` . -<pre><code class="language-föö">foo +<pre><code class="language-föö">foo </code></pre> . @@ -3946,7 +3964,7 @@ But this is a link: . <http://foo.bar.`baz>` . -<p><a href="http://foo.bar.`baz">http://foo.bar.`baz</a>`</p> +<p><a href="http://foo.bar.%60baz">http://foo.bar.`baz</a>`</p> . And this is an HTML tag: @@ -4024,15 +4042,15 @@ for efficient parsing strategies that do not backtrack: (a) it is not part of a sequence of four or more unescaped `*`s, (b) it is not followed by whitespace, and (c) either it is not followed by a `*` character or it is - followed immediately by strong emphasis. + followed immediately by emphasis or strong emphasis. 2. A single `_` character [can open emphasis](#can-open-emphasis) iff (a) it is not part of a sequence of four or more unescaped `_`s, (b) it is not followed by whitespace, - (c) is is not preceded by an ASCII alphanumeric character, and + (c) it is not preceded by an ASCII alphanumeric character, and (d) either it is not followed by a `_` character or it is - followed immediately by strong emphasis. + followed immediately by emphasis or strong emphasis. 3. A single `*` character [can close emphasis](#can-close-emphasis) <a id="can-close-emphasis"></a> iff @@ -4088,6 +4106,11 @@ for efficient parsing strategies that do not backtrack: emphasis](#can-close-strong-emphasis), and that uses the same character (`_` or `*`) as the opening delimiter, is reached. +11. In case of ambiguity, strong emphasis takes precedence. Thus, + `**foo**` is `<strong>foo</strong>`, not `<em><em>foo</em></em>`, + and `***foo***` is `<strong><em>foo</em></strong>`, not + `<em><strong>foo</strong></em>` or `<em><em><em>foo</em></em></em>`. + These rules can be illustrated through a series of examples. Simple emphasis: @@ -4334,6 +4357,32 @@ __this is a double underscore (`__`)__ <p><strong>this is a double underscore (<code>__</code>)</strong></p> . +Or use the other emphasis character: + +. +*_* +. +<p><em>_</em></p> +. + +. +_*_ +. +<p><em>*</em></p> +. + +. +*__* +. +<p><em>__</em></p> +. + +. +_**_ +. +<p><em>**</em></p> +. + `*` delimiters allow intra-word emphasis; `_` delimiters do not: . @@ -4509,6 +4558,36 @@ __foo _bar_ baz__ <p><strong>foo <em>bar</em> baz</strong></p> . +. +**foo, *bar*, baz** +. +<p><strong>foo, <em>bar</em>, baz</strong></p> +. + +. +__foo, _bar_, baz__ +. +<p><strong>foo, <em>bar</em>, baz</strong></p> +. + +But note: + +. +*foo**bar**baz* +. +<p><em>foo</em><em>bar</em><em>baz</em></p> +. + +. +**foo*bar*baz** +. +<p><em><em>foo</em>bar</em>baz**</p> +. + +The difference is that in the two preceding cases, +the internal delimiters [can close emphasis](#can-close-emphasis), +while in the cases with spaces, they cannot. + Note that you cannot nest emphasis directly inside emphasis using the same delimeter, or strong emphasis directly inside strong emphasis: @@ -4590,7 +4669,7 @@ However, a string of four or more `****` can never close emphasis: <p>*foo****</p> . -Note that there are some asymmetries here: +We retain symmetry in these cases: . *foo** @@ -4598,7 +4677,7 @@ Note that there are some asymmetries here: **foo* . <p><em>foo</em>*</p> -<p>**foo*</p> +<p>*<em>foo</em></p> . . @@ -4607,18 +4686,12 @@ Note that there are some asymmetries here: **foo* bar* . <p><em>foo <em>bar</em></em></p> -<p>**foo* bar*</p> +<p><em><em>foo</em> bar</em></p> . More cases with mismatched delimiters: . -**foo* bar* -. -<p>**foo* bar*</p> -. - -. *bar*** . <p><em>bar</em>**</p> @@ -4627,7 +4700,7 @@ More cases with mismatched delimiters: . ***foo* . -<p>***foo*</p> +<p>**<em>foo</em></p> . . @@ -4639,7 +4712,7 @@ More cases with mismatched delimiters: . ***foo** . -<p>***foo**</p> +<p>*<strong>foo</strong></p> . . @@ -4755,7 +4828,7 @@ braces: . [link](</my uri>) . -<p><a href="/my uri">link</a></p> +<p><a href="/my%20uri">link</a></p> . The destination cannot contain line breaks, even with pointy braces: @@ -4806,12 +4879,15 @@ in Markdown: <p><a href="foo):">link</a></p> . -URL-escaping and entities should be left alone inside the destination: +URL-escaping should be left alone inside the destination, as all +URL-escaped characters are also valid URL characters. HTML entities in +the destination will be parsed into their UTF-8 codepoints, as usual, and +optionally URL-escaped when written as HTML. . [link](foo%20bä) . -<p><a href="foo%20bä">link</a></p> +<p><a href="foo%20b%C3%A4">link</a></p> . Note that, because titles can often be parsed as destinations, @@ -4821,7 +4897,7 @@ get unexpected results: . [link]("title") . -<p><a href=""title"">link</a></p> +<p><a href="%22title%22">link</a></p> . Titles may be in single quotes, double quotes, or parentheses: @@ -5491,9 +5567,9 @@ spec](http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-m Examples of email autolinks: . -<foo@bar.baz.com> +<foo@bar.example.com> . -<p><a href="mailto:foo@bar.baz.com">foo@bar.baz.com</a></p> +<p><a href="mailto:foo@bar.example.com">foo@bar.example.com</a></p> . . @@ -5535,15 +5611,15 @@ These are not autolinks: . . -http://google.com +http://example.com . -<p>http://google.com</p> +<p>http://example.com</p> . . -foo@bar.baz.com +foo@bar.example.com . -<p>foo@bar.baz.com</p> +<p>foo@bar.example.com</p> . ## Raw HTML diff --git a/src/blocks.c b/src/blocks.c index 2776231..5b38116 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -1,747 +1,770 @@ #include <stdlib.h> +#include <assert.h> #include <stdio.h> #include <stdbool.h> #include <ctype.h> -#include "bstrlib.h" + #include "stmd.h" -#include "uthash.h" -#include "debug.h" +#include "utf8.h" #include "scanners.h" +#include "inlines.h" +#include "html/houdini.h" + +#define peek_at(i, n) (i)->data[n] + +static void incorporate_line(strbuf *ln, int line_number, node_block** curptr); +static void finalize(node_block* b, int line_number); -static block* make_block(int tag, int start_line, int start_column) +static node_block* make_block(int tag, int start_line, int start_column) { - block* e; - e = (block*) malloc(sizeof(block)); - e->tag = tag; - e->open = true; - e->last_line_blank = false; - e->start_line = start_line; - e->start_column = start_column; - e->end_line = start_line; - e->children = NULL; - e->last_child = NULL; - e->parent = NULL; - e->top = NULL; - e->attributes.refmap = NULL; - e->string_content = bfromcstr(""); - e->inline_content = NULL; - e->next = NULL; - e->prev = NULL; - return e; + node_block* e; + + e = malloc(sizeof(node_block)); + memset(e, 0x0, sizeof(*e)); + + e->tag = tag; + e->open = true; + e->start_line = start_line; + e->start_column = start_column; + e->end_line = start_line; + strbuf_init(&e->string_content, 32); + + return e; } -// Create a root document block. -extern block* make_document() +// Create a root document node_block. +extern node_block* make_document() { - block * e = make_block(document, 1, 1); - reference * map = NULL; - reference ** refmap; - refmap = (reference**) malloc(sizeof(reference*)); - *refmap = map; - e->attributes.refmap = refmap; - e->top = e; - return e; + node_block *e = make_block(BLOCK_DOCUMENT, 1, 1); + e->as.document.refmap = reference_map_new(); + e->top = e; + + return e; } // Returns true if line has only space characters, else false. -bool is_blank(bstring s, int offset) +bool is_blank(strbuf *s, int offset) { - char c; - while ((c = bchar(s, offset))) { - if (c == '\n') { - return true; - } else if (c == ' ') { - offset++; - } else { - return false; - } - } - return true; + while (offset < s->size) { + switch (s->ptr[offset]) { + case '\n': + return true; + case ' ': + offset++; + break; + default: + return false; + } + } + + return true; } static inline bool can_contain(int parent_type, int child_type) { - return ( parent_type == document || - parent_type == block_quote || - parent_type == list_item || - (parent_type == list && child_type == list_item) ); + return ( parent_type == BLOCK_DOCUMENT || + parent_type == BLOCK_BQUOTE || + parent_type == BLOCK_LIST_ITEM || + (parent_type == BLOCK_LIST && child_type == BLOCK_LIST_ITEM) ); } static inline bool accepts_lines(int block_type) { - return (block_type == paragraph || - block_type == atx_header || - block_type == indented_code || - block_type == fenced_code); + return (block_type == BLOCK_PARAGRAPH || + block_type == BLOCK_ATX_HEADER || + block_type == BLOCK_INDENTED_CODE || + block_type == BLOCK_FENCED_CODE); } -static int add_line(block* block, bstring ln, int offset) +static void add_line(node_block* node_block, chunk *ch, int offset) { - bstring s = bmidstr(ln, offset, blength(ln) - offset); - check(block->open, "attempted to add line (%s) to closed container (%d)", - ln->data, block->tag); - check(bformata(block->string_content, "%s", s->data) == 0, - "could not append line to string_content"); - bdestroy(s); - return 0; - error: - return -1; + assert(node_block->open); + strbuf_put(&node_block->string_content, ch->data + offset, ch->len - offset); } -static int remove_trailing_blank_lines(bstring ln) +static void remove_trailing_blank_lines(strbuf *ln) { - bstring tofind = bfromcstr(" \t\r\n"); - int pos; - // find last nonspace: - pos = bninchrr(ln, blength(ln) - 1, tofind); - if (pos == BSTR_ERR) { // all spaces - bassigncstr(ln, ""); - } else { - // find next newline after it - pos = bstrchrp(ln, '\n', pos); - if (pos != BSTR_ERR) { - check(bdelete(ln, pos, blength(ln) - pos) != BSTR_ERR, - "failed to delete trailing blank lines"); - } - } - bdestroy(tofind); - return 0; - error: - return -1; + int i; + + for (i = ln->size - 1; i >= 0; --i) { + char c = ln->ptr[i]; + + if (c != ' ' && c != '\t' && c != '\r' && c != '\n') + break; + } + + if (i < 0) { + strbuf_clear(ln); + return; + } + + i = strbuf_strchr(ln, '\n', i); + if (i >= 0) + strbuf_truncate(ln, i); } -// Check to see if a block ends with a blank line, descending +// Check to see if a node_block ends with a blank line, descending // if needed into lists and sublists. -static bool ends_with_blank_line(block* block) +static bool ends_with_blank_line(node_block* node_block) { - if (block->last_line_blank) { - return true; - } - if ((block->tag == list || block->tag == list_item) && block->last_child) { - return ends_with_blank_line(block->last_child); - } else { - return false; - } + if (node_block->last_line_blank) { + return true; + } + if ((node_block->tag == BLOCK_LIST || node_block->tag == BLOCK_LIST_ITEM) && node_block->last_child) { + return ends_with_blank_line(node_block->last_child); + } else { + return false; + } } // Break out of all containing lists -static int break_out_of_lists(block ** bptr, int line_number) +static int break_out_of_lists(node_block ** bptr, int line_number) { - block * container = *bptr; - block * b = container->top; - // find first containing list: - while (b && b->tag != list) { - b = b->last_child; - } - if (b) { - while (container && container != b) { - finalize(container, line_number); - container = container->parent; - } - finalize(b, line_number); - *bptr = b->parent; - } - return 0; + node_block *container = *bptr; + node_block *b = container->top; + // find first containing BLOCK_LIST: + while (b && b->tag != BLOCK_LIST) { + b = b->last_child; + } + if (b) { + while (container && container != b) { + finalize(container, line_number); + container = container->parent; + } + finalize(b, line_number); + *bptr = b->parent; + } + return 0; } -extern int finalize(block* b, int line_number) +static void finalize(node_block* b, int line_number) { - int firstlinelen; - int pos; - block* item; - block* subitem; - - check(b != NULL, "finalize called on null block"); - if (!b->open) { - return 0; // don't do anything if the block is already closed - } - b->open = false; - if (line_number > b->start_line) { - b->end_line = line_number - 1; - } else { - b->end_line = line_number; - } - - switch (b->tag) { - - case paragraph: - pos = 0; - while (bchar(b->string_content, 0) == '[' && - (pos = parse_reference(b->string_content, - b->top->attributes.refmap))) { - bdelete(b->string_content, 0, pos); - } - if (is_blank(b->string_content, 0)) { - b->tag = reference_def; - } - break; - - case indented_code: - remove_trailing_blank_lines(b->string_content); - bformata(b->string_content, "\n"); - break; - - case fenced_code: - // first line of contents becomes info - firstlinelen = bstrchr(b->string_content, '\n'); - b->attributes.fenced_code_data.info = - bmidstr(b->string_content, 0, firstlinelen); - bdelete(b->string_content, 0, firstlinelen + 1); // +1 for \n - btrimws(b->attributes.fenced_code_data.info); - unescape(b->attributes.fenced_code_data.info); - break; - - case list: // determine tight/loose status - b->attributes.list_data.tight = true; // tight by default - item = b->children; - - while (item) { - // check for non-final non-empty list item ending with blank line: - if (item->last_line_blank && item->next) { - b->attributes.list_data.tight = false; - break; - } - // recurse into children of list item, to see if there are - // spaces between them: - subitem = item->children; - while (subitem) { - if (ends_with_blank_line(subitem) && - (item->next || subitem->next)) { - b->attributes.list_data.tight = false; - break; - } - subitem = subitem->next; - } - if (!(b->attributes.list_data.tight)) { - break; - } - item = item->next; - } - - break; - - default: - break; - } - - return 0; - error: - return -1; + int firstlinelen; + int pos; + node_block* item; + node_block* subitem; + + if (!b->open) + return; // don't do anything if the node_block is already closed + + b->open = false; + if (line_number > b->start_line) { + b->end_line = line_number - 1; + } else { + b->end_line = line_number; + } + + switch (b->tag) { + case BLOCK_PARAGRAPH: + pos = 0; + while (strbuf_at(&b->string_content, 0) == '[' && + (pos = parse_reference_inline(&b->string_content, b->top->as.document.refmap))) { + + strbuf_drop(&b->string_content, pos); + } + if (is_blank(&b->string_content, 0)) { + b->tag = BLOCK_REFERENCE_DEF; + } + break; + + case BLOCK_INDENTED_CODE: + remove_trailing_blank_lines(&b->string_content); + strbuf_putc(&b->string_content, '\n'); + break; + + case BLOCK_FENCED_CODE: + // first line of contents becomes info + firstlinelen = strbuf_strchr(&b->string_content, '\n', 0); + + strbuf_init(&b->as.code.info, 0); + houdini_unescape_html_f( + &b->as.code.info, + b->string_content.ptr, + firstlinelen + ); + + strbuf_drop(&b->string_content, firstlinelen + 1); + + strbuf_trim(&b->as.code.info); + strbuf_unescape(&b->as.code.info); + break; + + case BLOCK_LIST: // determine tight/loose status + b->as.list.tight = true; // tight by default + item = b->children; + + while (item) { + // check for non-final non-empty list item ending with blank line: + if (item->last_line_blank && item->next) { + b->as.list.tight = false; + break; + } + // recurse into children of list item, to see if there are + // spaces between them: + subitem = item->children; + while (subitem) { + if (ends_with_blank_line(subitem) && + (item->next || subitem->next)) { + b->as.list.tight = false; + break; + } + subitem = subitem->next; + } + if (!(b->as.list.tight)) { + break; + } + item = item->next; + } + + break; + + default: + break; + } } -// Add a block as child of another. Return pointer to child. -extern block* add_child(block* parent, - int block_type, int start_line, int start_column) +// Add a node_block as child of another. Return pointer to child. +static node_block* add_child(node_block* parent, + int block_type, int start_line, int start_column) { - // if 'parent' isn't the kind of block that can accept this child, - // then back up til we hit a block that can. - while (!can_contain(parent->tag, block_type)) { - finalize(parent, start_line); - parent = parent->parent; - } - - check(parent != NULL, "parent container cannot accept children"); - - block* child = make_block(block_type, start_line, start_column); - child->parent = parent; - child->top = parent->top; - - if (parent->last_child) { - parent->last_child->next = child; - child->prev = parent->last_child; - } else { - parent->children = child; - child->prev = NULL; - } - parent->last_child = child; - return child; - error: - return NULL; + assert(parent); + + // if 'parent' isn't the kind of node_block that can accept this child, + // then back up til we hit a node_block that can. + while (!can_contain(parent->tag, block_type)) { + finalize(parent, start_line); + parent = parent->parent; + } + + node_block* child = make_block(block_type, start_line, start_column); + child->parent = parent; + child->top = parent->top; + + if (parent->last_child) { + parent->last_child->next = child; + child->prev = parent->last_child; + } else { + parent->children = child; + child->prev = NULL; + } + parent->last_child = child; + return child; } -// Free a block list and any children. -extern void free_blocks(block* e) +// Free a node_block list and any children. +void stmd_free_nodes(node_block *e) { - block * next; - while (e != NULL) { - next = e->next; - free_inlines(e->inline_content); - bdestroy(e->string_content); - if (e->tag == fenced_code) { - bdestroy(e->attributes.fenced_code_data.info); - } else if (e->tag == document) { - free_reference_map(e->attributes.refmap); - } - free_blocks(e->children); - free(e); - e = next; - } + node_block * next; + while (e != NULL) { + next = e->next; + free_inlines(e->inline_content); + strbuf_free(&e->string_content); + if (e->tag == BLOCK_FENCED_CODE) { + strbuf_free(&e->as.code.info); + } else if (e->tag == BLOCK_DOCUMENT) { + reference_map_free(e->as.document.refmap); + } + stmd_free_nodes(e->children); + free(e); + e = next; + } } -// Walk through block and all children, recursively, parsing +// Walk through node_block and all children, recursively, parsing // string content into inline content where appropriate. -int process_inlines(block* cur, reference** refmap) +void process_inlines(node_block* cur, reference_map *refmap) { - switch (cur->tag) { - - case paragraph: - case atx_header: - case setext_header: - check(cur->string_content != NULL, "string_content is NULL"); - cur->inline_content = parse_inlines(cur->string_content, refmap); - bdestroy(cur->string_content); - cur->string_content = NULL; - break; - - default: - break; - } - - block * child = cur->children; - while (child != NULL) { - process_inlines(child, refmap); - child = child->next; - } - - return 0; - error: - return -1; + switch (cur->tag) { + case BLOCK_PARAGRAPH: + case BLOCK_ATX_HEADER: + case BLOCK_SETEXT_HEADER: + cur->inline_content = parse_inlines(&cur->string_content, refmap); + break; + + default: + break; + } + + node_block *child = cur->children; + while (child != NULL) { + process_inlines(child, refmap); + child = child->next; + } } // Attempts to parse a list item marker (bullet or enumerated). // On success, returns length of the marker, and populates // data with the details. On failure, returns 0. -static int parse_list_marker(bstring ln, int pos, - struct ListData ** dataptr) +static int parse_list_marker(chunk *input, int pos, struct ListData ** dataptr) { - char c; - int startpos; - int start = 1; - struct ListData * data; - - startpos = pos; - c = bchar(ln, pos); - - if ((c == '*' || c == '-' || c == '+') && !scan_hrule(ln, pos)) { - pos++; - if (!isspace(bchar(ln, pos))) { - return 0; - } - data = malloc(sizeof(struct ListData)); - data->marker_offset = 0; // will be adjusted later - data->list_type = bullet; - data->bullet_char = c; - data->start = 1; - data->delimiter = period; - data->tight = false; - - } else if (isdigit(c)) { - - pos++; - while (isdigit(bchar(ln, pos))) { - pos++; - } - - if (!sscanf((char *) ln->data + startpos, "%d", &start)) { - log_err("sscanf failed"); - return 0; - } - - c = bchar(ln, pos); - if (c == '.' || c == ')') { - pos++; - if (!isspace(bchar(ln, pos))) { - return 0; - } - data = malloc(sizeof(struct ListData)); - data->marker_offset = 0; // will be adjusted later - data->list_type = ordered; - data->bullet_char = 0; - data->start = start; - data->delimiter = (c == '.' ? period : parens); - data->tight = false; - } else { - return 0; - } - - } else { - return 0; - } - - *dataptr = data; - return (pos - startpos); + unsigned char c; + int startpos; + struct ListData * data; + + startpos = pos; + c = peek_at(input, pos); + + if ((c == '*' || c == '-' || c == '+') && !scan_hrule(input, pos)) { + pos++; + if (!isspace(peek_at(input, pos))) { + return 0; + } + data = malloc(sizeof(struct ListData)); + data->marker_offset = 0; // will be adjusted later + data->list_type = bullet; + data->bullet_char = c; + data->start = 1; + data->delimiter = period; + data->tight = false; + + } else if (isdigit(c)) { + int start = 0; + + do { + start = (10 * start) + (peek_at(input, pos) - '0'); + pos++; + } while (isdigit(peek_at(input, pos))); + + c = peek_at(input, pos); + if (c == '.' || c == ')') { + pos++; + if (!isspace(peek_at(input, pos))) { + return 0; + } + data = malloc(sizeof(struct ListData)); + data->marker_offset = 0; // will be adjusted later + data->list_type = ordered; + data->bullet_char = 0; + data->start = start; + data->delimiter = (c == '.' ? period : parens); + data->tight = false; + } else { + return 0; + } + + } else { + return 0; + } + + *dataptr = data; + return (pos - startpos); } // Return 1 if list item belongs in list, else 0. -static int lists_match(struct ListData list_data, - struct ListData item_data) +static int lists_match(struct ListData *list_data, struct ListData *item_data) +{ + return (list_data->list_type == item_data->list_type && + list_data->delimiter == item_data->delimiter && + // list_data->marker_offset == item_data.marker_offset && + list_data->bullet_char == item_data->bullet_char); +} + +static node_block *finalize_document(node_block *document, int linenum) +{ + while (document != document->top) { + finalize(document, linenum); + document = document->parent; + } + + finalize(document, linenum); + process_inlines(document, document->as.document.refmap); + + return document; +} + +extern node_block *stmd_parse_file(FILE *f) { - return (list_data.list_type == item_data.list_type && - list_data.delimiter == item_data.delimiter && - // list_data.marker_offset == item_data.marker_offset && - list_data.bullet_char == item_data.bullet_char); + strbuf line = GH_BUF_INIT; + unsigned char buffer[4096]; + int linenum = 1; + node_block *document = make_document(); + + while (fgets((char *)buffer, sizeof(buffer), f)) { + utf8proc_detab(&line, buffer, strlen((char *)buffer)); + incorporate_line(&line, linenum, &document); + strbuf_clear(&line); + linenum++; + } + + strbuf_free(&line); + return finalize_document(document, linenum); } -// Process one line at a time, modifying a block. -// Returns 0 if successful. curptr is changed to point to -// the currently open block. -extern int incorporate_line(bstring ln, int line_number, block** curptr) +extern node_block *stmd_parse_document(const unsigned char *buffer, size_t len) { - block* last_matched_container; - int offset = 0; - int matched = 0; - int lev = 0; - int i; - struct ListData * data = NULL; - bool all_matched = true; - block* container; - block* cur = *curptr; - bool blank = false; - int first_nonspace; - int indent; - - // detab input line - check(bdetab(ln, 1) != BSTR_ERR, - "invalid UTF-8 sequence in line %d\n", line_number); - - // container starts at the document root. - container = cur->top; - - // for each containing block, try to parse the associated line start. - // bail out on failure: container will point to the last matching block. - - while (container->last_child && container->last_child->open) { - container = container->last_child; - - first_nonspace = offset; - while (bchar(ln, first_nonspace) == ' ') { - first_nonspace++; - } - - indent = first_nonspace - offset; - blank = bchar(ln, first_nonspace) == '\n'; - - if (container->tag == block_quote) { - - matched = indent <= 3 && bchar(ln, first_nonspace) == '>'; - if (matched) { - offset = first_nonspace + 1; - if (bchar(ln, offset) == ' ') { - offset++; - } - } else { - all_matched = false; - } - - } else if (container->tag == list_item) { - - if (indent >= container->attributes.list_data.marker_offset + - container->attributes.list_data.padding) { - offset += container->attributes.list_data.marker_offset + - container->attributes.list_data.padding; - } else if (blank) { - offset = first_nonspace; - } else { - all_matched = false; - } - - } else if (container->tag == indented_code) { - - if (indent >= CODE_INDENT) { - offset += CODE_INDENT; - } else if (blank) { - offset = first_nonspace; - } else { - all_matched = false; - } - - } else if (container->tag == atx_header || - container->tag == setext_header) { - - // a header can never contain more than one line - all_matched = false; - - } else if (container->tag == fenced_code) { - - // skip optional spaces of fence offset - i = container->attributes.fenced_code_data.fence_offset; - while (i > 0 && bchar(ln, offset) == ' ') { - offset++; - i--; - } - - } else if (container->tag == html_block) { - - if (blank) { - all_matched = false; - } - - } else if (container->tag == paragraph) { - - if (blank) { - container->last_line_blank =true; - all_matched = false; - } - - } - - if (!all_matched) { - container = container->parent; // back up to last matching block - break; - } - } - - last_matched_container = container; - - // check to see if we've hit 2nd blank line, break out of list: - if (blank && container->last_line_blank) { - break_out_of_lists(&container, line_number); - } - - // unless last matched container is code block, try new container starts: - while (container->tag != fenced_code && container->tag != indented_code && - container->tag != html_block) { - - first_nonspace = offset; - while (bchar(ln, first_nonspace) == ' ') { - first_nonspace++; - } - - indent = first_nonspace - offset; - blank = bchar(ln, first_nonspace) == '\n'; - - if (indent >= CODE_INDENT) { - - if (cur->tag != paragraph && !blank) { - offset += CODE_INDENT; - container = add_child(container, indented_code, line_number, offset + 1); - } else { // indent > 4 in lazy line - break; - } - - } else if (bchar(ln, first_nonspace) == '>') { - - offset = first_nonspace + 1; - // optional following character - if (bchar(ln, offset) == ' ') { - offset++; - } - container = add_child(container, block_quote, line_number, offset + 1); - - } else if ((matched = scan_atx_header_start(ln, first_nonspace))) { - - offset = first_nonspace + matched; - container = add_child(container, atx_header, line_number, offset + 1); - int hashpos = bstrchrp(ln, '#', first_nonspace); - check(hashpos != BSTR_ERR, "no # found in atx header start"); - int level = 0; - while (bchar(ln, hashpos) == '#') { - level++; - hashpos++; - } - container->attributes.header_level = level; - - } else if ((matched = scan_open_code_fence(ln, first_nonspace))) { - - container = add_child(container, fenced_code, line_number, - first_nonspace + 1); - container->attributes.fenced_code_data.fence_char = bchar(ln, - first_nonspace); - container->attributes.fenced_code_data.fence_length = matched; - container->attributes.fenced_code_data.fence_offset = - first_nonspace - offset; - offset = first_nonspace + matched; - - } else if ((matched = scan_html_block_tag(ln, first_nonspace))) { - - container = add_child(container, html_block, line_number, - first_nonspace + 1); - // note, we don't adjust offset because the tag is part of the text - - } else if (container->tag == paragraph && - (lev = scan_setext_header_line(ln, first_nonspace)) && - // check that there is only one line in the paragraph: - bstrrchrp(container->string_content, '\n', - blength(container->string_content) - 2) == BSTR_ERR) { - - container->tag = setext_header; - container->attributes.header_level = lev; - offset = blength(ln) - 1; - - } else if (!(container->tag == paragraph && !all_matched) && - (matched = scan_hrule(ln, first_nonspace))) { - - // it's only now that we know the line is not part of a setext header: - container = add_child(container, hrule, line_number, first_nonspace + 1); - finalize(container, line_number); - container = container->parent; - offset = blength(ln) - 1; - - } else if ((matched = parse_list_marker(ln, first_nonspace, &data))) { - - // compute padding: - offset = first_nonspace + matched; - i = 0; - while (i <= 5 && bchar(ln, offset + i) == ' ') { - i++; - } - // i = number of spaces after marker, up to 5 - if (i >= 5 || i < 1 || bchar(ln, offset) == '\n') { - data->padding = matched + 1; - if (i > 0) { - offset += 1; - } - } else { - data->padding = matched + i; - offset += i; - } - - // check container; if it's a list, see if this list item - // can continue the list; otherwise, create a list container. - - data->marker_offset = indent; - - if (container->tag != list || - !lists_match(container->attributes.list_data, *data)) { - container = add_child(container, list, line_number, - first_nonspace + 1); - container->attributes.list_data = *data; - } - - // add the list item - container = add_child(container, list_item, line_number, - first_nonspace + 1); - container->attributes.list_data = *data; - free(data); - - } else { - break; - } - - if (accepts_lines(container->tag)) { - // if it's a line container, it can't contain other containers - break; - } - } - - // what remains at offset is a text line. add the text to the - // appropriate container. - - first_nonspace = offset; - while (bchar(ln, first_nonspace) == ' ') { - first_nonspace++; - } - - indent = first_nonspace - offset; - blank = bchar(ln, first_nonspace) == '\n'; - - // block quote lines are never blank as they start with > - // and we don't count blanks in fenced code for purposes of tight/loose - // lists or breaking out of lists. we also don't set last_line_blank - // on an empty list item. - container->last_line_blank = (blank && - container->tag != block_quote && - container->tag != fenced_code && - !(container->tag == list_item && - container->children == NULL && - container->start_line == line_number)); - - block *cont = container; - while (cont->parent) { - cont->parent->last_line_blank = false; - cont = cont->parent; - } - - if (cur != last_matched_container && - container == last_matched_container && - !blank && - cur->tag == paragraph && - blength(cur->string_content) > 0) { - - check(add_line(cur, ln, offset) == 0, "could not add line"); - - } else { // not a lazy continuation - - // finalize any blocks that were not matched and set cur to container: - while (cur != last_matched_container) { - - finalize(cur, line_number); - cur = cur->parent; - check(cur != NULL, "cur is NULL, last_matched_container->tag = %d", - last_matched_container->tag); - - } - - if (container->tag == indented_code) { - - check(add_line(container, ln, offset) == 0, "could not add line"); - - } else if (container->tag == fenced_code) { - - matched = (indent <= 3 - && bchar(ln, first_nonspace) == container->attributes.fenced_code_data.fence_char) - && scan_close_code_fence(ln, first_nonspace, - container->attributes.fenced_code_data.fence_length); - if (matched) { - // if closing fence, don't add line to container; instead, close it: - finalize(container, line_number); - container = container->parent; // back up to parent - } else { - check(add_line(container, ln, offset) == 0, "could not add line"); - } - - } else if (container->tag == html_block) { - - check(add_line(container, ln, offset) == 0, "could not add line"); - - } else if (blank) { - - // ??? do nothing - - } else if (container->tag == atx_header) { - - // chop off trailing ###s...use a scanner? - brtrimws(ln); - int p = blength(ln) - 1; - int numhashes = 0; - // if string ends in #s, remove these: - while (bchar(ln, p) == '#') { - p--; - numhashes++; - } - if (bchar(ln, p) == '\\') { - // the last # was escaped, so we include it. - p++; - numhashes--; - } - check(bdelete(ln, p + 1, numhashes) != BSTR_ERR, - "could not delete final hashes"); - check(add_line(container, ln, first_nonspace) == 0, "could not add line"); - finalize(container, line_number); - container = container->parent; - - } else if (accepts_lines(container->tag)) { - - check(add_line(container, ln, first_nonspace) == 0, "could not add line"); + strbuf line = GH_BUF_INIT; + int linenum = 1; + const unsigned char *end = buffer + len; + node_block *document = make_document(); + + while (buffer < end) { + const unsigned char *eol = memchr(buffer, '\n', end - buffer); + + if (!eol) { + utf8proc_detab(&line, buffer, end - buffer); + buffer = end; + } else { + utf8proc_detab(&line, buffer, (eol - buffer) + 1); + buffer += (eol - buffer) + 1; + } + + incorporate_line(&line, linenum, &document); + strbuf_clear(&line); + linenum++; + } + + strbuf_free(&line); + return finalize_document(document, linenum); +} + +static void chop_trailing_hashtags(chunk *ch) +{ + int n, orig_n; + + chunk_rtrim(ch); + orig_n = n = ch->len - 1; + + // if string ends in #s, remove these: + while (n >= 0 && peek_at(ch, n) == '#') + n--; + + // the last # was escaped, so we include it. + if (n != orig_n && n >= 0 && peek_at(ch, n) == '\\') + n++; + + ch->len = n + 1; +} + +// Process one line at a time, modifying a node_block. +static void incorporate_line(strbuf *line, int line_number, node_block** curptr) +{ + node_block* last_matched_container; + int offset = 0; + int matched = 0; + int lev = 0; + int i; + struct ListData * data = NULL; + bool all_matched = true; + node_block* container; + node_block* cur = *curptr; + bool blank = false; + int first_nonspace; + int indent; + chunk input; + + input.data = line->ptr; + input.len = line->size; + + // container starts at the document root. + container = cur->top; + + // for each containing node_block, try to parse the associated line start. + // bail out on failure: container will point to the last matching node_block. + + while (container->last_child && container->last_child->open) { + container = container->last_child; + + first_nonspace = offset; + while (peek_at(&input, first_nonspace) == ' ') { + first_nonspace++; + } + + indent = first_nonspace - offset; + blank = peek_at(&input, first_nonspace) == '\n'; + + if (container->tag == BLOCK_BQUOTE) { + matched = indent <= 3 && peek_at(&input, first_nonspace) == '>'; + if (matched) { + offset = first_nonspace + 1; + if (peek_at(&input, offset) == ' ') + offset++; + } else { + all_matched = false; + } + + } else if (container->tag == BLOCK_LIST_ITEM) { + + if (indent >= container->as.list.marker_offset + + container->as.list.padding) { + offset += container->as.list.marker_offset + + container->as.list.padding; + } else if (blank) { + offset = first_nonspace; + } else { + all_matched = false; + } + + } else if (container->tag == BLOCK_INDENTED_CODE) { + + if (indent >= CODE_INDENT) { + offset += CODE_INDENT; + } else if (blank) { + offset = first_nonspace; + } else { + all_matched = false; + } + + } else if (container->tag == BLOCK_ATX_HEADER || + container->tag == BLOCK_SETEXT_HEADER) { + + // a header can never contain more than one line + all_matched = false; + + } else if (container->tag == BLOCK_FENCED_CODE) { + + // skip optional spaces of fence offset + i = container->as.code.fence_offset; + while (i > 0 && peek_at(&input, offset) == ' ') { + offset++; + i--; + } + + } else if (container->tag == BLOCK_HTML) { + + if (blank) { + all_matched = false; + } + + } else if (container->tag == BLOCK_PARAGRAPH) { + + if (blank) { + container->last_line_blank = true; + all_matched = false; + } + + } + + if (!all_matched) { + container = container->parent; // back up to last matching node_block + break; + } + } + + last_matched_container = container; + + // check to see if we've hit 2nd blank line, break out of list: + if (blank && container->last_line_blank) { + break_out_of_lists(&container, line_number); + } + + // unless last matched container is code node_block, try new container starts: + while (container->tag != BLOCK_FENCED_CODE && container->tag != BLOCK_INDENTED_CODE && + container->tag != BLOCK_HTML) { + + first_nonspace = offset; + while (peek_at(&input, first_nonspace) == ' ') + first_nonspace++; + + indent = first_nonspace - offset; + blank = peek_at(&input, first_nonspace) == '\n'; + + if (indent >= CODE_INDENT) { + if (cur->tag != BLOCK_PARAGRAPH && !blank) { + offset += CODE_INDENT; + container = add_child(container, BLOCK_INDENTED_CODE, line_number, offset + 1); + } else { // indent > 4 in lazy line + break; + } + + } else if (peek_at(&input, first_nonspace) == '>') { + + offset = first_nonspace + 1; + // optional following character + if (peek_at(&input, offset) == ' ') + offset++; + container = add_child(container, BLOCK_BQUOTE, line_number, offset + 1); + + } else if ((matched = scan_atx_header_start(&input, first_nonspace))) { + + offset = first_nonspace + matched; + container = add_child(container, BLOCK_ATX_HEADER, line_number, offset + 1); + + int hashpos = chunk_strchr(&input, '#', first_nonspace); + int level = 0; + + while (peek_at(&input, hashpos) == '#') { + level++; + hashpos++; + } + container->as.header.level = level; + + } else if ((matched = scan_open_code_fence(&input, first_nonspace))) { + + container = add_child(container, BLOCK_FENCED_CODE, line_number, first_nonspace + 1); + container->as.code.fence_char = peek_at(&input, first_nonspace); + container->as.code.fence_length = matched; + container->as.code.fence_offset = first_nonspace - offset; + offset = first_nonspace + matched; + + } else if ((matched = scan_html_block_tag(&input, first_nonspace))) { + + container = add_child(container, BLOCK_HTML, line_number, first_nonspace + 1); + // note, we don't adjust offset because the tag is part of the text + + } else if (container->tag == BLOCK_PARAGRAPH && + (lev = scan_setext_header_line(&input, first_nonspace)) && + // check that there is only one line in the paragraph: + strbuf_strrchr(&container->string_content, '\n', + strbuf_len(&container->string_content) - 2) < 0) { + + container->tag = BLOCK_SETEXT_HEADER; + container->as.header.level = lev; + offset = input.len - 1; + + } else if (!(container->tag == BLOCK_PARAGRAPH && !all_matched) && + (matched = scan_hrule(&input, first_nonspace))) { + + // it's only now that we know the line is not part of a setext header: + container = add_child(container, BLOCK_HRULE, line_number, first_nonspace + 1); + finalize(container, line_number); + container = container->parent; + offset = input.len - 1; + + } else if ((matched = parse_list_marker(&input, first_nonspace, &data))) { + + // compute padding: + offset = first_nonspace + matched; + i = 0; + while (i <= 5 && peek_at(&input, offset + i) == ' ') { + i++; + } + // i = number of spaces after marker, up to 5 + if (i >= 5 || i < 1 || peek_at(&input, offset) == '\n') { + data->padding = matched + 1; + if (i > 0) { + offset += 1; + } + } else { + data->padding = matched + i; + offset += i; + } + + // check container; if it's a list, see if this list item + // can continue the list; otherwise, create a list container. + + data->marker_offset = indent; + + if (container->tag != BLOCK_LIST || + !lists_match(&container->as.list, data)) { + container = add_child(container, BLOCK_LIST, line_number, + first_nonspace + 1); + + memcpy(&container->as.list, data, sizeof(*data)); + } + + // add the list item + container = add_child(container, BLOCK_LIST_ITEM, line_number, + first_nonspace + 1); + /* TODO: static */ + memcpy(&container->as.list, data, sizeof(*data)); + free(data); + } else { + break; + } + + if (accepts_lines(container->tag)) { + // if it's a line container, it can't contain other containers + break; + } + } + + // what remains at offset is a text line. add the text to the + // appropriate container. + + first_nonspace = offset; + while (peek_at(&input, first_nonspace) == ' ') + first_nonspace++; + + indent = first_nonspace - offset; + blank = peek_at(&input, first_nonspace) == '\n'; + + // node_block quote lines are never blank as they start with > + // and we don't count blanks in fenced code for purposes of tight/loose + // lists or breaking out of lists. we also don't set last_line_blank + // on an empty list item. + container->last_line_blank = (blank && + container->tag != BLOCK_BQUOTE && + container->tag != BLOCK_FENCED_CODE && + !(container->tag == BLOCK_LIST_ITEM && + container->children == NULL && + container->start_line == line_number)); + + node_block *cont = container; + while (cont->parent) { + cont->parent->last_line_blank = false; + cont = cont->parent; + } + + if (cur != last_matched_container && + container == last_matched_container && + !blank && + cur->tag == BLOCK_PARAGRAPH && + strbuf_len(&cur->string_content) > 0) { + + add_line(cur, &input, offset); + + } else { // not a lazy continuation + + // finalize any blocks that were not matched and set cur to container: + while (cur != last_matched_container) { + finalize(cur, line_number); + cur = cur->parent; + assert(cur != NULL); + } + + if (container->tag == BLOCK_INDENTED_CODE) { + + add_line(container, &input, offset); + + } else if (container->tag == BLOCK_FENCED_CODE) { + matched = 0; + + if (indent <= 3 && + peek_at(&input, first_nonspace) == container->as.code.fence_char) { + int fence_len = scan_close_code_fence(&input, first_nonspace); + if (fence_len > container->as.code.fence_length) + matched = 1; + } + + if (matched) { + // if closing fence, don't add line to container; instead, close it: + finalize(container, line_number); + container = container->parent; // back up to parent + } else { + add_line(container, &input, offset); + } + + } else if (container->tag == BLOCK_HTML) { + + add_line(container, &input, offset); + + } else if (blank) { + + // ??? do nothing + + } else if (container->tag == BLOCK_ATX_HEADER) { + + chop_trailing_hashtags(&input); + add_line(container, &input, first_nonspace); + finalize(container, line_number); + container = container->parent; + + } else if (accepts_lines(container->tag)) { + + add_line(container, &input, first_nonspace); + + } else if (container->tag != BLOCK_HRULE && container->tag != BLOCK_SETEXT_HEADER) { + + // create paragraph container for line + container = add_child(container, BLOCK_PARAGRAPH, line_number, first_nonspace + 1); + add_line(container, &input, first_nonspace); - } else if (container->tag != hrule && container->tag != setext_header) { - - // create paragraph container for line - container = add_child(container, paragraph, line_number, first_nonspace + 1); - check(add_line(container, ln, first_nonspace) == 0, "could not add line"); - - } else { + } else { + assert(false); + } - log_warn("Line %d with container type %d did not match any condition:\n\"%s\"", - line_number, container->tag, ln->data); - - } - *curptr = container; - } - - return 0; - error: - return -1; + *curptr = container; + } } diff --git a/src/bstrlib.c b/src/bstrlib.c deleted file mode 100644 index 1b19dbe..0000000 --- a/src/bstrlib.c +++ /dev/null @@ -1,2979 +0,0 @@ -/*
- * This source file is part of the bstring string library. This code was
- * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause
- * BSD open source license or GPL v2.0. Refer to the accompanying documentation
- * for details on usage and license.
- */
-
-/*
- * bstrlib.c
- *
- * This file is the core module for implementing the bstring functions.
- */
-
-#if defined (_MSC_VER)
-/* These warnings from MSVC++ are totally pointless. */
-# define _CRT_SECURE_NO_WARNINGS
-#endif
-
-#include <stdio.h>
-#include <stddef.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include "bstrlib.h"
-
-/* Optionally include a mechanism for debugging memory */
-
-#if defined(MEMORY_DEBUG) || defined(BSTRLIB_MEMORY_DEBUG)
-#include "memdbg.h"
-#endif
-
-#ifndef bstr__alloc
-#define bstr__alloc(x) malloc (x)
-#endif
-
-#ifndef bstr__free
-#define bstr__free(p) free (p)
-#endif
-
-#ifndef bstr__realloc
-#define bstr__realloc(p,x) realloc ((p), (x))
-#endif
-
-#ifndef bstr__memcpy
-#define bstr__memcpy(d,s,l) memcpy ((d), (s), (l))
-#endif
-
-#ifndef bstr__memmove
-#define bstr__memmove(d,s,l) memmove ((d), (s), (l))
-#endif
-
-#ifndef bstr__memset
-#define bstr__memset(d,c,l) memset ((d), (c), (l))
-#endif
-
-#ifndef bstr__memcmp
-#define bstr__memcmp(d,c,l) memcmp ((d), (c), (l))
-#endif
-
-#ifndef bstr__memchr
-#define bstr__memchr(s,c,l) memchr ((s), (c), (l))
-#endif
-
-/* Just a length safe wrapper for memmove. */
-
-#define bBlockCopy(D,S,L) { if ((L) > 0) bstr__memmove ((D),(S),(L)); }
-
-/* Compute the snapped size for a given requested size. By snapping to powers
- of 2 like this, repeated reallocations are avoided. */
-static int snapUpSize (int i) {
- if (i < 8) {
- i = 8;
- } else {
- unsigned int j;
- j = (unsigned int) i;
-
- j |= (j >> 1);
- j |= (j >> 2);
- j |= (j >> 4);
- j |= (j >> 8); /* Ok, since int >= 16 bits */
-#if (UINT_MAX != 0xffff)
- j |= (j >> 16); /* For 32 bit int systems */
-#if (UINT_MAX > 0xffffffffUL)
- j |= (j >> 32); /* For 64 bit int systems */
-#endif
-#endif
- /* Least power of two greater than i */
- j++;
- if ((int) j >= i) i = (int) j;
- }
- return i;
-}
-
-/* int balloc (bstring b, int len)
- *
- * Increase the size of the memory backing the bstring b to at least len.
- */
-int balloc (bstring b, int olen) {
- int len;
- if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen <= 0 ||
- b->mlen < b->slen || olen <= 0) {
- return BSTR_ERR;
- }
-
- if (olen >= b->mlen) {
- unsigned char * x;
-
- if ((len = snapUpSize (olen)) <= b->mlen) return BSTR_OK;
-
- /* Assume probability of a non-moving realloc is 0.125 */
- if (7 * b->mlen < 8 * b->slen) {
-
- /* If slen is close to mlen in size then use realloc to reduce
- the memory defragmentation */
-
- reallocStrategy:;
-
- x = (unsigned char *) bstr__realloc (b->data, (size_t) len);
- if (x == NULL) {
-
- /* Since we failed, try allocating the tighest possible
- allocation */
-
- if (NULL == (x = (unsigned char *) bstr__realloc (b->data, (size_t) (len = olen)))) {
- return BSTR_ERR;
- }
- }
- } else {
-
- /* If slen is not close to mlen then avoid the penalty of copying
- the extra bytes that are allocated, but not considered part of
- the string */
-
- if (NULL == (x = (unsigned char *) bstr__alloc ((size_t) len))) {
-
- /* Perhaps there is no available memory for the two
- allocations to be in memory at once */
-
- goto reallocStrategy;
-
- } else {
- if (b->slen) bstr__memcpy ((char *) x, (char *) b->data, (size_t) b->slen);
- bstr__free (b->data);
- }
- }
- b->data = x;
- b->mlen = len;
- b->data[b->slen] = (unsigned char) '\0';
- }
-
- return BSTR_OK;
-}
-
-/* int ballocmin (bstring b, int len)
- *
- * Set the size of the memory backing the bstring b to len or b->slen+1,
- * whichever is larger. Note that repeated use of this function can degrade
- * performance.
- */
-int ballocmin (bstring b, int len) {
- unsigned char * s;
-
- if (b == NULL || b->data == NULL || (b->slen+1) < 0 || b->mlen <= 0 ||
- b->mlen < b->slen || len <= 0) {
- return BSTR_ERR;
- }
-
- if (len < b->slen + 1) len = b->slen + 1;
-
- if (len != b->mlen) {
- s = (unsigned char *) bstr__realloc (b->data, (size_t) len);
- if (NULL == s) return BSTR_ERR;
- s[b->slen] = (unsigned char) '\0';
- b->data = s;
- b->mlen = len;
- }
-
- return BSTR_OK;
-}
-
-/* bstring bfromcstr (const char * str)
- *
- * Create a bstring which contains the contents of the '\0' terminated char *
- * buffer str.
- */
-bstring bfromcstr (const char * str) {
-bstring b;
-int i;
-size_t j;
-
- if (str == NULL) return NULL;
- j = (strlen) (str);
- i = snapUpSize ((int) (j + (2 - (j != 0))));
- if (i <= (int) j) return NULL;
-
- b = (bstring) bstr__alloc (sizeof (struct tagbstring));
- if (NULL == b) return NULL;
- b->slen = (int) j;
- if (NULL == (b->data = (unsigned char *) bstr__alloc (b->mlen = i))) {
- bstr__free (b);
- return NULL;
- }
-
- bstr__memcpy (b->data, str, j+1);
- return b;
-}
-
-/* bstring bfromcstralloc (int mlen, const char * str)
- *
- * Create a bstring which contains the contents of the '\0' terminated char *
- * buffer str. The memory buffer backing the string is at least len
- * characters in length.
- */
-bstring bfromcstralloc (int mlen, const char * str) {
-bstring b;
-int i;
-size_t j;
-
- if (str == NULL) return NULL;
- j = (strlen) (str);
- i = snapUpSize ((int) (j + (2 - (j != 0))));
- if (i <= (int) j) return NULL;
-
- b = (bstring) bstr__alloc (sizeof (struct tagbstring));
- if (b == NULL) return NULL;
- b->slen = (int) j;
- if (i < mlen) i = mlen;
-
- if (NULL == (b->data = (unsigned char *) bstr__alloc (b->mlen = i))) {
- bstr__free (b);
- return NULL;
- }
-
- bstr__memcpy (b->data, str, j+1);
- return b;
-}
-
-/* bstring blk2bstr (const void * blk, int len)
- *
- * Create a bstring which contains the content of the block blk of length
- * len.
- */
-bstring blk2bstr (const void * blk, int len) {
-bstring b;
-int i;
-
- if (blk == NULL || len < 0) return NULL;
- b = (bstring) bstr__alloc (sizeof (struct tagbstring));
- if (b == NULL) return NULL;
- b->slen = len;
-
- i = len + (2 - (len != 0));
- i = snapUpSize (i);
-
- b->mlen = i;
-
- b->data = (unsigned char *) bstr__alloc ((size_t) b->mlen);
- if (b->data == NULL) {
- bstr__free (b);
- return NULL;
- }
-
- if (len > 0) bstr__memcpy (b->data, blk, (size_t) len);
- b->data[len] = (unsigned char) '\0';
-
- return b;
-}
-
-/* char * bstr2cstr (const_bstring s, char z)
- *
- * Create a '\0' terminated char * buffer which is equal to the contents of
- * the bstring s, except that any contained '\0' characters are converted
- * to the character in z. This returned value should be freed with a
- * bcstrfree () call, by the calling application.
- */
-char * bstr2cstr (const_bstring b, char z) {
-int i, l;
-char * r;
-
- if (b == NULL || b->slen < 0 || b->data == NULL) return NULL;
- l = b->slen;
- r = (char *) bstr__alloc ((size_t) (l + 1));
- if (r == NULL) return r;
-
- for (i=0; i < l; i ++) {
- r[i] = (char) ((b->data[i] == '\0') ? z : (char) (b->data[i]));
- }
-
- r[l] = (unsigned char) '\0';
-
- return r;
-}
-
-/* int bcstrfree (char * s)
- *
- * Frees a C-string generated by bstr2cstr (). This is normally unnecessary
- * since it just wraps a call to bstr__free (), however, if bstr__alloc ()
- * and bstr__free () have been redefined as a macros within the bstrlib
- * module (via defining them in memdbg.h after defining
- * BSTRLIB_MEMORY_DEBUG) with some difference in behaviour from the std
- * library functions, then this allows a correct way of freeing the memory
- * that allows higher level code to be independent from these macro
- * redefinitions.
- */
-int bcstrfree (char * s) {
- if (s) {
- bstr__free (s);
- return BSTR_OK;
- }
- return BSTR_ERR;
-}
-
-/* int bconcat (bstring b0, const_bstring b1)
- *
- * Concatenate the bstring b1 to the bstring b0.
- */
-int bconcat (bstring b0, const_bstring b1) {
-int len, d;
-bstring aux = (bstring) b1;
-
- if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL) return BSTR_ERR;
-
- d = b0->slen;
- len = b1->slen;
- if ((d | (b0->mlen - d) | len | (d + len)) < 0) return BSTR_ERR;
-
- if (b0->mlen <= d + len + 1) {
- ptrdiff_t pd = b1->data - b0->data;
- if (0 <= pd && pd < b0->mlen) {
- if (NULL == (aux = bstrcpy (b1))) return BSTR_ERR;
- }
- if (balloc (b0, d + len + 1) != BSTR_OK) {
- if (aux != b1) bdestroy (aux);
- return BSTR_ERR;
- }
- }
-
- bBlockCopy (&b0->data[d], &aux->data[0], (size_t) len);
- b0->data[d + len] = (unsigned char) '\0';
- b0->slen = d + len;
- if (aux != b1) bdestroy (aux);
- return BSTR_OK;
-}
-
-/* int bconchar (bstring b, char c)
-/ *
- * Concatenate the single character c to the bstring b.
- */
-int bconchar (bstring b, char c) {
-int d;
-
- if (b == NULL) return BSTR_ERR;
- d = b->slen;
- if ((d | (b->mlen - d)) < 0 || balloc (b, d + 2) != BSTR_OK) return BSTR_ERR;
- b->data[d] = (unsigned char) c;
- b->data[d + 1] = (unsigned char) '\0';
- b->slen++;
- return BSTR_OK;
-}
-
-/* int bcatcstr (bstring b, const char * s)
- *
- * Concatenate a char * string to a bstring.
- */
-int bcatcstr (bstring b, const char * s) {
-char * d;
-int i, l;
-
- if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen < b->slen
- || b->mlen <= 0 || s == NULL) return BSTR_ERR;
-
- /* Optimistically concatenate directly */
- l = b->mlen - b->slen;
- d = (char *) &b->data[b->slen];
- for (i=0; i < l; i++) {
- if ((*d++ = *s++) == '\0') {
- b->slen += i;
- return BSTR_OK;
- }
- }
- b->slen += i;
-
- /* Need to explicitely resize and concatenate tail */
- return bcatblk (b, (const void *) s, (int) strlen (s));
-}
-
-/* int bcatblk (bstring b, const void * s, int len)
- *
- * Concatenate a fixed length buffer to a bstring.
- */
-int bcatblk (bstring b, const void * s, int len) {
-int nl;
-
- if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen < b->slen
- || b->mlen <= 0 || s == NULL || len < 0) return BSTR_ERR;
-
- if (0 > (nl = b->slen + len)) return BSTR_ERR; /* Overflow? */
- if (b->mlen <= nl && 0 > balloc (b, nl + 1)) return BSTR_ERR;
-
- bBlockCopy (&b->data[b->slen], s, (size_t) len);
- b->slen = nl;
- b->data[nl] = (unsigned char) '\0';
- return BSTR_OK;
-}
-
-/* bstring bstrcpy (const_bstring b)
- *
- * Create a copy of the bstring b.
- */
-bstring bstrcpy (const_bstring b) {
-bstring b0;
-int i,j;
-
- /* Attempted to copy an invalid string? */
- if (b == NULL || b->slen < 0 || b->data == NULL) return NULL;
-
- b0 = (bstring) bstr__alloc (sizeof (struct tagbstring));
- if (b0 == NULL) {
- /* Unable to allocate memory for string header */
- return NULL;
- }
-
- i = b->slen;
- j = snapUpSize (i + 1);
-
- b0->data = (unsigned char *) bstr__alloc (j);
- if (b0->data == NULL) {
- j = i + 1;
- b0->data = (unsigned char *) bstr__alloc (j);
- if (b0->data == NULL) {
- /* Unable to allocate memory for string data */
- bstr__free (b0);
- return NULL;
- }
- }
-
- b0->mlen = j;
- b0->slen = i;
-
- if (i) bstr__memcpy ((char *) b0->data, (char *) b->data, i);
- b0->data[b0->slen] = (unsigned char) '\0';
-
- return b0;
-}
-
-/* int bassign (bstring a, const_bstring b)
- *
- * Overwrite the string a with the contents of string b.
- */
-int bassign (bstring a, const_bstring b) {
- if (b == NULL || b->data == NULL || b->slen < 0)
- return BSTR_ERR;
- if (b->slen != 0) {
- if (balloc (a, b->slen) != BSTR_OK) return BSTR_ERR;
- bstr__memmove (a->data, b->data, b->slen);
- } else {
- if (a == NULL || a->data == NULL || a->mlen < a->slen ||
- a->slen < 0 || a->mlen == 0)
- return BSTR_ERR;
- }
- a->data[b->slen] = (unsigned char) '\0';
- a->slen = b->slen;
- return BSTR_OK;
-}
-
-/* int bassignmidstr (bstring a, const_bstring b, int left, int len)
- *
- * Overwrite the string a with the middle of contents of string b
- * starting from position left and running for a length len. left and
- * len are clamped to the ends of b as with the function bmidstr.
- */
-int bassignmidstr (bstring a, const_bstring b, int left, int len) {
- if (b == NULL || b->data == NULL || b->slen < 0)
- return BSTR_ERR;
-
- if (left < 0) {
- len += left;
- left = 0;
- }
-
- if (len > b->slen - left) len = b->slen - left;
-
- if (a == NULL || a->data == NULL || a->mlen < a->slen ||
- a->slen < 0 || a->mlen == 0)
- return BSTR_ERR;
-
- if (len > 0) {
- if (balloc (a, len) != BSTR_OK) return BSTR_ERR;
- bstr__memmove (a->data, b->data + left, len);
- a->slen = len;
- } else {
- a->slen = 0;
- }
- a->data[a->slen] = (unsigned char) '\0';
- return BSTR_OK;
-}
-
-/* int bassigncstr (bstring a, const char * str)
- *
- * Overwrite the string a with the contents of char * string str. Note that
- * the bstring a must be a well defined and writable bstring. If an error
- * occurs BSTR_ERR is returned however a may be partially overwritten.
- */
-int bassigncstr (bstring a, const char * str) {
-int i;
-size_t len;
- if (a == NULL || a->data == NULL || a->mlen < a->slen ||
- a->slen < 0 || a->mlen == 0 || NULL == str)
- return BSTR_ERR;
-
- for (i=0; i < a->mlen; i++) {
- if ('\0' == (a->data[i] = str[i])) {
- a->slen = i;
- return BSTR_OK;
- }
- }
-
- a->slen = i;
- len = strlen (str + i);
- if (len > INT_MAX || i + len + 1 > INT_MAX ||
- 0 > balloc (a, (int) (i + len + 1))) return BSTR_ERR;
- bBlockCopy (a->data + i, str + i, (size_t) len + 1);
- a->slen += (int) len;
- return BSTR_OK;
-}
-
-/* int bassignblk (bstring a, const void * s, int len)
- *
- * Overwrite the string a with the contents of the block (s, len). Note that
- * the bstring a must be a well defined and writable bstring. If an error
- * occurs BSTR_ERR is returned and a is not overwritten.
- */
-int bassignblk (bstring a, const void * s, int len) {
- if (a == NULL || a->data == NULL || a->mlen < a->slen ||
- a->slen < 0 || a->mlen == 0 || NULL == s || len + 1 < 1)
- return BSTR_ERR;
- if (len + 1 > a->mlen && 0 > balloc (a, len + 1)) return BSTR_ERR;
- bBlockCopy (a->data, s, (size_t) len);
- a->data[len] = (unsigned char) '\0';
- a->slen = len;
- return BSTR_OK;
-}
-
-/* int btrunc (bstring b, int n)
- *
- * Truncate the bstring to at most n characters.
- */
-int btrunc (bstring b, int n) {
- if (n < 0 || b == NULL || b->data == NULL || b->mlen < b->slen ||
- b->slen < 0 || b->mlen <= 0) return BSTR_ERR;
- if (b->slen > n) {
- b->slen = n;
- b->data[n] = (unsigned char) '\0';
- }
- return BSTR_OK;
-}
-
-#define upcase(c) (toupper ((unsigned char) c))
-#define downcase(c) (tolower ((unsigned char) c))
-#define wspace(c) (isspace ((unsigned char) c))
-
-/* int btoupper (bstring b)
- *
- * Convert contents of bstring to upper case.
- */
-int btoupper (bstring b) {
-int i, len;
- if (b == NULL || b->data == NULL || b->mlen < b->slen ||
- b->slen < 0 || b->mlen <= 0) return BSTR_ERR;
- for (i=0, len = b->slen; i < len; i++) {
- b->data[i] = (unsigned char) upcase (b->data[i]);
- }
- return BSTR_OK;
-}
-
-/* int btolower (bstring b)
- *
- * Convert contents of bstring to lower case.
- */
-int btolower (bstring b) {
-int i, len;
- if (b == NULL || b->data == NULL || b->mlen < b->slen ||
- b->slen < 0 || b->mlen <= 0) return BSTR_ERR;
- for (i=0, len = b->slen; i < len; i++) {
- b->data[i] = (unsigned char) downcase (b->data[i]);
- }
- return BSTR_OK;
-}
-
-/* int bstricmp (const_bstring b0, const_bstring b1)
- *
- * Compare two strings without differentiating between case. The return
- * value is the difference of the values of the characters where the two
- * strings first differ after lower case transformation, otherwise 0 is
- * returned indicating that the strings are equal. If the lengths are
- * different, then a difference from 0 is given, but if the first extra
- * character is '\0', then it is taken to be the value UCHAR_MAX+1.
- */
-int bstricmp (const_bstring b0, const_bstring b1) {
-int i, v, n;
-
- if (bdata (b0) == NULL || b0->slen < 0 ||
- bdata (b1) == NULL || b1->slen < 0) return SHRT_MIN;
- if ((n = b0->slen) > b1->slen) n = b1->slen;
- else if (b0->slen == b1->slen && b0->data == b1->data) return BSTR_OK;
-
- for (i = 0; i < n; i ++) {
- v = (char) downcase (b0->data[i])
- - (char) downcase (b1->data[i]);
- if (0 != v) return v;
- }
-
- if (b0->slen > n) {
- v = (char) downcase (b0->data[n]);
- if (v) return v;
- return UCHAR_MAX + 1;
- }
- if (b1->slen > n) {
- v = - (char) downcase (b1->data[n]);
- if (v) return v;
- return - (int) (UCHAR_MAX + 1);
- }
- return BSTR_OK;
-}
-
-/* int bstrnicmp (const_bstring b0, const_bstring b1, int n)
- *
- * Compare two strings without differentiating between case for at most n
- * characters. If the position where the two strings first differ is
- * before the nth position, the return value is the difference of the values
- * of the characters, otherwise 0 is returned. If the lengths are different
- * and less than n characters, then a difference from 0 is given, but if the
- * first extra character is '\0', then it is taken to be the value
- * UCHAR_MAX+1.
- */
-int bstrnicmp (const_bstring b0, const_bstring b1, int n) {
-int i, v, m;
-
- if (bdata (b0) == NULL || b0->slen < 0 ||
- bdata (b1) == NULL || b1->slen < 0 || n < 0) return SHRT_MIN;
- m = n;
- if (m > b0->slen) m = b0->slen;
- if (m > b1->slen) m = b1->slen;
-
- if (b0->data != b1->data) {
- for (i = 0; i < m; i ++) {
- v = (char) downcase (b0->data[i]);
- v -= (char) downcase (b1->data[i]);
- if (v != 0) return b0->data[i] - b1->data[i];
- }
- }
-
- if (n == m || b0->slen == b1->slen) return BSTR_OK;
-
- if (b0->slen > m) {
- v = (char) downcase (b0->data[m]);
- if (v) return v;
- return UCHAR_MAX + 1;
- }
-
- v = - (char) downcase (b1->data[m]);
- if (v) return v;
- return - (int) (UCHAR_MAX + 1);
-}
-
-/* int biseqcaseless (const_bstring b0, const_bstring b1)
- *
- * Compare two strings for equality without differentiating between case.
- * If the strings differ other than in case, 0 is returned, if the strings
- * are the same, 1 is returned, if there is an error, -1 is returned. If
- * the length of the strings are different, this function is O(1). '\0'
- * termination characters are not treated in any special way.
- */
-int biseqcaseless (const_bstring b0, const_bstring b1) {
-int i, n;
-
- if (bdata (b0) == NULL || b0->slen < 0 ||
- bdata (b1) == NULL || b1->slen < 0) return BSTR_ERR;
- if (b0->slen != b1->slen) return BSTR_OK;
- if (b0->data == b1->data || b0->slen == 0) return 1;
- for (i=0, n=b0->slen; i < n; i++) {
- if (b0->data[i] != b1->data[i]) {
- unsigned char c = (unsigned char) downcase (b0->data[i]);
- if (c != (unsigned char) downcase (b1->data[i])) return 0;
- }
- }
- return 1;
-}
-
-/* int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len)
- *
- * Compare beginning of string b0 with a block of memory of length len
- * without differentiating between case for equality. If the beginning of b0
- * differs from the memory block other than in case (or if b0 is too short),
- * 0 is returned, if the strings are the same, 1 is returned, if there is an
- * error, -1 is returned. '\0' characters are not treated in any special
- * way.
- */
-int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len) {
-int i;
-
- if (bdata (b0) == NULL || b0->slen < 0 || NULL == blk || len < 0)
- return BSTR_ERR;
- if (b0->slen < len) return BSTR_OK;
- if (b0->data == (const unsigned char *) blk || len == 0) return 1;
-
- for (i = 0; i < len; i ++) {
- if (b0->data[i] != ((const unsigned char *) blk)[i]) {
- if (downcase (b0->data[i]) !=
- downcase (((const unsigned char *) blk)[i])) return 0;
- }
- }
- return 1;
-}
-
-/*
- * int bltrimws (bstring b)
- *
- * Delete whitespace contiguous from the left end of the string.
- */
-int bltrimws (bstring b) {
-int i, len;
-
- if (b == NULL || b->data == NULL || b->mlen < b->slen ||
- b->slen < 0 || b->mlen <= 0) return BSTR_ERR;
-
- for (len = b->slen, i = 0; i < len; i++) {
- if (!wspace (b->data[i])) {
- return bdelete (b, 0, i);
- }
- }
-
- b->data[0] = (unsigned char) '\0';
- b->slen = 0;
- return BSTR_OK;
-}
-
-/*
- * int brtrimws (bstring b)
- *
- * Delete whitespace contiguous from the right end of the string.
- */
-int brtrimws (bstring b) {
-int i;
-
- if (b == NULL || b->data == NULL || b->mlen < b->slen ||
- b->slen < 0 || b->mlen <= 0) return BSTR_ERR;
-
- for (i = b->slen - 1; i >= 0; i--) {
- if (!wspace (b->data[i])) {
- if (b->mlen > i) b->data[i+1] = (unsigned char) '\0';
- b->slen = i + 1;
- return BSTR_OK;
- }
- }
-
- b->data[0] = (unsigned char) '\0';
- b->slen = 0;
- return BSTR_OK;
-}
-
-/*
- * int btrimws (bstring b)
- *
- * Delete whitespace contiguous from both ends of the string.
- */
-int btrimws (bstring b) {
-int i, j;
-
- if (b == NULL || b->data == NULL || b->mlen < b->slen ||
- b->slen < 0 || b->mlen <= 0) return BSTR_ERR;
-
- for (i = b->slen - 1; i >= 0; i--) {
- if (!wspace (b->data[i])) {
- if (b->mlen > i) b->data[i+1] = (unsigned char) '\0';
- b->slen = i + 1;
- for (j = 0; wspace (b->data[j]); j++) {}
- return bdelete (b, 0, j);
- }
- }
-
- b->data[0] = (unsigned char) '\0';
- b->slen = 0;
- return BSTR_OK;
-}
-
-/* int biseq (const_bstring b0, const_bstring b1)
- *
- * Compare the string b0 and b1. If the strings differ, 0 is returned, if
- * the strings are the same, 1 is returned, if there is an error, -1 is
- * returned. If the length of the strings are different, this function is
- * O(1). '\0' termination characters are not treated in any special way.
- */
-int biseq (const_bstring b0, const_bstring b1) {
- if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL ||
- b0->slen < 0 || b1->slen < 0) return BSTR_ERR;
- if (b0->slen != b1->slen) return BSTR_OK;
- if (b0->data == b1->data || b0->slen == 0) return 1;
- return !bstr__memcmp (b0->data, b1->data, b0->slen);
-}
-
-/* int bisstemeqblk (const_bstring b0, const void * blk, int len)
- *
- * Compare beginning of string b0 with a block of memory of length len for
- * equality. If the beginning of b0 differs from the memory block (or if b0
- * is too short), 0 is returned, if the strings are the same, 1 is returned,
- * if there is an error, -1 is returned. '\0' characters are not treated in
- * any special way.
- */
-int bisstemeqblk (const_bstring b0, const void * blk, int len) {
-int i;
-
- if (bdata (b0) == NULL || b0->slen < 0 || NULL == blk || len < 0)
- return BSTR_ERR;
- if (b0->slen < len) return BSTR_OK;
- if (b0->data == (const unsigned char *) blk || len == 0) return 1;
-
- for (i = 0; i < len; i ++) {
- if (b0->data[i] != ((const unsigned char *) blk)[i]) return BSTR_OK;
- }
- return 1;
-}
-
-/* int biseqcstr (const_bstring b, const char *s)
- *
- * Compare the bstring b and char * string s. The C string s must be '\0'
- * terminated at exactly the length of the bstring b, and the contents
- * between the two must be identical with the bstring b with no '\0'
- * characters for the two contents to be considered equal. This is
- * equivalent to the condition that their current contents will be always be
- * equal when comparing them in the same format after converting one or the
- * other. If the strings are equal 1 is returned, if they are unequal 0 is
- * returned and if there is a detectable error BSTR_ERR is returned.
- */
-int biseqcstr (const_bstring b, const char * s) {
-int i;
- if (b == NULL || s == NULL || b->data == NULL || b->slen < 0) return BSTR_ERR;
- for (i=0; i < b->slen; i++) {
- if (s[i] == '\0' || b->data[i] != (unsigned char) s[i]) return BSTR_OK;
- }
- return s[i] == '\0';
-}
-
-/* int biseqcstrcaseless (const_bstring b, const char *s)
- *
- * Compare the bstring b and char * string s. The C string s must be '\0'
- * terminated at exactly the length of the bstring b, and the contents
- * between the two must be identical except for case with the bstring b with
- * no '\0' characters for the two contents to be considered equal. This is
- * equivalent to the condition that their current contents will be always be
- * equal ignoring case when comparing them in the same format after
- * converting one or the other. If the strings are equal, except for case,
- * 1 is returned, if they are unequal regardless of case 0 is returned and
- * if there is a detectable error BSTR_ERR is returned.
- */
-int biseqcstrcaseless (const_bstring b, const char * s) {
-int i;
- if (b == NULL || s == NULL || b->data == NULL || b->slen < 0) return BSTR_ERR;
- for (i=0; i < b->slen; i++) {
- if (s[i] == '\0' ||
- (b->data[i] != (unsigned char) s[i] &&
- downcase (b->data[i]) != (unsigned char) downcase (s[i])))
- return BSTR_OK;
- }
- return s[i] == '\0';
-}
-
-/* int bstrcmp (const_bstring b0, const_bstring b1)
- *
- * Compare the string b0 and b1. If there is an error, SHRT_MIN is returned,
- * otherwise a value less than or greater than zero, indicating that the
- * string pointed to by b0 is lexicographically less than or greater than
- * the string pointed to by b1 is returned. If the the string lengths are
- * unequal but the characters up until the length of the shorter are equal
- * then a value less than, or greater than zero, indicating that the string
- * pointed to by b0 is shorter or longer than the string pointed to by b1 is
- * returned. 0 is returned if and only if the two strings are the same. If
- * the length of the strings are different, this function is O(n). Like its
- * standard C library counter part strcmp, the comparison does not proceed
- * past any '\0' termination characters encountered.
- */
-int bstrcmp (const_bstring b0, const_bstring b1) {
-int i, v, n;
-
- if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL ||
- b0->slen < 0 || b1->slen < 0) return SHRT_MIN;
- n = b0->slen; if (n > b1->slen) n = b1->slen;
- if (b0->slen == b1->slen && (b0->data == b1->data || b0->slen == 0))
- return BSTR_OK;
-
- for (i = 0; i < n; i ++) {
- v = ((char) b0->data[i]) - ((char) b1->data[i]);
- if (v != 0) return v;
- if (b0->data[i] == (unsigned char) '\0') return BSTR_OK;
- }
-
- if (b0->slen > n) return 1;
- if (b1->slen > n) return -1;
- return BSTR_OK;
-}
-
-/* int bstrncmp (const_bstring b0, const_bstring b1, int n)
- *
- * Compare the string b0 and b1 for at most n characters. If there is an
- * error, SHRT_MIN is returned, otherwise a value is returned as if b0 and
- * b1 were first truncated to at most n characters then bstrcmp was called
- * with these new strings are paremeters. If the length of the strings are
- * different, this function is O(n). Like its standard C library counter
- * part strcmp, the comparison does not proceed past any '\0' termination
- * characters encountered.
- */
-int bstrncmp (const_bstring b0, const_bstring b1, int n) {
-int i, v, m;
-
- if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL ||
- b0->slen < 0 || b1->slen < 0) return SHRT_MIN;
- m = n;
- if (m > b0->slen) m = b0->slen;
- if (m > b1->slen) m = b1->slen;
-
- if (b0->data != b1->data) {
- for (i = 0; i < m; i ++) {
- v = ((char) b0->data[i]) - ((char) b1->data[i]);
- if (v != 0) return v;
- if (b0->data[i] == (unsigned char) '\0') return BSTR_OK;
- }
- }
-
- if (n == m || b0->slen == b1->slen) return BSTR_OK;
-
- if (b0->slen > m) return 1;
- return -1;
-}
-
-/* bstring bmidstr (const_bstring b, int left, int len)
- *
- * Create a bstring which is the substring of b starting from position left
- * and running for a length len (clamped by the end of the bstring b.) If
- * b is detectably invalid, then NULL is returned. The section described
- * by (left, len) is clamped to the boundaries of b.
- */
-bstring bmidstr (const_bstring b, int left, int len) {
-
- if (b == NULL || b->slen < 0 || b->data == NULL) return NULL;
-
- if (left < 0) {
- len += left;
- left = 0;
- }
-
- if (len > b->slen - left) len = b->slen - left;
-
- if (len <= 0) return bfromcstr ("");
- return blk2bstr (b->data + left, len);
-}
-
-/* int bdelete (bstring b, int pos, int len)
- *
- * Removes characters from pos to pos+len-1 inclusive and shifts the tail of
- * the bstring starting from pos+len to pos. len must be positive for this
- * call to have any effect. The section of the string described by (pos,
- * len) is clamped to boundaries of the bstring b.
- */
-int bdelete (bstring b, int pos, int len) {
- /* Clamp to left side of bstring */
- if (pos < 0) {
- len += pos;
- pos = 0;
- }
-
- if (len < 0 || b == NULL || b->data == NULL || b->slen < 0 ||
- b->mlen < b->slen || b->mlen <= 0)
- return BSTR_ERR;
- if (len > 0 && pos < b->slen) {
- if (pos + len >= b->slen) {
- b->slen = pos;
- } else {
- bBlockCopy ((char *) (b->data + pos),
- (char *) (b->data + pos + len),
- b->slen - (pos+len));
- b->slen -= len;
- }
- b->data[b->slen] = (unsigned char) '\0';
- }
- return BSTR_OK;
-}
-
-/* int bdestroy (bstring b)
- *
- * Free up the bstring. Note that if b is detectably invalid or not writable
- * then no action is performed and BSTR_ERR is returned. Like a freed memory
- * allocation, dereferences, writes or any other action on b after it has
- * been bdestroyed is undefined.
- */
-int bdestroy (bstring b) {
- if (b == NULL || b->slen < 0 || b->mlen <= 0 || b->mlen < b->slen ||
- b->data == NULL)
- return BSTR_ERR;
-
- bstr__free (b->data);
-
- /* In case there is any stale usage, there is one more chance to
- notice this error. */
-
- b->slen = -1;
- b->mlen = -__LINE__;
- b->data = NULL;
-
- bstr__free (b);
- return BSTR_OK;
-}
-
-/* int binstr (const_bstring b1, int pos, const_bstring b2)
- *
- * Search for the bstring b2 in b1 starting from position pos, and searching
- * forward. If it is found then return with the first position where it is
- * found, otherwise return BSTR_ERR. Note that this is just a brute force
- * string searcher that does not attempt clever things like the Boyer-Moore
- * search algorithm. Because of this there are many degenerate cases where
- * this can take much longer than it needs to.
- */
-int binstr (const_bstring b1, int pos, const_bstring b2) {
-int j, ii, ll, lf;
-unsigned char * d0;
-unsigned char c0;
-register unsigned char * d1;
-register unsigned char c1;
-register int i;
-
- if (b1 == NULL || b1->data == NULL || b1->slen < 0 ||
- b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR;
- if (b1->slen == pos) return (b2->slen == 0)?pos:BSTR_ERR;
- if (b1->slen < pos || pos < 0) return BSTR_ERR;
- if (b2->slen == 0) return pos;
-
- /* No space to find such a string? */
- if ((lf = b1->slen - b2->slen + 1) <= pos) return BSTR_ERR;
-
- /* An obvious alias case */
- if (b1->data == b2->data && pos == 0) return 0;
-
- i = pos;
-
- d0 = b2->data;
- d1 = b1->data;
- ll = b2->slen;
-
- /* Peel off the b2->slen == 1 case */
- c0 = d0[0];
- if (1 == ll) {
- for (;i < lf; i++) if (c0 == d1[i]) return i;
- return BSTR_ERR;
- }
-
- c1 = c0;
- j = 0;
- lf = b1->slen - 1;
-
- ii = -1;
- if (i < lf) do {
- /* Unrolled current character test */
- if (c1 != d1[i]) {
- if (c1 != d1[1+i]) {
- i += 2;
- continue;
- }
- i++;
- }
-
- /* Take note if this is the start of a potential match */
- if (0 == j) ii = i;
-
- /* Shift the test character down by one */
- j++;
- i++;
-
- /* If this isn't past the last character continue */
- if (j < ll) {
- c1 = d0[j];
- continue;
- }
-
- N0:;
-
- /* If no characters mismatched, then we matched */
- if (i == ii+j) return ii;
-
- /* Shift back to the beginning */
- i -= j;
- j = 0;
- c1 = c0;
- } while (i < lf);
-
- /* Deal with last case if unrolling caused a misalignment */
- if (i == lf && ll == j+1 && c1 == d1[i]) goto N0;
-
- return BSTR_ERR;
-}
-
-/* int binstrr (const_bstring b1, int pos, const_bstring b2)
- *
- * Search for the bstring b2 in b1 starting from position pos, and searching
- * backward. If it is found then return with the first position where it is
- * found, otherwise return BSTR_ERR. Note that this is just a brute force
- * string searcher that does not attempt clever things like the Boyer-Moore
- * search algorithm. Because of this there are many degenerate cases where
- * this can take much longer than it needs to.
- */
-int binstrr (const_bstring b1, int pos, const_bstring b2) {
-int j, i, l;
-unsigned char * d0, * d1;
-
- if (b1 == NULL || b1->data == NULL || b1->slen < 0 ||
- b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR;
- if (b1->slen == pos && b2->slen == 0) return pos;
- if (b1->slen < pos || pos < 0) return BSTR_ERR;
- if (b2->slen == 0) return pos;
-
- /* Obvious alias case */
- if (b1->data == b2->data && pos == 0 && b2->slen <= b1->slen) return 0;
-
- i = pos;
- if ((l = b1->slen - b2->slen) < 0) return BSTR_ERR;
-
- /* If no space to find such a string then snap back */
- if (l + 1 <= i) i = l;
- j = 0;
-
- d0 = b2->data;
- d1 = b1->data;
- l = b2->slen;
-
- for (;;) {
- if (d0[j] == d1[i + j]) {
- j ++;
- if (j >= l) return i;
- } else {
- i --;
- if (i < 0) break;
- j=0;
- }
- }
-
- return BSTR_ERR;
-}
-
-/* int binstrcaseless (const_bstring b1, int pos, const_bstring b2)
- *
- * Search for the bstring b2 in b1 starting from position pos, and searching
- * forward but without regard to case. If it is found then return with the
- * first position where it is found, otherwise return BSTR_ERR. Note that
- * this is just a brute force string searcher that does not attempt clever
- * things like the Boyer-Moore search algorithm. Because of this there are
- * many degenerate cases where this can take much longer than it needs to.
- */
-int binstrcaseless (const_bstring b1, int pos, const_bstring b2) {
-int j, i, l, ll;
-unsigned char * d0, * d1;
-
- if (b1 == NULL || b1->data == NULL || b1->slen < 0 ||
- b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR;
- if (b1->slen == pos) return (b2->slen == 0)?pos:BSTR_ERR;
- if (b1->slen < pos || pos < 0) return BSTR_ERR;
- if (b2->slen == 0) return pos;
-
- l = b1->slen - b2->slen + 1;
-
- /* No space to find such a string? */
- if (l <= pos) return BSTR_ERR;
-
- /* An obvious alias case */
- if (b1->data == b2->data && pos == 0) return BSTR_OK;
-
- i = pos;
- j = 0;
-
- d0 = b2->data;
- d1 = b1->data;
- ll = b2->slen;
-
- for (;;) {
- if (d0[j] == d1[i + j] || downcase (d0[j]) == downcase (d1[i + j])) {
- j ++;
- if (j >= ll) return i;
- } else {
- i ++;
- if (i >= l) break;
- j=0;
- }
- }
-
- return BSTR_ERR;
-}
-
-/* int binstrrcaseless (const_bstring b1, int pos, const_bstring b2)
- *
- * Search for the bstring b2 in b1 starting from position pos, and searching
- * backward but without regard to case. If it is found then return with the
- * first position where it is found, otherwise return BSTR_ERR. Note that
- * this is just a brute force string searcher that does not attempt clever
- * things like the Boyer-Moore search algorithm. Because of this there are
- * many degenerate cases where this can take much longer than it needs to.
- */
-int binstrrcaseless (const_bstring b1, int pos, const_bstring b2) {
-int j, i, l;
-unsigned char * d0, * d1;
-
- if (b1 == NULL || b1->data == NULL || b1->slen < 0 ||
- b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR;
- if (b1->slen == pos && b2->slen == 0) return pos;
- if (b1->slen < pos || pos < 0) return BSTR_ERR;
- if (b2->slen == 0) return pos;
-
- /* Obvious alias case */
- if (b1->data == b2->data && pos == 0 && b2->slen <= b1->slen) return BSTR_OK;
-
- i = pos;
- if ((l = b1->slen - b2->slen) < 0) return BSTR_ERR;
-
- /* If no space to find such a string then snap back */
- if (l + 1 <= i) i = l;
- j = 0;
-
- d0 = b2->data;
- d1 = b1->data;
- l = b2->slen;
-
- for (;;) {
- if (d0[j] == d1[i + j] || downcase (d0[j]) == downcase (d1[i + j])) {
- j ++;
- if (j >= l) return i;
- } else {
- i --;
- if (i < 0) break;
- j=0;
- }
- }
-
- return BSTR_ERR;
-}
-
-
-/* int bstrchrp (const_bstring b, int c, int pos)
- *
- * Search for the character c in b forwards from the position pos
- * (inclusive).
- */
-int bstrchrp (const_bstring b, int c, int pos) {
-unsigned char * p;
-
- if (b == NULL || b->data == NULL || b->slen <= pos || pos < 0) return BSTR_ERR;
- p = (unsigned char *) bstr__memchr ((b->data + pos), (unsigned char) c, (b->slen - pos));
- if (p) return (int) (p - b->data);
- return BSTR_ERR;
-}
-
-/* int bstrrchrp (const_bstring b, int c, int pos)
- *
- * Search for the character c in b backwards from the position pos in string
- * (inclusive).
- */
-int bstrrchrp (const_bstring b, int c, int pos) {
-int i;
-
- if (b == NULL || b->data == NULL || b->slen <= pos || pos < 0) return BSTR_ERR;
- for (i=pos; i >= 0; i--) {
- if (b->data[i] == (unsigned char) c) return i;
- }
- return BSTR_ERR;
-}
-
-#if !defined (BSTRLIB_AGGRESSIVE_MEMORY_FOR_SPEED_TRADEOFF)
-#define LONG_LOG_BITS_QTY (3)
-#define LONG_BITS_QTY (1 << LONG_LOG_BITS_QTY)
-#define LONG_TYPE unsigned char
-
-#define CFCLEN ((1 << CHAR_BIT) / LONG_BITS_QTY)
-struct charField { LONG_TYPE content[CFCLEN]; };
-#define testInCharField(cf,c) ((cf)->content[(c) >> LONG_LOG_BITS_QTY] & (((long)1) << ((c) & (LONG_BITS_QTY-1))))
-#define setInCharField(cf,idx) { \
- unsigned int c = (unsigned int) (idx); \
- (cf)->content[c >> LONG_LOG_BITS_QTY] |= (LONG_TYPE) (1ul << (c & (LONG_BITS_QTY-1))); \
-}
-
-#else
-
-#define CFCLEN (1 << CHAR_BIT)
-struct charField { unsigned char content[CFCLEN]; };
-#define testInCharField(cf,c) ((cf)->content[(unsigned char) (c)])
-#define setInCharField(cf,idx) (cf)->content[(unsigned int) (idx)] = ~0
-
-#endif
-
-/* Convert a bstring to charField */
-static int buildCharField (struct charField * cf, const_bstring b) {
-int i;
- if (b == NULL || b->data == NULL || b->slen <= 0) return BSTR_ERR;
- memset ((void *) cf->content, 0, sizeof (struct charField));
- for (i=0; i < b->slen; i++) {
- setInCharField (cf, b->data[i]);
- }
- return BSTR_OK;
-}
-
-static void invertCharField (struct charField * cf) {
-int i;
- for (i=0; i < CFCLEN; i++) cf->content[i] = ~cf->content[i];
-}
-
-/* Inner engine for binchr */
-static int binchrCF (const unsigned char * data, int len, int pos, const struct charField * cf) {
-int i;
- for (i=pos; i < len; i++) {
- unsigned char c = (unsigned char) data[i];
- if (testInCharField (cf, c)) return i;
- }
- return BSTR_ERR;
-}
-
-/* int binchr (const_bstring b0, int pos, const_bstring b1);
- *
- * Search for the first position in b0 starting from pos or after, in which
- * one of the characters in b1 is found and return it. If such a position
- * does not exist in b0, then BSTR_ERR is returned.
- */
-int binchr (const_bstring b0, int pos, const_bstring b1) {
-struct charField chrs;
- if (pos < 0 || b0 == NULL || b0->data == NULL ||
- b0->slen <= pos) return BSTR_ERR;
- if (1 == b1->slen) return bstrchrp (b0, b1->data[0], pos);
- if (0 > buildCharField (&chrs, b1)) return BSTR_ERR;
- return binchrCF (b0->data, b0->slen, pos, &chrs);
-}
-
-/* Inner engine for binchrr */
-static int binchrrCF (const unsigned char * data, int pos, const struct charField * cf) {
-int i;
- for (i=pos; i >= 0; i--) {
- unsigned int c = (unsigned int) data[i];
- if (testInCharField (cf, c)) return i;
- }
- return BSTR_ERR;
-}
-
-/* int binchrr (const_bstring b0, int pos, const_bstring b1);
- *
- * Search for the last position in b0 no greater than pos, in which one of
- * the characters in b1 is found and return it. If such a position does not
- * exist in b0, then BSTR_ERR is returned.
- */
-int binchrr (const_bstring b0, int pos, const_bstring b1) {
-struct charField chrs;
- if (pos < 0 || b0 == NULL || b0->data == NULL || b1 == NULL ||
- b0->slen < pos) return BSTR_ERR;
- if (pos == b0->slen) pos--;
- if (1 == b1->slen) return bstrrchrp (b0, b1->data[0], pos);
- if (0 > buildCharField (&chrs, b1)) return BSTR_ERR;
- return binchrrCF (b0->data, pos, &chrs);
-}
-
-/* int bninchr (const_bstring b0, int pos, const_bstring b1);
- *
- * Search for the first position in b0 starting from pos or after, in which
- * none of the characters in b1 is found and return it. If such a position
- * does not exist in b0, then BSTR_ERR is returned.
- */
-int bninchr (const_bstring b0, int pos, const_bstring b1) {
-struct charField chrs;
- if (pos < 0 || b0 == NULL || b0->data == NULL ||
- b0->slen <= pos) return BSTR_ERR;
- if (buildCharField (&chrs, b1) < 0) return BSTR_ERR;
- invertCharField (&chrs);
- return binchrCF (b0->data, b0->slen, pos, &chrs);
-}
-
-/* int bninchrr (const_bstring b0, int pos, const_bstring b1);
- *
- * Search for the last position in b0 no greater than pos, in which none of
- * the characters in b1 is found and return it. If such a position does not
- * exist in b0, then BSTR_ERR is returned.
- */
-int bninchrr (const_bstring b0, int pos, const_bstring b1) {
-struct charField chrs;
- if (pos < 0 || b0 == NULL || b0->data == NULL ||
- b0->slen < pos) return BSTR_ERR;
- if (pos == b0->slen) pos--;
- if (buildCharField (&chrs, b1) < 0) return BSTR_ERR;
- invertCharField (&chrs);
- return binchrrCF (b0->data, pos, &chrs);
-}
-
-/* int bsetstr (bstring b0, int pos, bstring b1, unsigned char fill)
- *
- * Overwrite the string b0 starting at position pos with the string b1. If
- * the position pos is past the end of b0, then the character "fill" is
- * appended as necessary to make up the gap between the end of b0 and pos.
- * If b1 is NULL, it behaves as if it were a 0-length string.
- */
-int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill) {
-int d, newlen;
-ptrdiff_t pd;
-bstring aux = (bstring) b1;
-
- if (pos < 0 || b0 == NULL || b0->slen < 0 || NULL == b0->data ||
- b0->mlen < b0->slen || b0->mlen <= 0) return BSTR_ERR;
- if (b1 != NULL && (b1->slen < 0 || b1->data == NULL)) return BSTR_ERR;
-
- d = pos;
-
- /* Aliasing case */
- if (NULL != aux) {
- if ((pd = (ptrdiff_t) (b1->data - b0->data)) >= 0 && pd < (ptrdiff_t) b0->mlen) {
- if (NULL == (aux = bstrcpy (b1))) return BSTR_ERR;
- }
- d += aux->slen;
- }
-
- /* Increase memory size if necessary */
- if (balloc (b0, d + 1) != BSTR_OK) {
- if (aux != b1) bdestroy (aux);
- return BSTR_ERR;
- }
-
- newlen = b0->slen;
-
- /* Fill in "fill" character as necessary */
- if (pos > newlen) {
- bstr__memset (b0->data + b0->slen, (int) fill, (size_t) (pos - b0->slen));
- newlen = pos;
- }
-
- /* Copy b1 to position pos in b0. */
- if (aux != NULL) {
- bBlockCopy ((char *) (b0->data + pos), (char *) aux->data, aux->slen);
- if (aux != b1) bdestroy (aux);
- }
-
- /* Indicate the potentially increased size of b0 */
- if (d > newlen) newlen = d;
-
- b0->slen = newlen;
- b0->data[newlen] = (unsigned char) '\0';
-
- return BSTR_OK;
-}
-
-/* int binsert (bstring b1, int pos, bstring b2, unsigned char fill)
- *
- * Inserts the string b2 into b1 at position pos. If the position pos is
- * past the end of b1, then the character "fill" is appended as necessary to
- * make up the gap between the end of b1 and pos. Unlike bsetstr, binsert
- * does not allow b2 to be NULL.
- */
-int binsert (bstring b1, int pos, const_bstring b2, unsigned char fill) {
-int d, l;
-ptrdiff_t pd;
-bstring aux = (bstring) b2;
-
- if (pos < 0 || b1 == NULL || b2 == NULL || b1->slen < 0 ||
- b2->slen < 0 || b1->mlen < b1->slen || b1->mlen <= 0) return BSTR_ERR;
-
- /* Aliasing case */
- if ((pd = (ptrdiff_t) (b2->data - b1->data)) >= 0 && pd < (ptrdiff_t) b1->mlen) {
- if (NULL == (aux = bstrcpy (b2))) return BSTR_ERR;
- }
-
- /* Compute the two possible end pointers */
- d = b1->slen + aux->slen;
- l = pos + aux->slen;
- if ((d|l) < 0) return BSTR_ERR;
-
- if (l > d) {
- /* Inserting past the end of the string */
- if (balloc (b1, l + 1) != BSTR_OK) {
- if (aux != b2) bdestroy (aux);
- return BSTR_ERR;
- }
- bstr__memset (b1->data + b1->slen, (int) fill, (size_t) (pos - b1->slen));
- b1->slen = l;
- } else {
- /* Inserting in the middle of the string */
- if (balloc (b1, d + 1) != BSTR_OK) {
- if (aux != b2) bdestroy (aux);
- return BSTR_ERR;
- }
- bBlockCopy (b1->data + l, b1->data + pos, d - l);
- b1->slen = d;
- }
- bBlockCopy (b1->data + pos, aux->data, aux->slen);
- b1->data[b1->slen] = (unsigned char) '\0';
- if (aux != b2) bdestroy (aux);
- return BSTR_OK;
-}
-
-/* int breplace (bstring b1, int pos, int len, bstring b2,
- * unsigned char fill)
- *
- * Replace a section of a string from pos for a length len with the string b2.
- * fill is used is pos > b1->slen.
- */
-int breplace (bstring b1, int pos, int len, const_bstring b2,
- unsigned char fill) {
-int pl, ret;
-ptrdiff_t pd;
-bstring aux = (bstring) b2;
-
- if (pos < 0 || len < 0 || (pl = pos + len) < 0 || b1 == NULL ||
- b2 == NULL || b1->data == NULL || b2->data == NULL ||
- b1->slen < 0 || b2->slen < 0 || b1->mlen < b1->slen ||
- b1->mlen <= 0) return BSTR_ERR;
-
- /* Straddles the end? */
- if (pl >= b1->slen) {
- if ((ret = bsetstr (b1, pos, b2, fill)) < 0) return ret;
- if (pos + b2->slen < b1->slen) {
- b1->slen = pos + b2->slen;
- b1->data[b1->slen] = (unsigned char) '\0';
- }
- return ret;
- }
-
- /* Aliasing case */
- if ((pd = (ptrdiff_t) (b2->data - b1->data)) >= 0 && pd < (ptrdiff_t) b1->slen) {
- if (NULL == (aux = bstrcpy (b2))) return BSTR_ERR;
- }
-
- if (aux->slen > len) {
- if (balloc (b1, b1->slen + aux->slen - len) != BSTR_OK) {
- if (aux != b2) bdestroy (aux);
- return BSTR_ERR;
- }
- }
-
- if (aux->slen != len) bstr__memmove (b1->data + pos + aux->slen, b1->data + pos + len, b1->slen - (pos + len));
- bstr__memcpy (b1->data + pos, aux->data, aux->slen);
- b1->slen += aux->slen - len;
- b1->data[b1->slen] = (unsigned char) '\0';
- if (aux != b2) bdestroy (aux);
- return BSTR_OK;
-}
-
-/*
- * findreplaceengine is used to implement bfindreplace and
- * bfindreplacecaseless. It works by breaking the three cases of
- * expansion, reduction and replacement, and solving each of these
- * in the most efficient way possible.
- */
-
-typedef int (*instr_fnptr) (const_bstring s1, int pos, const_bstring s2);
-
-#define INITIAL_STATIC_FIND_INDEX_COUNT 32
-
-static int findreplaceengine (bstring b, const_bstring find, const_bstring repl, int pos, instr_fnptr instr) {
-int i, ret, slen, mlen, delta, acc;
-int * d;
-int static_d[INITIAL_STATIC_FIND_INDEX_COUNT+1]; /* This +1 is unnecessary, but it shuts up LINT. */
-ptrdiff_t pd;
-bstring auxf = (bstring) find;
-bstring auxr = (bstring) repl;
-
- if (b == NULL || b->data == NULL || find == NULL ||
- find->data == NULL || repl == NULL || repl->data == NULL ||
- pos < 0 || find->slen <= 0 || b->mlen < 0 || b->slen > b->mlen ||
- b->mlen <= 0 || b->slen < 0 || repl->slen < 0) return BSTR_ERR;
- if (pos > b->slen - find->slen) return BSTR_OK;
-
- /* Alias with find string */
- pd = (ptrdiff_t) (find->data - b->data);
- if ((ptrdiff_t) (pos - find->slen) < pd && pd < (ptrdiff_t) b->slen) {
- if (NULL == (auxf = bstrcpy (find))) return BSTR_ERR;
- }
-
- /* Alias with repl string */
- pd = (ptrdiff_t) (repl->data - b->data);
- if ((ptrdiff_t) (pos - repl->slen) < pd && pd < (ptrdiff_t) b->slen) {
- if (NULL == (auxr = bstrcpy (repl))) {
- if (auxf != find) bdestroy (auxf);
- return BSTR_ERR;
- }
- }
-
- delta = auxf->slen - auxr->slen;
-
- /* in-place replacement since find and replace strings are of equal
- length */
- if (delta == 0) {
- while ((pos = instr (b, pos, auxf)) >= 0) {
- bstr__memcpy (b->data + pos, auxr->data, auxr->slen);
- pos += auxf->slen;
- }
- if (auxf != find) bdestroy (auxf);
- if (auxr != repl) bdestroy (auxr);
- return BSTR_OK;
- }
-
- /* shrinking replacement since auxf->slen > auxr->slen */
- if (delta > 0) {
- acc = 0;
-
- while ((i = instr (b, pos, auxf)) >= 0) {
- if (acc && i > pos)
- bstr__memmove (b->data + pos - acc, b->data + pos, i - pos);
- if (auxr->slen)
- bstr__memcpy (b->data + i - acc, auxr->data, auxr->slen);
- acc += delta;
- pos = i + auxf->slen;
- }
-
- if (acc) {
- i = b->slen;
- if (i > pos)
- bstr__memmove (b->data + pos - acc, b->data + pos, i - pos);
- b->slen -= acc;
- b->data[b->slen] = (unsigned char) '\0';
- }
-
- if (auxf != find) bdestroy (auxf);
- if (auxr != repl) bdestroy (auxr);
- return BSTR_OK;
- }
-
- /* expanding replacement since find->slen < repl->slen. Its a lot
- more complicated. This works by first finding all the matches and
- storing them to a growable array, then doing at most one resize of
- the destination bstring and then performing the direct memory transfers
- of the string segment pieces to form the final result. The growable
- array of matches uses a deferred doubling reallocing strategy. What
- this means is that it starts as a reasonably fixed sized auto array in
- the hopes that many if not most cases will never need to grow this
- array. But it switches as soon as the bounds of the array will be
- exceeded. An extra find result is always appended to this array that
- corresponds to the end of the destination string, so slen is checked
- against mlen - 1 rather than mlen before resizing.
- */
-
- mlen = INITIAL_STATIC_FIND_INDEX_COUNT;
- d = (int *) static_d; /* Avoid malloc for trivial/initial cases */
- acc = slen = 0;
-
- while ((pos = instr (b, pos, auxf)) >= 0) {
- if (slen >= mlen - 1) {
- int sl, *t;
-
- mlen += mlen;
- sl = sizeof (int *) * mlen;
- if (static_d == d) d = NULL; /* static_d cannot be realloced */
- if (mlen <= 0 || sl < mlen || NULL == (t = (int *) bstr__realloc (d, sl))) {
- ret = BSTR_ERR;
- goto done;
- }
- if (NULL == d) bstr__memcpy (t, static_d, sizeof (static_d));
- d = t;
- }
- d[slen] = pos;
- slen++;
- acc -= delta;
- pos += auxf->slen;
- if (pos < 0 || acc < 0) {
- ret = BSTR_ERR;
- goto done;
- }
- }
-
- /* slen <= INITIAL_STATIC_INDEX_COUNT-1 or mlen-1 here. */
- d[slen] = b->slen;
-
- if (BSTR_OK == (ret = balloc (b, b->slen + acc + 1))) {
- b->slen += acc;
- for (i = slen-1; i >= 0; i--) {
- int s, l;
- s = d[i] + auxf->slen;
- l = d[i+1] - s; /* d[slen] may be accessed here. */
- if (l) {
- bstr__memmove (b->data + s + acc, b->data + s, l);
- }
- if (auxr->slen) {
- bstr__memmove (b->data + s + acc - auxr->slen,
- auxr->data, auxr->slen);
- }
- acc += delta;
- }
- b->data[b->slen] = (unsigned char) '\0';
- }
-
- done:;
- if (static_d == d) d = NULL;
- bstr__free (d);
- if (auxf != find) bdestroy (auxf);
- if (auxr != repl) bdestroy (auxr);
- return ret;
-}
-
-/* int bfindreplace (bstring b, const_bstring find, const_bstring repl,
- * int pos)
- *
- * Replace all occurrences of a find string with a replace string after a
- * given point in a bstring.
- */
-int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos) {
- return findreplaceengine (b, find, repl, pos, binstr);
-}
-
-/* int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl,
- * int pos)
- *
- * Replace all occurrences of a find string, ignoring case, with a replace
- * string after a given point in a bstring.
- */
-int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos) {
- return findreplaceengine (b, find, repl, pos, binstrcaseless);
-}
-
-/* int binsertch (bstring b, int pos, int len, unsigned char fill)
- *
- * Inserts the character fill repeatedly into b at position pos for a
- * length len. If the position pos is past the end of b, then the
- * character "fill" is appended as necessary to make up the gap between the
- * end of b and the position pos + len.
- */
-int binsertch (bstring b, int pos, int len, unsigned char fill) {
-int d, l, i;
-
- if (pos < 0 || b == NULL || b->slen < 0 || b->mlen < b->slen ||
- b->mlen <= 0 || len < 0) return BSTR_ERR;
-
- /* Compute the two possible end pointers */
- d = b->slen + len;
- l = pos + len;
- if ((d|l) < 0) return BSTR_ERR;
-
- if (l > d) {
- /* Inserting past the end of the string */
- if (balloc (b, l + 1) != BSTR_OK) return BSTR_ERR;
- pos = b->slen;
- b->slen = l;
- } else {
- /* Inserting in the middle of the string */
- if (balloc (b, d + 1) != BSTR_OK) return BSTR_ERR;
- for (i = d - 1; i >= l; i--) {
- b->data[i] = b->data[i - len];
- }
- b->slen = d;
- }
-
- for (i=pos; i < l; i++) b->data[i] = fill;
- b->data[b->slen] = (unsigned char) '\0';
- return BSTR_OK;
-}
-
-/* int bpattern (bstring b, int len)
- *
- * Replicate the bstring, b in place, end to end repeatedly until it
- * surpasses len characters, then chop the result to exactly len characters.
- * This function operates in-place. The function will return with BSTR_ERR
- * if b is NULL or of length 0, otherwise BSTR_OK is returned.
- */
-int bpattern (bstring b, int len) {
-int i, d;
-
- d = blength (b);
- if (d <= 0 || len < 0 || balloc (b, len + 1) != BSTR_OK) return BSTR_ERR;
- if (len > 0) {
- if (d == 1) return bsetstr (b, len, NULL, b->data[0]);
- for (i = d; i < len; i++) b->data[i] = b->data[i - d];
- }
- b->data[len] = (unsigned char) '\0';
- b->slen = len;
- return BSTR_OK;
-}
-
-#define BS_BUFF_SZ (1024)
-
-/* int breada (bstring b, bNread readPtr, void * parm)
- *
- * Use a finite buffer fread-like function readPtr to concatenate to the
- * bstring b the entire contents of file-like source data in a roughly
- * efficient way.
- */
-int breada (bstring b, bNread readPtr, void * parm) {
-int i, l, n;
-
- if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen ||
- b->mlen <= 0 || readPtr == NULL) return BSTR_ERR;
-
- i = b->slen;
- for (n=i+16; ; n += ((n < BS_BUFF_SZ) ? n : BS_BUFF_SZ)) {
- if (BSTR_OK != balloc (b, n + 1)) return BSTR_ERR;
- l = (int) readPtr ((void *) (b->data + i), 1, n - i, parm);
- i += l;
- b->slen = i;
- if (i < n) break;
- }
-
- b->data[i] = (unsigned char) '\0';
- return BSTR_OK;
-}
-
-/* bstring bread (bNread readPtr, void * parm)
- *
- * Use a finite buffer fread-like function readPtr to create a bstring
- * filled with the entire contents of file-like source data in a roughly
- * efficient way.
- */
-bstring bread (bNread readPtr, void * parm) {
-bstring buff;
-
- if (0 > breada (buff = bfromcstr (""), readPtr, parm)) {
- bdestroy (buff);
- return NULL;
- }
- return buff;
-}
-
-/* int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator)
- *
- * Use an fgetc-like single character stream reading function (getcPtr) to
- * obtain a sequence of characters which are concatenated to the end of the
- * bstring b. The stream read is terminated by the passed in terminator
- * parameter.
- *
- * If getcPtr returns with a negative number, or the terminator character
- * (which is appended) is read, then the stream reading is halted and the
- * function returns with a partial result in b. If there is an empty partial
- * result, 1 is returned. If no characters are read, or there is some other
- * detectable error, BSTR_ERR is returned.
- */
-int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator) {
-int c, d, e;
-
- if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen ||
- b->mlen <= 0 || getcPtr == NULL) return BSTR_ERR;
- d = 0;
- e = b->mlen - 2;
-
- while ((c = getcPtr (parm)) >= 0) {
- if (d > e) {
- b->slen = d;
- if (balloc (b, d + 2) != BSTR_OK) return BSTR_ERR;
- e = b->mlen - 2;
- }
- b->data[d] = (unsigned char) c;
- d++;
- if (c == terminator) break;
- }
-
- b->data[d] = (unsigned char) '\0';
- b->slen = d;
-
- return d == 0 && c < 0;
-}
-
-/* int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator)
- *
- * Use an fgetc-like single character stream reading function (getcPtr) to
- * obtain a sequence of characters which are concatenated to the end of the
- * bstring b. The stream read is terminated by the passed in terminator
- * parameter.
- *
- * If getcPtr returns with a negative number, or the terminator character
- * (which is appended) is read, then the stream reading is halted and the
- * function returns with a partial result concatentated to b. If there is
- * an empty partial result, 1 is returned. If no characters are read, or
- * there is some other detectable error, BSTR_ERR is returned.
- */
-int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator) {
-int c, d, e;
-
- if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen ||
- b->mlen <= 0 || getcPtr == NULL) return BSTR_ERR;
- d = b->slen;
- e = b->mlen - 2;
-
- while ((c = getcPtr (parm)) >= 0) {
- if (d > e) {
- b->slen = d;
- if (balloc (b, d + 2) != BSTR_OK) return BSTR_ERR;
- e = b->mlen - 2;
- }
- b->data[d] = (unsigned char) c;
- d++;
- if (c == terminator) break;
- }
-
- b->data[d] = (unsigned char) '\0';
- b->slen = d;
-
- return d == 0 && c < 0;
-}
-
-/* bstring bgets (bNgetc getcPtr, void * parm, char terminator)
- *
- * Use an fgetc-like single character stream reading function (getcPtr) to
- * obtain a sequence of characters which are concatenated into a bstring.
- * The stream read is terminated by the passed in terminator function.
- *
- * If getcPtr returns with a negative number, or the terminator character
- * (which is appended) is read, then the stream reading is halted and the
- * result obtained thus far is returned. If no characters are read, or
- * there is some other detectable error, NULL is returned.
- */
-bstring bgets (bNgetc getcPtr, void * parm, char terminator) {
-bstring buff;
-
- if (0 > bgetsa (buff = bfromcstr (""), getcPtr, parm, terminator) || 0 >= buff->slen) {
- bdestroy (buff);
- buff = NULL;
- }
- return buff;
-}
-
-struct bStream {
- bstring buff; /* Buffer for over-reads */
- void * parm; /* The stream handle for core stream */
- bNread readFnPtr; /* fread compatible fnptr for core stream */
- int isEOF; /* track file's EOF state */
- int maxBuffSz;
-};
-
-/* struct bStream * bsopen (bNread readPtr, void * parm)
- *
- * Wrap a given open stream (described by a fread compatible function
- * pointer and stream handle) into an open bStream suitable for the bstring
- * library streaming functions.
- */
-struct bStream * bsopen (bNread readPtr, void * parm) {
-struct bStream * s;
-
- if (readPtr == NULL) return NULL;
- s = (struct bStream *) bstr__alloc (sizeof (struct bStream));
- if (s == NULL) return NULL;
- s->parm = parm;
- s->buff = bfromcstr ("");
- s->readFnPtr = readPtr;
- s->maxBuffSz = BS_BUFF_SZ;
- s->isEOF = 0;
- return s;
-}
-
-/* int bsbufflength (struct bStream * s, int sz)
- *
- * Set the length of the buffer used by the bStream. If sz is zero, the
- * length is not set. This function returns with the previous length.
- */
-int bsbufflength (struct bStream * s, int sz) {
-int oldSz;
- if (s == NULL || sz < 0) return BSTR_ERR;
- oldSz = s->maxBuffSz;
- if (sz > 0) s->maxBuffSz = sz;
- return oldSz;
-}
-
-int bseof (const struct bStream * s) {
- if (s == NULL || s->readFnPtr == NULL) return BSTR_ERR;
- return s->isEOF && (s->buff->slen == 0);
-}
-
-/* void * bsclose (struct bStream * s)
- *
- * Close the bStream, and return the handle to the stream that was originally
- * used to open the given stream.
- */
-void * bsclose (struct bStream * s) {
-void * parm;
- if (s == NULL) return NULL;
- s->readFnPtr = NULL;
- if (s->buff) bdestroy (s->buff);
- s->buff = NULL;
- parm = s->parm;
- s->parm = NULL;
- s->isEOF = 1;
- bstr__free (s);
- return parm;
-}
-
-/* int bsreadlna (bstring r, struct bStream * s, char terminator)
- *
- * Read a bstring terminated by the terminator character or the end of the
- * stream from the bStream (s) and return it into the parameter r. This
- * function may read additional characters from the core stream that are not
- * returned, but will be retained for subsequent read operations.
- */
-int bsreadlna (bstring r, struct bStream * s, char terminator) {
-int i, l, ret, rlo;
-char * b;
-struct tagbstring x;
-
- if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 ||
- r->slen < 0 || r->mlen < r->slen) return BSTR_ERR;
- l = s->buff->slen;
- if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR;
- b = (char *) s->buff->data;
- x.data = (unsigned char *) b;
-
- /* First check if the current buffer holds the terminator */
- b[l] = terminator; /* Set sentinel */
- for (i=0; b[i] != terminator; i++) ;
- if (i < l) {
- x.slen = i + 1;
- ret = bconcat (r, &x);
- s->buff->slen = l;
- if (BSTR_OK == ret) bdelete (s->buff, 0, i + 1);
- return BSTR_OK;
- }
-
- rlo = r->slen;
-
- /* If not then just concatenate the entire buffer to the output */
- x.slen = l;
- if (BSTR_OK != bconcat (r, &x)) return BSTR_ERR;
-
- /* Perform direct in-place reads into the destination to allow for
- the minimum of data-copies */
- for (;;) {
- if (BSTR_OK != balloc (r, r->slen + s->maxBuffSz + 1)) return BSTR_ERR;
- b = (char *) (r->data + r->slen);
- l = (int) s->readFnPtr (b, 1, s->maxBuffSz, s->parm);
- if (l <= 0) {
- r->data[r->slen] = (unsigned char) '\0';
- s->buff->slen = 0;
- s->isEOF = 1;
- /* If nothing was read return with an error message */
- return BSTR_ERR & -(r->slen == rlo);
- }
- b[l] = terminator; /* Set sentinel */
- for (i=0; b[i] != terminator; i++) ;
- if (i < l) break;
- r->slen += l;
- }
-
- /* Terminator found, push over-read back to buffer */
- i++;
- r->slen += i;
- s->buff->slen = l - i;
- bstr__memcpy (s->buff->data, b + i, l - i);
- r->data[r->slen] = (unsigned char) '\0';
- return BSTR_OK;
-}
-
-/* int bsreadlnsa (bstring r, struct bStream * s, bstring term)
- *
- * Read a bstring terminated by any character in the term string or the end
- * of the stream from the bStream (s) and return it into the parameter r.
- * This function may read additional characters from the core stream that
- * are not returned, but will be retained for subsequent read operations.
- */
-int bsreadlnsa (bstring r, struct bStream * s, const_bstring term) {
-int i, l, ret, rlo;
-unsigned char * b;
-struct tagbstring x;
-struct charField cf;
-
- if (s == NULL || s->buff == NULL || r == NULL || term == NULL ||
- term->data == NULL || r->mlen <= 0 || r->slen < 0 ||
- r->mlen < r->slen) return BSTR_ERR;
- if (term->slen == 1) return bsreadlna (r, s, term->data[0]);
- if (term->slen < 1 || buildCharField (&cf, term)) return BSTR_ERR;
-
- l = s->buff->slen;
- if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR;
- b = (unsigned char *) s->buff->data;
- x.data = b;
-
- /* First check if the current buffer holds the terminator */
- b[l] = term->data[0]; /* Set sentinel */
- for (i=0; !testInCharField (&cf, b[i]); i++) ;
- if (i < l) {
- x.slen = i + 1;
- ret = bconcat (r, &x);
- s->buff->slen = l;
- if (BSTR_OK == ret) bdelete (s->buff, 0, i + 1);
- return BSTR_OK;
- }
-
- rlo = r->slen;
-
- /* If not then just concatenate the entire buffer to the output */
- x.slen = l;
- if (BSTR_OK != bconcat (r, &x)) return BSTR_ERR;
-
- /* Perform direct in-place reads into the destination to allow for
- the minimum of data-copies */
- for (;;) {
- if (BSTR_OK != balloc (r, r->slen + s->maxBuffSz + 1)) return BSTR_ERR;
- b = (unsigned char *) (r->data + r->slen);
- l = (int) s->readFnPtr (b, 1, s->maxBuffSz, s->parm);
- if (l <= 0) {
- r->data[r->slen] = (unsigned char) '\0';
- s->buff->slen = 0;
- s->isEOF = 1;
- /* If nothing was read return with an error message */
- return BSTR_ERR & -(r->slen == rlo);
- }
-
- b[l] = term->data[0]; /* Set sentinel */
- for (i=0; !testInCharField (&cf, b[i]); i++) ;
- if (i < l) break;
- r->slen += l;
- }
-
- /* Terminator found, push over-read back to buffer */
- i++;
- r->slen += i;
- s->buff->slen = l - i;
- bstr__memcpy (s->buff->data, b + i, l - i);
- r->data[r->slen] = (unsigned char) '\0';
- return BSTR_OK;
-}
-
-/* int bsreada (bstring r, struct bStream * s, int n)
- *
- * Read a bstring of length n (or, if it is fewer, as many bytes as is
- * remaining) from the bStream. This function may read additional
- * characters from the core stream that are not returned, but will be
- * retained for subsequent read operations. This function will not read
- * additional characters from the core stream beyond virtual stream pointer.
- */
-int bsreada (bstring r, struct bStream * s, int n) {
-int l, ret, orslen;
-char * b;
-struct tagbstring x;
-
- if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0
- || r->slen < 0 || r->mlen < r->slen || n <= 0) return BSTR_ERR;
-
- n += r->slen;
- if (n <= 0) return BSTR_ERR;
-
- l = s->buff->slen;
-
- orslen = r->slen;
-
- if (0 == l) {
- if (s->isEOF) return BSTR_ERR;
- if (r->mlen > n) {
- l = (int) s->readFnPtr (r->data + r->slen, 1, n - r->slen, s->parm);
- if (0 >= l || l > n - r->slen) {
- s->isEOF = 1;
- return BSTR_ERR;
- }
- r->slen += l;
- r->data[r->slen] = (unsigned char) '\0';
- return 0;
- }
- }
-
- if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR;
- b = (char *) s->buff->data;
- x.data = (unsigned char *) b;
-
- do {
- if (l + r->slen >= n) {
- x.slen = n - r->slen;
- ret = bconcat (r, &x);
- s->buff->slen = l;
- if (BSTR_OK == ret) bdelete (s->buff, 0, x.slen);
- return BSTR_ERR & -(r->slen == orslen);
- }
-
- x.slen = l;
- if (BSTR_OK != bconcat (r, &x)) break;
-
- l = n - r->slen;
- if (l > s->maxBuffSz) l = s->maxBuffSz;
-
- l = (int) s->readFnPtr (b, 1, l, s->parm);
-
- } while (l > 0);
- if (l < 0) l = 0;
- if (l == 0) s->isEOF = 1;
- s->buff->slen = l;
- return BSTR_ERR & -(r->slen == orslen);
-}
-
-/* int bsreadln (bstring r, struct bStream * s, char terminator)
- *
- * Read a bstring terminated by the terminator character or the end of the
- * stream from the bStream (s) and return it into the parameter r. This
- * function may read additional characters from the core stream that are not
- * returned, but will be retained for subsequent read operations.
- */
-int bsreadln (bstring r, struct bStream * s, char terminator) {
- if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0)
- return BSTR_ERR;
- if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR;
- r->slen = 0;
- return bsreadlna (r, s, terminator);
-}
-
-/* int bsreadlns (bstring r, struct bStream * s, bstring term)
- *
- * Read a bstring terminated by any character in the term string or the end
- * of the stream from the bStream (s) and return it into the parameter r.
- * This function may read additional characters from the core stream that
- * are not returned, but will be retained for subsequent read operations.
- */
-int bsreadlns (bstring r, struct bStream * s, const_bstring term) {
- if (s == NULL || s->buff == NULL || r == NULL || term == NULL
- || term->data == NULL || r->mlen <= 0) return BSTR_ERR;
- if (term->slen == 1) return bsreadln (r, s, term->data[0]);
- if (term->slen < 1) return BSTR_ERR;
- if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR;
- r->slen = 0;
- return bsreadlnsa (r, s, term);
-}
-
-/* int bsread (bstring r, struct bStream * s, int n)
- *
- * Read a bstring of length n (or, if it is fewer, as many bytes as is
- * remaining) from the bStream. This function may read additional
- * characters from the core stream that are not returned, but will be
- * retained for subsequent read operations. This function will not read
- * additional characters from the core stream beyond virtual stream pointer.
- */
-int bsread (bstring r, struct bStream * s, int n) {
- if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0
- || n <= 0) return BSTR_ERR;
- if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR;
- r->slen = 0;
- return bsreada (r, s, n);
-}
-
-/* int bsunread (struct bStream * s, const_bstring b)
- *
- * Insert a bstring into the bStream at the current position. These
- * characters will be read prior to those that actually come from the core
- * stream.
- */
-int bsunread (struct bStream * s, const_bstring b) {
- if (s == NULL || s->buff == NULL) return BSTR_ERR;
- return binsert (s->buff, 0, b, (unsigned char) '?');
-}
-
-/* int bspeek (bstring r, const struct bStream * s)
- *
- * Return the currently buffered characters from the bStream that will be
- * read prior to reads from the core stream.
- */
-int bspeek (bstring r, const struct bStream * s) {
- if (s == NULL || s->buff == NULL) return BSTR_ERR;
- return bassign (r, s->buff);
-}
-
-/* bstring bjoin (const struct bstrList * bl, const_bstring sep);
- *
- * Join the entries of a bstrList into one bstring by sequentially
- * concatenating them with the sep string in between. If there is an error
- * NULL is returned, otherwise a bstring with the correct result is returned.
- */
-bstring bjoin (const struct bstrList * bl, const_bstring sep) {
-bstring b;
-int i, c, v;
-
- if (bl == NULL || bl->qty < 0) return NULL;
- if (sep != NULL && (sep->slen < 0 || sep->data == NULL)) return NULL;
-
- for (i = 0, c = 1; i < bl->qty; i++) {
- v = bl->entry[i]->slen;
- if (v < 0) return NULL; /* Invalid input */
- c += v;
- if (c < 0) return NULL; /* Wrap around ?? */
- }
-
- if (sep != NULL) c += (bl->qty - 1) * sep->slen;
-
- b = (bstring) bstr__alloc (sizeof (struct tagbstring));
- if (NULL == b) return NULL; /* Out of memory */
- b->data = (unsigned char *) bstr__alloc (c);
- if (b->data == NULL) {
- bstr__free (b);
- return NULL;
- }
-
- b->mlen = c;
- b->slen = c-1;
-
- for (i = 0, c = 0; i < bl->qty; i++) {
- if (i > 0 && sep != NULL) {
- bstr__memcpy (b->data + c, sep->data, sep->slen);
- c += sep->slen;
- }
- v = bl->entry[i]->slen;
- bstr__memcpy (b->data + c, bl->entry[i]->data, v);
- c += v;
- }
- b->data[c] = (unsigned char) '\0';
- return b;
-}
-
-#define BSSSC_BUFF_LEN (256)
-
-/* int bssplitscb (struct bStream * s, const_bstring splitStr,
- * int (* cb) (void * parm, int ofs, const_bstring entry), void * parm)
- *
- * Iterate the set of disjoint sequential substrings read from a stream
- * divided by any of the characters in splitStr. An empty splitStr causes
- * the whole stream to be iterated once.
- *
- * Note: At the point of calling the cb function, the bStream pointer is
- * pointed exactly at the position right after having read the split
- * character. The cb function can act on the stream by causing the bStream
- * pointer to move, and bssplitscb will continue by starting the next split
- * at the position of the pointer after the return from cb.
- *
- * However, if the cb causes the bStream s to be destroyed then the cb must
- * return with a negative value, otherwise bssplitscb will continue in an
- * undefined manner.
- */
-int bssplitscb (struct bStream * s, const_bstring splitStr,
- int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) {
-struct charField chrs;
-bstring buff;
-int i, p, ret;
-
- if (cb == NULL || s == NULL || s->readFnPtr == NULL
- || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR;
-
- if (NULL == (buff = bfromcstr (""))) return BSTR_ERR;
-
- if (splitStr->slen == 0) {
- while (bsreada (buff, s, BSSSC_BUFF_LEN) >= 0) ;
- if ((ret = cb (parm, 0, buff)) > 0)
- ret = 0;
- } else {
- buildCharField (&chrs, splitStr);
- ret = p = i = 0;
- for (;;) {
- if (i >= buff->slen) {
- bsreada (buff, s, BSSSC_BUFF_LEN);
- if (i >= buff->slen) {
- if (0 < (ret = cb (parm, p, buff))) ret = 0;
- break;
- }
- }
- if (testInCharField (&chrs, buff->data[i])) {
- struct tagbstring t;
- unsigned char c;
-
- blk2tbstr (t, buff->data + i + 1, buff->slen - (i + 1));
- if ((ret = bsunread (s, &t)) < 0) break;
- buff->slen = i;
- c = buff->data[i];
- buff->data[i] = (unsigned char) '\0';
- if ((ret = cb (parm, p, buff)) < 0) break;
- buff->data[i] = c;
- buff->slen = 0;
- p += i + 1;
- i = -1;
- }
- i++;
- }
- }
-
- bdestroy (buff);
- return ret;
-}
-
-/* int bssplitstrcb (struct bStream * s, const_bstring splitStr,
- * int (* cb) (void * parm, int ofs, const_bstring entry), void * parm)
- *
- * Iterate the set of disjoint sequential substrings read from a stream
- * divided by the entire substring splitStr. An empty splitStr causes
- * each character of the stream to be iterated.
- *
- * Note: At the point of calling the cb function, the bStream pointer is
- * pointed exactly at the position right after having read the split
- * character. The cb function can act on the stream by causing the bStream
- * pointer to move, and bssplitscb will continue by starting the next split
- * at the position of the pointer after the return from cb.
- *
- * However, if the cb causes the bStream s to be destroyed then the cb must
- * return with a negative value, otherwise bssplitscb will continue in an
- * undefined manner.
- */
-int bssplitstrcb (struct bStream * s, const_bstring splitStr,
- int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) {
-bstring buff;
-int i, p, ret;
-
- if (cb == NULL || s == NULL || s->readFnPtr == NULL
- || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR;
-
- if (splitStr->slen == 1) return bssplitscb (s, splitStr, cb, parm);
-
- if (NULL == (buff = bfromcstr (""))) return BSTR_ERR;
-
- if (splitStr->slen == 0) {
- for (i=0; bsreada (buff, s, BSSSC_BUFF_LEN) >= 0; i++) {
- if ((ret = cb (parm, 0, buff)) < 0) {
- bdestroy (buff);
- return ret;
- }
- buff->slen = 0;
- }
- return BSTR_OK;
- } else {
- ret = p = i = 0;
- for (i=p=0;;) {
- if ((ret = binstr (buff, 0, splitStr)) >= 0) {
- struct tagbstring t;
- blk2tbstr (t, buff->data, ret);
- i = ret + splitStr->slen;
- if ((ret = cb (parm, p, &t)) < 0) break;
- p += i;
- bdelete (buff, 0, i);
- } else {
- bsreada (buff, s, BSSSC_BUFF_LEN);
- if (bseof (s)) {
- if ((ret = cb (parm, p, buff)) > 0) ret = 0;
- break;
- }
- }
- }
- }
-
- bdestroy (buff);
- return ret;
-}
-
-/* int bstrListCreate (void)
- *
- * Create a bstrList.
- */
-struct bstrList * bstrListCreate (void) {
-struct bstrList * sl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList));
- if (sl) {
- sl->entry = (bstring *) bstr__alloc (1*sizeof (bstring));
- if (!sl->entry) {
- bstr__free (sl);
- sl = NULL;
- } else {
- sl->qty = 0;
- sl->mlen = 1;
- }
- }
- return sl;
-}
-
-/* int bstrListDestroy (struct bstrList * sl)
- *
- * Destroy a bstrList that has been created by bsplit, bsplits or bstrListCreate.
- */
-int bstrListDestroy (struct bstrList * sl) {
-int i;
- if (sl == NULL || sl->qty < 0) return BSTR_ERR;
- for (i=0; i < sl->qty; i++) {
- if (sl->entry[i]) {
- bdestroy (sl->entry[i]);
- sl->entry[i] = NULL;
- }
- }
- sl->qty = -1;
- sl->mlen = -1;
- bstr__free (sl->entry);
- sl->entry = NULL;
- bstr__free (sl);
- return BSTR_OK;
-}
-
-/* int bstrListAlloc (struct bstrList * sl, int msz)
- *
- * Ensure that there is memory for at least msz number of entries for the
- * list.
- */
-int bstrListAlloc (struct bstrList * sl, int msz) {
-bstring * l;
-int smsz;
-size_t nsz;
- if (!sl || msz <= 0 || !sl->entry || sl->qty < 0 || sl->mlen <= 0 || sl->qty > sl->mlen) return BSTR_ERR;
- if (sl->mlen >= msz) return BSTR_OK;
- smsz = snapUpSize (msz);
- nsz = ((size_t) smsz) * sizeof (bstring);
- if (nsz < (size_t) smsz) return BSTR_ERR;
- l = (bstring *) bstr__realloc (sl->entry, nsz);
- if (!l) {
- smsz = msz;
- nsz = ((size_t) smsz) * sizeof (bstring);
- l = (bstring *) bstr__realloc (sl->entry, nsz);
- if (!l) return BSTR_ERR;
- }
- sl->mlen = smsz;
- sl->entry = l;
- return BSTR_OK;
-}
-
-/* int bstrListAllocMin (struct bstrList * sl, int msz)
- *
- * Try to allocate the minimum amount of memory for the list to include at
- * least msz entries or sl->qty whichever is greater.
- */
-int bstrListAllocMin (struct bstrList * sl, int msz) {
-bstring * l;
-size_t nsz;
- if (!sl || msz <= 0 || !sl->entry || sl->qty < 0 || sl->mlen <= 0 || sl->qty > sl->mlen) return BSTR_ERR;
- if (msz < sl->qty) msz = sl->qty;
- if (sl->mlen == msz) return BSTR_OK;
- nsz = ((size_t) msz) * sizeof (bstring);
- if (nsz < (size_t) msz) return BSTR_ERR;
- l = (bstring *) bstr__realloc (sl->entry, nsz);
- if (!l) return BSTR_ERR;
- sl->mlen = msz;
- sl->entry = l;
- return BSTR_OK;
-}
-
-/* int bsplitcb (const_bstring str, unsigned char splitChar, int pos,
- * int (* cb) (void * parm, int ofs, int len), void * parm)
- *
- * Iterate the set of disjoint sequential substrings over str divided by the
- * character in splitChar.
- *
- * Note: Non-destructive modification of str from within the cb function
- * while performing this split is not undefined. bsplitcb behaves in
- * sequential lock step with calls to cb. I.e., after returning from a cb
- * that return a non-negative integer, bsplitcb continues from the position
- * 1 character after the last detected split character and it will halt
- * immediately if the length of str falls below this point. However, if the
- * cb function destroys str, then it *must* return with a negative value,
- * otherwise bsplitcb will continue in an undefined manner.
- */
-int bsplitcb (const_bstring str, unsigned char splitChar, int pos,
- int (* cb) (void * parm, int ofs, int len), void * parm) {
-int i, p, ret;
-
- if (cb == NULL || str == NULL || pos < 0 || pos > str->slen)
- return BSTR_ERR;
-
- p = pos;
- do {
- for (i=p; i < str->slen; i++) {
- if (str->data[i] == splitChar) break;
- }
- if ((ret = cb (parm, p, i - p)) < 0) return ret;
- p = i + 1;
- } while (p <= str->slen);
- return BSTR_OK;
-}
-
-/* int bsplitscb (const_bstring str, const_bstring splitStr, int pos,
- * int (* cb) (void * parm, int ofs, int len), void * parm)
- *
- * Iterate the set of disjoint sequential substrings over str divided by any
- * of the characters in splitStr. An empty splitStr causes the whole str to
- * be iterated once.
- *
- * Note: Non-destructive modification of str from within the cb function
- * while performing this split is not undefined. bsplitscb behaves in
- * sequential lock step with calls to cb. I.e., after returning from a cb
- * that return a non-negative integer, bsplitscb continues from the position
- * 1 character after the last detected split character and it will halt
- * immediately if the length of str falls below this point. However, if the
- * cb function destroys str, then it *must* return with a negative value,
- * otherwise bsplitscb will continue in an undefined manner.
- */
-int bsplitscb (const_bstring str, const_bstring splitStr, int pos,
- int (* cb) (void * parm, int ofs, int len), void * parm) {
-struct charField chrs;
-int i, p, ret;
-
- if (cb == NULL || str == NULL || pos < 0 || pos > str->slen
- || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR;
- if (splitStr->slen == 0) {
- if ((ret = cb (parm, 0, str->slen)) > 0) ret = 0;
- return ret;
- }
-
- if (splitStr->slen == 1)
- return bsplitcb (str, splitStr->data[0], pos, cb, parm);
-
- buildCharField (&chrs, splitStr);
-
- p = pos;
- do {
- for (i=p; i < str->slen; i++) {
- if (testInCharField (&chrs, str->data[i])) break;
- }
- if ((ret = cb (parm, p, i - p)) < 0) return ret;
- p = i + 1;
- } while (p <= str->slen);
- return BSTR_OK;
-}
-
-/* int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos,
- * int (* cb) (void * parm, int ofs, int len), void * parm)
- *
- * Iterate the set of disjoint sequential substrings over str divided by the
- * substring splitStr. An empty splitStr causes the whole str to be
- * iterated once.
- *
- * Note: Non-destructive modification of str from within the cb function
- * while performing this split is not undefined. bsplitstrcb behaves in
- * sequential lock step with calls to cb. I.e., after returning from a cb
- * that return a non-negative integer, bsplitscb continues from the position
- * 1 character after the last detected split character and it will halt
- * immediately if the length of str falls below this point. However, if the
- * cb function destroys str, then it *must* return with a negative value,
- * otherwise bsplitscb will continue in an undefined manner.
- */
-int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos,
- int (* cb) (void * parm, int ofs, int len), void * parm) {
-int i, p, ret;
-
- if (cb == NULL || str == NULL || pos < 0 || pos > str->slen
- || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR;
-
- if (0 == splitStr->slen) {
- for (i=pos; i < str->slen; i++) {
- if ((ret = cb (parm, i, 1)) < 0) return ret;
- }
- return BSTR_OK;
- }
-
- if (splitStr->slen == 1)
- return bsplitcb (str, splitStr->data[0], pos, cb, parm);
-
- for (i=p=pos; i <= str->slen - splitStr->slen; i++) {
- if (0 == bstr__memcmp (splitStr->data, str->data + i, splitStr->slen)) {
- if ((ret = cb (parm, p, i - p)) < 0) return ret;
- i += splitStr->slen;
- p = i;
- }
- }
- if ((ret = cb (parm, p, str->slen - p)) < 0) return ret;
- return BSTR_OK;
-}
-
-struct genBstrList {
- bstring b;
- struct bstrList * bl;
-};
-
-static int bscb (void * parm, int ofs, int len) {
-struct genBstrList * g = (struct genBstrList *) parm;
- if (g->bl->qty >= g->bl->mlen) {
- int mlen = g->bl->mlen * 2;
- bstring * tbl;
-
- while (g->bl->qty >= mlen) {
- if (mlen < g->bl->mlen) return BSTR_ERR;
- mlen += mlen;
- }
-
- tbl = (bstring *) bstr__realloc (g->bl->entry, sizeof (bstring) * mlen);
- if (tbl == NULL) return BSTR_ERR;
-
- g->bl->entry = tbl;
- g->bl->mlen = mlen;
- }
-
- g->bl->entry[g->bl->qty] = bmidstr (g->b, ofs, len);
- g->bl->qty++;
- return BSTR_OK;
-}
-
-/* struct bstrList * bsplit (const_bstring str, unsigned char splitChar)
- *
- * Create an array of sequential substrings from str divided by the character
- * splitChar.
- */
-struct bstrList * bsplit (const_bstring str, unsigned char splitChar) {
-struct genBstrList g;
-
- if (str == NULL || str->data == NULL || str->slen < 0) return NULL;
-
- g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList));
- if (g.bl == NULL) return NULL;
- g.bl->mlen = 4;
- g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring));
- if (NULL == g.bl->entry) {
- bstr__free (g.bl);
- return NULL;
- }
-
- g.b = (bstring) str;
- g.bl->qty = 0;
- if (bsplitcb (str, splitChar, 0, bscb, &g) < 0) {
- bstrListDestroy (g.bl);
- return NULL;
- }
- return g.bl;
-}
-
-/* struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr)
- *
- * Create an array of sequential substrings from str divided by the entire
- * substring splitStr.
- */
-struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr) {
-struct genBstrList g;
-
- if (str == NULL || str->data == NULL || str->slen < 0) return NULL;
-
- g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList));
- if (g.bl == NULL) return NULL;
- g.bl->mlen = 4;
- g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring));
- if (NULL == g.bl->entry) {
- bstr__free (g.bl);
- return NULL;
- }
-
- g.b = (bstring) str;
- g.bl->qty = 0;
- if (bsplitstrcb (str, splitStr, 0, bscb, &g) < 0) {
- bstrListDestroy (g.bl);
- return NULL;
- }
- return g.bl;
-}
-
-/* struct bstrList * bsplits (const_bstring str, bstring splitStr)
- *
- * Create an array of sequential substrings from str divided by any of the
- * characters in splitStr. An empty splitStr causes a single entry bstrList
- * containing a copy of str to be returned.
- */
-struct bstrList * bsplits (const_bstring str, const_bstring splitStr) {
-struct genBstrList g;
-
- if ( str == NULL || str->slen < 0 || str->data == NULL ||
- splitStr == NULL || splitStr->slen < 0 || splitStr->data == NULL)
- return NULL;
-
- g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList));
- if (g.bl == NULL) return NULL;
- g.bl->mlen = 4;
- g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring));
- if (NULL == g.bl->entry) {
- bstr__free (g.bl);
- return NULL;
- }
- g.b = (bstring) str;
- g.bl->qty = 0;
-
- if (bsplitscb (str, splitStr, 0, bscb, &g) < 0) {
- bstrListDestroy (g.bl);
- return NULL;
- }
- return g.bl;
-}
-
-#if defined (__TURBOC__) && !defined (__BORLANDC__)
-# ifndef BSTRLIB_NOVSNP
-# define BSTRLIB_NOVSNP
-# endif
-#endif
-
-/* Give WATCOM C/C++, MSVC some latitude for their non-support of vsnprintf */
-#if defined(__WATCOMC__) || defined(_MSC_VER)
-#define exvsnprintf(r,b,n,f,a) {r = _vsnprintf (b,n,f,a);}
-#else
-#ifdef BSTRLIB_NOVSNP
-/* This is just a hack. If you are using a system without a vsnprintf, it is
- not recommended that bformat be used at all. */
-#define exvsnprintf(r,b,n,f,a) {vsprintf (b,f,a); r = -1;}
-#define START_VSNBUFF (256)
-#else
-
-#if defined(__GNUC__) && !defined(__APPLE__)
-/* Something is making gcc complain about this prototype not being here, so
- I've just gone ahead and put it in. */
-extern int vsnprintf (char *buf, size_t count, const char *format, va_list arg);
-#endif
-
-#define exvsnprintf(r,b,n,f,a) {r = vsnprintf (b,n,f,a);}
-#endif
-#endif
-
-#if !defined (BSTRLIB_NOVSNP)
-
-#ifndef START_VSNBUFF
-#define START_VSNBUFF (16)
-#endif
-
-/* On IRIX vsnprintf returns n-1 when the operation would overflow the target
- buffer, WATCOM and MSVC both return -1, while C99 requires that the
- returned value be exactly what the length would be if the buffer would be
- large enough. This leads to the idea that if the return value is larger
- than n, then changing n to the return value will reduce the number of
- iterations required. */
-
-/* int bformata (bstring b, const char * fmt, ...)
- *
- * After the first parameter, it takes the same parameters as printf (), but
- * rather than outputting results to stdio, it appends the results to
- * a bstring which contains what would have been output. Note that if there
- * is an early generation of a '\0' character, the bstring will be truncated
- * to this end point.
- */
-int bformata (bstring b, const char * fmt, ...) {
-va_list arglist;
-bstring buff;
-int n, r;
-
- if (b == NULL || fmt == NULL || b->data == NULL || b->mlen <= 0
- || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR;
-
- /* Since the length is not determinable beforehand, a search is
- performed using the truncating "vsnprintf" call (to avoid buffer
- overflows) on increasing potential sizes for the output result. */
-
- if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF;
- if (NULL == (buff = bfromcstralloc (n + 2, ""))) {
- n = 1;
- if (NULL == (buff = bfromcstralloc (n + 2, ""))) return BSTR_ERR;
- }
-
- for (;;) {
- va_start (arglist, fmt);
- exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist);
- va_end (arglist);
-
- buff->data[n] = (unsigned char) '\0';
- buff->slen = (int) (strlen) ((char *) buff->data);
-
- if (buff->slen < n) break;
-
- if (r > n) n = r; else n += n;
-
- if (BSTR_OK != balloc (buff, n + 2)) {
- bdestroy (buff);
- return BSTR_ERR;
- }
- }
-
- r = bconcat (b, buff);
- bdestroy (buff);
- return r;
-}
-
-/* int bassignformat (bstring b, const char * fmt, ...)
- *
- * After the first parameter, it takes the same parameters as printf (), but
- * rather than outputting results to stdio, it outputs the results to
- * the bstring parameter b. Note that if there is an early generation of a
- * '\0' character, the bstring will be truncated to this end point.
- */
-int bassignformat (bstring b, const char * fmt, ...) {
-va_list arglist;
-bstring buff;
-int n, r;
-
- if (b == NULL || fmt == NULL || b->data == NULL || b->mlen <= 0
- || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR;
-
- /* Since the length is not determinable beforehand, a search is
- performed using the truncating "vsnprintf" call (to avoid buffer
- overflows) on increasing potential sizes for the output result. */
-
- if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF;
- if (NULL == (buff = bfromcstralloc (n + 2, ""))) {
- n = 1;
- if (NULL == (buff = bfromcstralloc (n + 2, ""))) return BSTR_ERR;
- }
-
- for (;;) {
- va_start (arglist, fmt);
- exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist);
- va_end (arglist);
-
- buff->data[n] = (unsigned char) '\0';
- buff->slen = (int) (strlen) ((char *) buff->data);
-
- if (buff->slen < n) break;
-
- if (r > n) n = r; else n += n;
-
- if (BSTR_OK != balloc (buff, n + 2)) {
- bdestroy (buff);
- return BSTR_ERR;
- }
- }
-
- r = bassign (b, buff);
- bdestroy (buff);
- return r;
-}
-
-/* bstring bformat (const char * fmt, ...)
- *
- * Takes the same parameters as printf (), but rather than outputting results
- * to stdio, it forms a bstring which contains what would have been output.
- * Note that if there is an early generation of a '\0' character, the
- * bstring will be truncated to this end point.
- */
-bstring bformat (const char * fmt, ...) {
-va_list arglist;
-bstring buff;
-int n, r;
-
- if (fmt == NULL) return NULL;
-
- /* Since the length is not determinable beforehand, a search is
- performed using the truncating "vsnprintf" call (to avoid buffer
- overflows) on increasing potential sizes for the output result. */
-
- if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF;
- if (NULL == (buff = bfromcstralloc (n + 2, ""))) {
- n = 1;
- if (NULL == (buff = bfromcstralloc (n + 2, ""))) return NULL;
- }
-
- for (;;) {
- va_start (arglist, fmt);
- exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist);
- va_end (arglist);
-
- buff->data[n] = (unsigned char) '\0';
- buff->slen = (int) (strlen) ((char *) buff->data);
-
- if (buff->slen < n) break;
-
- if (r > n) n = r; else n += n;
-
- if (BSTR_OK != balloc (buff, n + 2)) {
- bdestroy (buff);
- return NULL;
- }
- }
-
- return buff;
-}
-
-/* int bvcformata (bstring b, int count, const char * fmt, va_list arglist)
- *
- * The bvcformata function formats data under control of the format control
- * string fmt and attempts to append the result to b. The fmt parameter is
- * the same as that of the printf function. The variable argument list is
- * replaced with arglist, which has been initialized by the va_start macro.
- * The size of the appended output is upper bounded by count. If the
- * required output exceeds count, the string b is not augmented with any
- * contents and a value below BSTR_ERR is returned. If a value below -count
- * is returned then it is recommended that the negative of this value be
- * used as an update to the count in a subsequent pass. On other errors,
- * such as running out of memory, parameter errors or numeric wrap around
- * BSTR_ERR is returned. BSTR_OK is returned when the output is successfully
- * generated and appended to b.
- *
- * Note: There is no sanity checking of arglist, and this function is
- * destructive of the contents of b from the b->slen point onward. If there
- * is an early generation of a '\0' character, the bstring will be truncated
- * to this end point.
- */
-int bvcformata (bstring b, int count, const char * fmt, va_list arg) {
-int n, r, l;
-
- if (b == NULL || fmt == NULL || count <= 0 || b->data == NULL
- || b->mlen <= 0 || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR;
-
- if (count > (n = b->slen + count) + 2) return BSTR_ERR;
- if (BSTR_OK != balloc (b, n + 2)) return BSTR_ERR;
-
- exvsnprintf (r, (char *) b->data + b->slen, count + 2, fmt, arg);
-
- /* Did the operation complete successfully within bounds? */
- for (l = b->slen; l <= n; l++) {
- if ('\0' == b->data[l]) {
- b->slen = l;
- return BSTR_OK;
- }
- }
-
- /* Abort, since the buffer was not large enough. The return value
- tries to help set what the retry length should be. */
-
- b->data[b->slen] = '\0';
- if (r > count + 1) { /* Does r specify a particular target length? */
- n = r;
- } else {
- n = count + count; /* If not, just double the size of count */
- if (count > n) n = INT_MAX;
- }
- n = -n;
-
- if (n > BSTR_ERR-1) n = BSTR_ERR-1;
- return n;
-}
-
-#endif
diff --git a/src/bstrlib.h b/src/bstrlib.h deleted file mode 100644 index c8fa694..0000000 --- a/src/bstrlib.h +++ /dev/null @@ -1,304 +0,0 @@ -/*
- * This source file is part of the bstring string library. This code was
- * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause
- * BSD open source license or GPL v2.0. Refer to the accompanying documentation
- * for details on usage and license.
- */
-
-/*
- * bstrlib.h
- *
- * This file is the header file for the core module for implementing the
- * bstring functions.
- */
-
-#ifndef BSTRLIB_INCLUDE
-#define BSTRLIB_INCLUDE
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdarg.h>
-#include <string.h>
-#include <limits.h>
-#include <ctype.h>
-
-#if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP)
-# if defined (__TURBOC__) && !defined (__BORLANDC__)
-# define BSTRLIB_NOVSNP
-# endif
-#endif
-
-#define BSTR_ERR (-1)
-#define BSTR_OK (0)
-#define BSTR_BS_BUFF_LENGTH_GET (0)
-
-typedef struct tagbstring * bstring;
-typedef const struct tagbstring * const_bstring;
-
-/* Copy functions */
-#define cstr2bstr bfromcstr
-extern bstring bfromcstr (const char * str);
-extern bstring bfromcstralloc (int mlen, const char * str);
-extern bstring blk2bstr (const void * blk, int len);
-extern char * bstr2cstr (const_bstring s, char z);
-extern int bcstrfree (char * s);
-extern bstring bstrcpy (const_bstring b1);
-extern int bassign (bstring a, const_bstring b);
-extern int bassignmidstr (bstring a, const_bstring b, int left, int len);
-extern int bassigncstr (bstring a, const char * str);
-extern int bassignblk (bstring a, const void * s, int len);
-
-/* Destroy function */
-extern int bdestroy (bstring b);
-
-/* Space allocation hinting functions */
-extern int balloc (bstring s, int len);
-extern int ballocmin (bstring b, int len);
-
-/* Substring extraction */
-extern bstring bmidstr (const_bstring b, int left, int len);
-
-/* Various standard manipulations */
-extern int bconcat (bstring b0, const_bstring b1);
-extern int bconchar (bstring b0, char c);
-extern int bcatcstr (bstring b, const char * s);
-extern int bcatblk (bstring b, const void * s, int len);
-extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill);
-extern int binsertch (bstring s1, int pos, int len, unsigned char fill);
-extern int breplace (bstring b1, int pos, int len, const_bstring b2, unsigned char fill);
-extern int bdelete (bstring s1, int pos, int len);
-extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill);
-extern int btrunc (bstring b, int n);
-
-/* Scan/search functions */
-extern int bstricmp (const_bstring b0, const_bstring b1);
-extern int bstrnicmp (const_bstring b0, const_bstring b1, int n);
-extern int biseqcaseless (const_bstring b0, const_bstring b1);
-extern int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len);
-extern int biseq (const_bstring b0, const_bstring b1);
-extern int bisstemeqblk (const_bstring b0, const void * blk, int len);
-extern int biseqcstr (const_bstring b, const char * s);
-extern int biseqcstrcaseless (const_bstring b, const char * s);
-extern int bstrcmp (const_bstring b0, const_bstring b1);
-extern int bstrncmp (const_bstring b0, const_bstring b1, int n);
-extern int binstr (const_bstring s1, int pos, const_bstring s2);
-extern int binstrr (const_bstring s1, int pos, const_bstring s2);
-extern int binstrcaseless (const_bstring s1, int pos, const_bstring s2);
-extern int binstrrcaseless (const_bstring s1, int pos, const_bstring s2);
-extern int bstrchrp (const_bstring b, int c, int pos);
-extern int bstrrchrp (const_bstring b, int c, int pos);
-#define bstrchr(b,c) bstrchrp ((b), (c), 0)
-#define bstrrchr(b,c) bstrrchrp ((b), (c), blength(b)-1)
-extern int binchr (const_bstring b0, int pos, const_bstring b1);
-extern int binchrr (const_bstring b0, int pos, const_bstring b1);
-extern int bninchr (const_bstring b0, int pos, const_bstring b1);
-extern int bninchrr (const_bstring b0, int pos, const_bstring b1);
-extern int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos);
-extern int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos);
-
-/* List of string container functions */
-struct bstrList {
- int qty, mlen;
- bstring * entry;
-};
-extern struct bstrList * bstrListCreate (void);
-extern int bstrListDestroy (struct bstrList * sl);
-extern int bstrListAlloc (struct bstrList * sl, int msz);
-extern int bstrListAllocMin (struct bstrList * sl, int msz);
-
-/* String split and join functions */
-extern struct bstrList * bsplit (const_bstring str, unsigned char splitChar);
-extern struct bstrList * bsplits (const_bstring str, const_bstring splitStr);
-extern struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr);
-extern bstring bjoin (const struct bstrList * bl, const_bstring sep);
-extern int bsplitcb (const_bstring str, unsigned char splitChar, int pos,
- int (* cb) (void * parm, int ofs, int len), void * parm);
-extern int bsplitscb (const_bstring str, const_bstring splitStr, int pos,
- int (* cb) (void * parm, int ofs, int len), void * parm);
-extern int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos,
- int (* cb) (void * parm, int ofs, int len), void * parm);
-
-/* Miscellaneous functions */
-extern int bpattern (bstring b, int len);
-extern int btoupper (bstring b);
-extern int btolower (bstring b);
-extern int bltrimws (bstring b);
-extern int brtrimws (bstring b);
-extern int btrimws (bstring b);
-
-/* <*>printf format functions */
-#if !defined (BSTRLIB_NOVSNP)
-extern bstring bformat (const char * fmt, ...);
-extern int bformata (bstring b, const char * fmt, ...);
-extern int bassignformat (bstring b, const char * fmt, ...);
-extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist);
-
-#define bvformata(ret, b, fmt, lastarg) { \
-bstring bstrtmp_b = (b); \
-const char * bstrtmp_fmt = (fmt); \
-int bstrtmp_r = BSTR_ERR, bstrtmp_sz = 16; \
- for (;;) { \
- va_list bstrtmp_arglist; \
- va_start (bstrtmp_arglist, lastarg); \
- bstrtmp_r = bvcformata (bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, bstrtmp_arglist); \
- va_end (bstrtmp_arglist); \
- if (bstrtmp_r >= 0) { /* Everything went ok */ \
- bstrtmp_r = BSTR_OK; \
- break; \
- } else if (-bstrtmp_r <= bstrtmp_sz) { /* A real error? */ \
- bstrtmp_r = BSTR_ERR; \
- break; \
- } \
- bstrtmp_sz = -bstrtmp_r; /* Doubled or target size */ \
- } \
- ret = bstrtmp_r; \
-}
-
-#endif
-
-typedef int (*bNgetc) (void *parm);
-typedef size_t (* bNread) (void *buff, size_t elsize, size_t nelem, void *parm);
-
-/* Input functions */
-extern bstring bgets (bNgetc getcPtr, void * parm, char terminator);
-extern bstring bread (bNread readPtr, void * parm);
-extern int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator);
-extern int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator);
-extern int breada (bstring b, bNread readPtr, void * parm);
-
-/* Stream functions */
-extern struct bStream * bsopen (bNread readPtr, void * parm);
-extern void * bsclose (struct bStream * s);
-extern int bsbufflength (struct bStream * s, int sz);
-extern int bsreadln (bstring b, struct bStream * s, char terminator);
-extern int bsreadlns (bstring r, struct bStream * s, const_bstring term);
-extern int bsread (bstring b, struct bStream * s, int n);
-extern int bsreadlna (bstring b, struct bStream * s, char terminator);
-extern int bsreadlnsa (bstring r, struct bStream * s, const_bstring term);
-extern int bsreada (bstring b, struct bStream * s, int n);
-extern int bsunread (struct bStream * s, const_bstring b);
-extern int bspeek (bstring r, const struct bStream * s);
-extern int bssplitscb (struct bStream * s, const_bstring splitStr,
- int (* cb) (void * parm, int ofs, const_bstring entry), void * parm);
-extern int bssplitstrcb (struct bStream * s, const_bstring splitStr,
- int (* cb) (void * parm, int ofs, const_bstring entry), void * parm);
-extern int bseof (const struct bStream * s);
-
-struct tagbstring {
- int mlen;
- int slen;
- unsigned char * data;
-};
-
-/* Accessor macros */
-#define blengthe(b, e) (((b) == (void *)0 || (b)->slen < 0) ? (int)(e) : ((b)->slen))
-#define blength(b) (blengthe ((b), 0))
-#define bdataofse(b, o, e) (((b) == (void *)0 || (b)->data == (void*)0) ? (char *)(e) : ((char *)(b)->data) + (o))
-#define bdataofs(b, o) (bdataofse ((b), (o), (void *)0))
-#define bdatae(b, e) (bdataofse (b, 0, e))
-#define bdata(b) (bdataofs (b, 0))
-#define bchare(b, p, e) ((((unsigned)(p)) < (unsigned)blength(b)) ? ((b)->data[(p)]) : (e))
-#define bchar(b, p) bchare ((b), (p), '\0')
-
-/* Static constant string initialization macro */
-#define bsStaticMlen(q,m) {(m), (int) sizeof(q)-1, (unsigned char *) ("" q "")}
-#if defined(_MSC_VER)
-/* There are many versions of MSVC which emit __LINE__ as a non-constant. */
-# define bsStatic(q) bsStaticMlen(q,-32)
-#endif
-#ifndef bsStatic
-# define bsStatic(q) bsStaticMlen(q,-__LINE__)
-#endif
-
-/* Static constant block parameter pair */
-#define bsStaticBlkParms(q) ((void *)("" q "")), ((int) sizeof(q)-1)
-
-/* Reference building macros */
-#define cstr2tbstr btfromcstr
-#define btfromcstr(t,s) { \
- (t).data = (unsigned char *) (s); \
- (t).slen = ((t).data) ? ((int) (strlen) ((char *)(t).data)) : 0; \
- (t).mlen = -1; \
-}
-#define blk2tbstr(t,s,l) { \
- (t).data = (unsigned char *) (s); \
- (t).slen = l; \
- (t).mlen = -1; \
-}
-#define btfromblk(t,s,l) blk2tbstr(t,s,l)
-#define bmid2tbstr(t,b,p,l) { \
- const_bstring bstrtmp_s = (b); \
- if (bstrtmp_s && bstrtmp_s->data && bstrtmp_s->slen >= 0) { \
- int bstrtmp_left = (p); \
- int bstrtmp_len = (l); \
- if (bstrtmp_left < 0) { \
- bstrtmp_len += bstrtmp_left; \
- bstrtmp_left = 0; \
- } \
- if (bstrtmp_len > bstrtmp_s->slen - bstrtmp_left) \
- bstrtmp_len = bstrtmp_s->slen - bstrtmp_left; \
- if (bstrtmp_len <= 0) { \
- (t).data = (unsigned char *)""; \
- (t).slen = 0; \
- } else { \
- (t).data = bstrtmp_s->data + bstrtmp_left; \
- (t).slen = bstrtmp_len; \
- } \
- } else { \
- (t).data = (unsigned char *)""; \
- (t).slen = 0; \
- } \
- (t).mlen = -__LINE__; \
-}
-#define btfromblkltrimws(t,s,l) { \
- int bstrtmp_idx = 0, bstrtmp_len = (l); \
- unsigned char * bstrtmp_s = (s); \
- if (bstrtmp_s && bstrtmp_len >= 0) { \
- for (; bstrtmp_idx < bstrtmp_len; bstrtmp_idx++) { \
- if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \
- } \
- } \
- (t).data = bstrtmp_s + bstrtmp_idx; \
- (t).slen = bstrtmp_len - bstrtmp_idx; \
- (t).mlen = -__LINE__; \
-}
-#define btfromblkrtrimws(t,s,l) { \
- int bstrtmp_len = (l) - 1; \
- unsigned char * bstrtmp_s = (s); \
- if (bstrtmp_s && bstrtmp_len >= 0) { \
- for (; bstrtmp_len >= 0; bstrtmp_len--) { \
- if (!isspace (bstrtmp_s[bstrtmp_len])) break; \
- } \
- } \
- (t).data = bstrtmp_s; \
- (t).slen = bstrtmp_len + 1; \
- (t).mlen = -__LINE__; \
-}
-#define btfromblktrimws(t,s,l) { \
- int bstrtmp_idx = 0, bstrtmp_len = (l) - 1; \
- unsigned char * bstrtmp_s = (s); \
- if (bstrtmp_s && bstrtmp_len >= 0) { \
- for (; bstrtmp_idx <= bstrtmp_len; bstrtmp_idx++) { \
- if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \
- } \
- for (; bstrtmp_len >= bstrtmp_idx; bstrtmp_len--) { \
- if (!isspace (bstrtmp_s[bstrtmp_len])) break; \
- } \
- } \
- (t).data = bstrtmp_s + bstrtmp_idx; \
- (t).slen = bstrtmp_len + 1 - bstrtmp_idx; \
- (t).mlen = -__LINE__; \
-}
-
-/* Write protection macros */
-#define bwriteprotect(t) { if ((t).mlen >= 0) (t).mlen = -1; }
-#define bwriteallow(t) { if ((t).mlen == -1) (t).mlen = (t).slen + ((t).slen == 0); }
-#define biswriteprotected(t) ((t).mlen <= 0)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/buffer.c b/src/buffer.c new file mode 100644 index 0000000..7c2b86b --- /dev/null +++ b/src/buffer.c @@ -0,0 +1,354 @@ +#include <stdarg.h> +#include <ctype.h> +#include <string.h> +#include <assert.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/param.h> + +#include "buffer.h" + +/* Used as default value for strbuf->ptr so that people can always + * assume ptr is non-NULL and zero terminated even for new strbufs. + */ +unsigned char strbuf__initbuf[1]; +unsigned char strbuf__oom[1]; + +#define ENSURE_SIZE(b, d) \ + if ((d) > buf->asize && strbuf_grow(b, (d)) < 0)\ + return -1; + +void strbuf_init(strbuf *buf, int initial_size) +{ + buf->asize = 0; + buf->size = 0; + buf->ptr = strbuf__initbuf; + + if (initial_size) + strbuf_grow(buf, initial_size); +} + +int strbuf_try_grow(strbuf *buf, int target_size, bool mark_oom) +{ + unsigned char *new_ptr; + int new_size; + + if (buf->ptr == strbuf__oom) + return -1; + + if (target_size <= buf->asize) + return 0; + + if (buf->asize == 0) { + new_size = target_size; + new_ptr = NULL; + } else { + new_size = buf->asize; + new_ptr = buf->ptr; + } + + /* grow the buffer size by 1.5, until it's big enough + * to fit our target size */ + while (new_size < target_size) + new_size = (new_size << 1) - (new_size >> 1); + + /* round allocation up to multiple of 8 */ + new_size = (new_size + 7) & ~7; + + new_ptr = realloc(new_ptr, new_size); + + if (!new_ptr) { + if (mark_oom) + buf->ptr = strbuf__oom; + return -1; + } + + buf->asize = new_size; + buf->ptr = new_ptr; + + /* truncate the existing buffer size if necessary */ + if (buf->size >= buf->asize) + buf->size = buf->asize - 1; + buf->ptr[buf->size] = '\0'; + + return 0; +} + +void strbuf_free(strbuf *buf) +{ + if (!buf) return; + + if (buf->ptr != strbuf__initbuf && buf->ptr != strbuf__oom) + free(buf->ptr); + + strbuf_init(buf, 0); +} + +void strbuf_clear(strbuf *buf) +{ + buf->size = 0; + + if (buf->asize > 0) + buf->ptr[0] = '\0'; +} + +int strbuf_set(strbuf *buf, const unsigned char *data, int len) +{ + if (len <= 0 || data == NULL) { + strbuf_clear(buf); + } else { + if (data != buf->ptr) { + ENSURE_SIZE(buf, len + 1); + memmove(buf->ptr, data, len); + } + buf->size = len; + buf->ptr[buf->size] = '\0'; + } + return 0; +} + +int strbuf_sets(strbuf *buf, const char *string) +{ + return strbuf_set(buf, + (const unsigned char *)string, + string ? strlen(string) : 0); +} + +int strbuf_putc(strbuf *buf, int c) +{ + ENSURE_SIZE(buf, buf->size + 2); + buf->ptr[buf->size++] = c; + buf->ptr[buf->size] = '\0'; + return 0; +} + +int strbuf_put(strbuf *buf, const unsigned char *data, int len) +{ + if (len <= 0) + return 0; + + ENSURE_SIZE(buf, buf->size + len + 1); + memmove(buf->ptr + buf->size, data, len); + buf->size += len; + buf->ptr[buf->size] = '\0'; + return 0; +} + +int strbuf_puts(strbuf *buf, const char *string) +{ + return strbuf_put(buf, (const unsigned char *)string, strlen(string)); +} + +int strbuf_vprintf(strbuf *buf, const char *format, va_list ap) +{ + const int expected_size = buf->size + (strlen(format) * 2); + int len; + + ENSURE_SIZE(buf, expected_size); + + while (1) { + va_list args; + va_copy(args, ap); + + len = vsnprintf( + (char *)buf->ptr + buf->size, + buf->asize - buf->size, + format, args + ); + + if (len < 0) { + free(buf->ptr); + buf->ptr = strbuf__oom; + return -1; + } + + if (len + 1 <= buf->asize - buf->size) { + buf->size += len; + break; + } + + ENSURE_SIZE(buf, buf->size + len + 1); + } + + return 0; +} + +int strbuf_printf(strbuf *buf, const char *format, ...) +{ + int r; + va_list ap; + + va_start(ap, format); + r = strbuf_vprintf(buf, format, ap); + va_end(ap); + + return r; +} + +void strbuf_copy_cstr(char *data, int datasize, const strbuf *buf) +{ + int copylen; + + assert(data && datasize && buf); + + data[0] = '\0'; + + if (buf->size == 0 || buf->asize <= 0) + return; + + copylen = buf->size; + if (copylen > datasize - 1) + copylen = datasize - 1; + memmove(data, buf->ptr, copylen); + data[copylen] = '\0'; +} + +void strbuf_swap(strbuf *buf_a, strbuf *buf_b) +{ + strbuf t = *buf_a; + *buf_a = *buf_b; + *buf_b = t; +} + +unsigned char *strbuf_detach(strbuf *buf) +{ + unsigned char *data = buf->ptr; + + if (buf->asize == 0 || buf->ptr == strbuf__oom) { + /* return an empty string */ + return calloc(1, 1); + } + + strbuf_init(buf, 0); + return data; +} + +void strbuf_attach(strbuf *buf, unsigned char *ptr, int asize) +{ + strbuf_free(buf); + + if (ptr) { + buf->ptr = ptr; + buf->size = strlen((char *)ptr); + if (asize) + buf->asize = (asize < buf->size) ? buf->size + 1 : asize; + else /* pass 0 to fall back on strlen + 1 */ + buf->asize = buf->size + 1; + } else { + strbuf_grow(buf, asize); + } +} + +int strbuf_cmp(const strbuf *a, const strbuf *b) +{ + int result = memcmp(a->ptr, b->ptr, MIN(a->size, b->size)); + return (result != 0) ? result : + (a->size < b->size) ? -1 : (a->size > b->size) ? 1 : 0; +} + +int strbuf_strchr(const strbuf *buf, int c, int pos) +{ + const unsigned char *p = memchr(buf->ptr + pos, c, buf->size - pos); + if (!p) + return -1; + + return (int)(p - (const unsigned char *)buf->ptr); +} + +int strbuf_strrchr(const strbuf *buf, int c, int pos) +{ + int i; + + for (i = pos; i >= 0; i--) { + if (buf->ptr[i] == (unsigned char) c) + return i; + } + + return -1; +} + +void strbuf_truncate(strbuf *buf, int len) +{ + if (len < buf->size) { + buf->size = len; + buf->ptr[buf->size] = '\0'; + } +} + +void strbuf_drop(strbuf *buf, int n) +{ + if (n > 0) { + buf->size = buf->size - n; + if (buf->size) + memmove(buf->ptr, buf->ptr + n, buf->size); + + buf->ptr[buf->size] = '\0'; + } +} + +void strbuf_trim(strbuf *buf) +{ + int i = 0; + + if (!buf->size) + return; + + while (i < buf->size && isspace(buf->ptr[i])) + i++; + + strbuf_drop(buf, i); + + /* rtrim */ + while (buf->size > 0) { + if (!isspace(buf->ptr[buf->size - 1])) + break; + + buf->size--; + } + + buf->ptr[buf->size] = '\0'; +} + +// Destructively modify string, collapsing consecutive +// space and newline characters into a single space. +void strbuf_normalize_whitespace(strbuf *s) +{ + bool last_char_was_space = false; + int r, w; + + for (r = 0, w = 0; r < s->size; ++r) { + switch (s->ptr[r]) { + case ' ': + case '\n': + if (last_char_was_space) + break; + + s->ptr[w++] = ' '; + last_char_was_space = true; + break; + + default: + s->ptr[w++] = s->ptr[r]; + last_char_was_space = false; + } + } + + strbuf_truncate(s, w); +} + +// Destructively unescape a string: remove backslashes before punctuation chars. +extern void strbuf_unescape(strbuf *buf) +{ + int r, w; + + for (r = 0, w = 0; r < buf->size; ++r) { + if (buf->ptr[r] == '\\' && ispunct(buf->ptr[r + 1])) + continue; + + buf->ptr[w++] = buf->ptr[r]; + } + + strbuf_truncate(buf, w); +} + diff --git a/src/buffer.h b/src/buffer.h new file mode 100644 index 0000000..1bc1eee --- /dev/null +++ b/src/buffer.h @@ -0,0 +1,114 @@ +#ifndef INCLUDE_buffer_h__ +#define INCLUDE_buffer_h__ + +#include <stdbool.h> +#include <stddef.h> +#include <stdarg.h> +#include <sys/types.h> + +typedef struct { + unsigned char *ptr; + int asize, size; +} strbuf; + +extern unsigned char strbuf__initbuf[]; +extern unsigned char strbuf__oom[]; + +#define GH_BUF_INIT { strbuf__initbuf, 0, 0 } + +/** + * Initialize a strbuf structure. + * + * For the cases where GH_BUF_INIT cannot be used to do static + * initialization. + */ +extern void strbuf_init(strbuf *buf, int initial_size); + +/** + * Attempt to grow the buffer to hold at least `target_size` bytes. + * + * If the allocation fails, this will return an error. If mark_oom is true, + * this will mark the buffer as invalid for future operations; if false, + * existing buffer content will be preserved, but calling code must handle + * that buffer was not expanded. + */ +extern int strbuf_try_grow(strbuf *buf, int target_size, bool mark_oom); + +/** + * Grow the buffer to hold at least `target_size` bytes. + * + * If the allocation fails, this will return an error and the buffer will be + * marked as invalid for future operations, invaliding contents. + * + * @return 0 on success or -1 on failure + */ +static inline int strbuf_grow(strbuf *buf, int target_size) +{ + return strbuf_try_grow(buf, target_size, true); +} + +extern void strbuf_free(strbuf *buf); +extern void strbuf_swap(strbuf *buf_a, strbuf *buf_b); + +/** + * Test if there have been any reallocation failures with this strbuf. + * + * Any function that writes to a strbuf can fail due to memory allocation + * issues. If one fails, the strbuf will be marked with an OOM error and + * further calls to modify the buffer will fail. Check strbuf_oom() at the + * end of your sequence and it will be true if you ran out of memory at any + * point with that buffer. + * + * @return false if no error, true if allocation error + */ +static inline bool strbuf_oom(const strbuf *buf) +{ + return (buf->ptr == strbuf__oom); +} + + +static inline size_t strbuf_len(const strbuf *buf) +{ + return buf->size; +} + +extern int strbuf_cmp(const strbuf *a, const strbuf *b); + +extern void strbuf_attach(strbuf *buf, unsigned char *ptr, int asize); +extern unsigned char *strbuf_detach(strbuf *buf); +extern void strbuf_copy_cstr(char *data, int datasize, const strbuf *buf); + +static inline const char *strbuf_cstr(const strbuf *buf) +{ + return (char *)buf->ptr; +} + +#define strbuf_at(buf, n) ((buf)->ptr[n]) + +/* + * Functions below that return int value error codes will return 0 on + * success or -1 on failure (which generally means an allocation failed). + * Using a strbuf where the allocation has failed with result in -1 from + * all further calls using that buffer. As a result, you can ignore the + * return code of these functions and call them in a series then just call + * strbuf_oom at the end. + */ +extern int strbuf_set(strbuf *buf, const unsigned char *data, int len); +extern int strbuf_sets(strbuf *buf, const char *string); +extern int strbuf_putc(strbuf *buf, int c); +extern int strbuf_put(strbuf *buf, const unsigned char *data, int len); +extern int strbuf_puts(strbuf *buf, const char *string); +extern int strbuf_printf(strbuf *buf, const char *format, ...) + __attribute__((format (printf, 2, 3))); +extern int strbuf_vprintf(strbuf *buf, const char *format, va_list ap); +extern void strbuf_clear(strbuf *buf); + +int strbuf_strchr(const strbuf *buf, int c, int pos); +int strbuf_strrchr(const strbuf *buf, int c, int pos); +void strbuf_drop(strbuf *buf, int n); +void strbuf_truncate(strbuf *buf, int len); +void strbuf_trim(strbuf *buf); +void strbuf_normalize_whitespace(strbuf *s); +void strbuf_unescape(strbuf *s); + +#endif diff --git a/src/case_fold_switch.c b/src/case_fold_switch.inc index 70fdd75..70fdd75 100644 --- a/src/case_fold_switch.c +++ b/src/case_fold_switch.inc diff --git a/src/casefold.c b/src/casefold.c deleted file mode 100644 index 33f18aa..0000000 --- a/src/casefold.c +++ /dev/null @@ -1,2699 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> - - - switch c { - case 0x0041: - bufpush(0x0061); - break; - case 0x0042: - bufpush(0x0062); - break; - case 0x0043: - bufpush(0x0063); - break; - case 0x0044: - bufpush(0x0064); - break; - case 0x0045: - bufpush(0x0065); - break; - case 0x0046: - bufpush(0x0066); - break; - case 0x0047: - bufpush(0x0067); - break; - case 0x0048: - bufpush(0x0068); - break; - case 0x0049: - bufpush(0x0069); - break; - case 0x0049: - bufpush(0x0131); - break; - case 0x004A: - bufpush(0x006A); - break; - case 0x004B: - bufpush(0x006B); - break; - case 0x004C: - bufpush(0x006C); - break; - case 0x004D: - bufpush(0x006D); - break; - case 0x004E: - bufpush(0x006E); - break; - case 0x004F: - bufpush(0x006F); - break; - case 0x0050: - bufpush(0x0070); - break; - case 0x0051: - bufpush(0x0071); - break; - case 0x0052: - bufpush(0x0072); - break; - case 0x0053: - bufpush(0x0073); - break; - case 0x0054: - bufpush(0x0074); - break; - case 0x0055: - bufpush(0x0075); - break; - case 0x0056: - bufpush(0x0076); - break; - case 0x0057: - bufpush(0x0077); - break; - case 0x0058: - bufpush(0x0078); - break; - case 0x0059: - bufpush(0x0079); - break; - case 0x005A: - bufpush(0x007A); - break; - case 0x00B5: - bufpush(0x03BC); - break; - case 0x00C0: - bufpush(0x00E0); - break; - case 0x00C1: - bufpush(0x00E1); - break; - case 0x00C2: - bufpush(0x00E2); - break; - case 0x00C3: - bufpush(0x00E3); - break; - case 0x00C4: - bufpush(0x00E4); - break; - case 0x00C5: - bufpush(0x00E5); - break; - case 0x00C6: - bufpush(0x00E6); - break; - case 0x00C7: - bufpush(0x00E7); - break; - case 0x00C8: - bufpush(0x00E8); - break; - case 0x00C9: - bufpush(0x00E9); - break; - case 0x00CA: - bufpush(0x00EA); - break; - case 0x00CB: - bufpush(0x00EB); - break; - case 0x00CC: - bufpush(0x00EC); - break; - case 0x00CD: - bufpush(0x00ED); - break; - case 0x00CE: - bufpush(0x00EE); - break; - case 0x00CF: - bufpush(0x00EF); - break; - case 0x00D0: - bufpush(0x00F0); - break; - case 0x00D1: - bufpush(0x00F1); - break; - case 0x00D2: - bufpush(0x00F2); - break; - case 0x00D3: - bufpush(0x00F3); - break; - case 0x00D4: - bufpush(0x00F4); - break; - case 0x00D5: - bufpush(0x00F5); - break; - case 0x00D6: - bufpush(0x00F6); - break; - case 0x00D8: - bufpush(0x00F8); - break; - case 0x00D9: - bufpush(0x00F9); - break; - case 0x00DA: - bufpush(0x00FA); - break; - case 0x00DB: - bufpush(0x00FB); - break; - case 0x00DC: - bufpush(0x00FC); - break; - case 0x00DD: - bufpush(0x00FD); - break; - case 0x00DE: - bufpush(0x00FE); - break; - case 0x00DF: - bufpush(0x0073); - bufpush(0x0073); - break; - case 0x0100: - bufpush(0x0101); - break; - case 0x0102: - bufpush(0x0103); - break; - case 0x0104: - bufpush(0x0105); - break; - case 0x0106: - bufpush(0x0107); - break; - case 0x0108: - bufpush(0x0109); - break; - case 0x010A: - bufpush(0x010B); - break; - case 0x010C: - bufpush(0x010D); - break; - case 0x010E: - bufpush(0x010F); - break; - case 0x0110: - bufpush(0x0111); - break; - case 0x0112: - bufpush(0x0113); - break; - case 0x0114: - bufpush(0x0115); - break; - case 0x0116: - bufpush(0x0117); - break; - case 0x0118: - bufpush(0x0119); - break; - case 0x011A: - bufpush(0x011B); - break; - case 0x011C: - bufpush(0x011D); - break; - case 0x011E: - bufpush(0x011F); - break; - case 0x0120: - bufpush(0x0121); - break; - case 0x0122: - bufpush(0x0123); - break; - case 0x0124: - bufpush(0x0125); - break; - case 0x0126: - bufpush(0x0127); - break; - case 0x0128: - bufpush(0x0129); - break; - case 0x012A: - bufpush(0x012B); - break; - case 0x012C: - bufpush(0x012D); - break; - case 0x012E: - bufpush(0x012F); - break; - case 0x0130: - bufpush(0x0069); - bufpush(0x0307); - break; - case 0x0130: - bufpush(0x0069); - break; - case 0x0132: - bufpush(0x0133); - break; - case 0x0134: - bufpush(0x0135); - break; - case 0x0136: - bufpush(0x0137); - break; - case 0x0139: - bufpush(0x013A); - break; - case 0x013B: - bufpush(0x013C); - break; - case 0x013D: - bufpush(0x013E); - break; - case 0x013F: - bufpush(0x0140); - break; - case 0x0141: - bufpush(0x0142); - break; - case 0x0143: - bufpush(0x0144); - break; - case 0x0145: - bufpush(0x0146); - break; - case 0x0147: - bufpush(0x0148); - break; - case 0x0149: - bufpush(0x02BC); - bufpush(0x006E); - break; - case 0x014A: - bufpush(0x014B); - break; - case 0x014C: - bufpush(0x014D); - break; - case 0x014E: - bufpush(0x014F); - break; - case 0x0150: - bufpush(0x0151); - break; - case 0x0152: - bufpush(0x0153); - break; - case 0x0154: - bufpush(0x0155); - break; - case 0x0156: - bufpush(0x0157); - break; - case 0x0158: - bufpush(0x0159); - break; - case 0x015A: - bufpush(0x015B); - break; - case 0x015C: - bufpush(0x015D); - break; - case 0x015E: - bufpush(0x015F); - break; - case 0x0160: - bufpush(0x0161); - break; - case 0x0162: - bufpush(0x0163); - break; - case 0x0164: - bufpush(0x0165); - break; - case 0x0166: - bufpush(0x0167); - break; - case 0x0168: - bufpush(0x0169); - break; - case 0x016A: - bufpush(0x016B); - break; - case 0x016C: - bufpush(0x016D); - break; - case 0x016E: - bufpush(0x016F); - break; - case 0x0170: - bufpush(0x0171); - break; - case 0x0172: - bufpush(0x0173); - break; - case 0x0174: - bufpush(0x0175); - break; - case 0x0176: - bufpush(0x0177); - break; - case 0x0178: - bufpush(0x00FF); - break; - case 0x0179: - bufpush(0x017A); - break; - case 0x017B: - bufpush(0x017C); - break; - case 0x017D: - bufpush(0x017E); - break; - case 0x017F: - bufpush(0x0073); - break; - case 0x0181: - bufpush(0x0253); - break; - case 0x0182: - bufpush(0x0183); - break; - case 0x0184: - bufpush(0x0185); - break; - case 0x0186: - bufpush(0x0254); - break; - case 0x0187: - bufpush(0x0188); - break; - case 0x0189: - bufpush(0x0256); - break; - case 0x018A: - bufpush(0x0257); - break; - case 0x018B: - bufpush(0x018C); - break; - case 0x018E: - bufpush(0x01DD); - break; - case 0x018F: - bufpush(0x0259); - break; - case 0x0190: - bufpush(0x025B); - break; - case 0x0191: - bufpush(0x0192); - break; - case 0x0193: - bufpush(0x0260); - break; - case 0x0194: - bufpush(0x0263); - break; - case 0x0196: - bufpush(0x0269); - break; - case 0x0197: - bufpush(0x0268); - break; - case 0x0198: - bufpush(0x0199); - break; - case 0x019C: - bufpush(0x026F); - break; - case 0x019D: - bufpush(0x0272); - break; - case 0x019F: - bufpush(0x0275); - break; - case 0x01A0: - bufpush(0x01A1); - break; - case 0x01A2: - bufpush(0x01A3); - break; - case 0x01A4: - bufpush(0x01A5); - break; - case 0x01A6: - bufpush(0x0280); - break; - case 0x01A7: - bufpush(0x01A8); - break; - case 0x01A9: - bufpush(0x0283); - break; - case 0x01AC: - bufpush(0x01AD); - break; - case 0x01AE: - bufpush(0x0288); - break; - case 0x01AF: - bufpush(0x01B0); - break; - case 0x01B1: - bufpush(0x028A); - break; - case 0x01B2: - bufpush(0x028B); - break; - case 0x01B3: - bufpush(0x01B4); - break; - case 0x01B5: - bufpush(0x01B6); - break; - case 0x01B7: - bufpush(0x0292); - break; - case 0x01B8: - bufpush(0x01B9); - break; - case 0x01BC: - bufpush(0x01BD); - break; - case 0x01C4: - bufpush(0x01C6); - break; - case 0x01C5: - bufpush(0x01C6); - break; - case 0x01C7: - bufpush(0x01C9); - break; - case 0x01C8: - bufpush(0x01C9); - break; - case 0x01CA: - bufpush(0x01CC); - break; - case 0x01CB: - bufpush(0x01CC); - break; - case 0x01CD: - bufpush(0x01CE); - break; - case 0x01CF: - bufpush(0x01D0); - break; - case 0x01D1: - bufpush(0x01D2); - break; - case 0x01D3: - bufpush(0x01D4); - break; - case 0x01D5: - bufpush(0x01D6); - break; - case 0x01D7: - bufpush(0x01D8); - break; - case 0x01D9: - bufpush(0x01DA); - break; - case 0x01DB: - bufpush(0x01DC); - break; - case 0x01DE: - bufpush(0x01DF); - break; - case 0x01E0: - bufpush(0x01E1); - break; - case 0x01E2: - bufpush(0x01E3); - break; - case 0x01E4: - bufpush(0x01E5); - break; - case 0x01E6: - bufpush(0x01E7); - break; - case 0x01E8: - bufpush(0x01E9); - break; - case 0x01EA: - bufpush(0x01EB); - break; - case 0x01EC: - bufpush(0x01ED); - break; - case 0x01EE: - bufpush(0x01EF); - break; - case 0x01F0: - bufpush(0x006A); - bufpush(0x030C); - break; - case 0x01F1: - bufpush(0x01F3); - break; - case 0x01F2: - bufpush(0x01F3); - break; - case 0x01F4: - bufpush(0x01F5); - break; - case 0x01F6: - bufpush(0x0195); - break; - case 0x01F7: - bufpush(0x01BF); - break; - case 0x01F8: - bufpush(0x01F9); - break; - case 0x01FA: - bufpush(0x01FB); - break; - case 0x01FC: - bufpush(0x01FD); - break; - case 0x01FE: - bufpush(0x01FF); - break; - case 0x0200: - bufpush(0x0201); - break; - case 0x0202: - bufpush(0x0203); - break; - case 0x0204: - bufpush(0x0205); - break; - case 0x0206: - bufpush(0x0207); - break; - case 0x0208: - bufpush(0x0209); - break; - case 0x020A: - bufpush(0x020B); - break; - case 0x020C: - bufpush(0x020D); - break; - case 0x020E: - bufpush(0x020F); - break; - case 0x0210: - bufpush(0x0211); - break; - case 0x0212: - bufpush(0x0213); - break; - case 0x0214: - bufpush(0x0215); - break; - case 0x0216: - bufpush(0x0217); - break; - case 0x0218: - bufpush(0x0219); - break; - case 0x021A: - bufpush(0x021B); - break; - case 0x021C: - bufpush(0x021D); - break; - case 0x021E: - bufpush(0x021F); - break; - case 0x0220: - bufpush(0x019E); - break; - case 0x0222: - bufpush(0x0223); - break; - case 0x0224: - bufpush(0x0225); - break; - case 0x0226: - bufpush(0x0227); - break; - case 0x0228: - bufpush(0x0229); - break; - case 0x022A: - bufpush(0x022B); - break; - case 0x022C: - bufpush(0x022D); - break; - case 0x022E: - bufpush(0x022F); - break; - case 0x0230: - bufpush(0x0231); - break; - case 0x0232: - bufpush(0x0233); - break; - case 0x0345: - bufpush(0x03B9); - break; - case 0x0386: - bufpush(0x03AC); - break; - case 0x0388: - bufpush(0x03AD); - break; - case 0x0389: - bufpush(0x03AE); - break; - case 0x038A: - bufpush(0x03AF); - break; - case 0x038C: - bufpush(0x03CC); - break; - case 0x038E: - bufpush(0x03CD); - break; - case 0x038F: - bufpush(0x03CE); - break; - case 0x0390: - bufpush(0x03B9); - bufpush(0x0308); - bufpush(0x0301); - break; - case 0x0391: - bufpush(0x03B1); - break; - case 0x0392: - bufpush(0x03B2); - break; - case 0x0393: - bufpush(0x03B3); - break; - case 0x0394: - bufpush(0x03B4); - break; - case 0x0395: - bufpush(0x03B5); - break; - case 0x0396: - bufpush(0x03B6); - break; - case 0x0397: - bufpush(0x03B7); - break; - case 0x0398: - bufpush(0x03B8); - break; - case 0x0399: - bufpush(0x03B9); - break; - case 0x039A: - bufpush(0x03BA); - break; - case 0x039B: - bufpush(0x03BB); - break; - case 0x039C: - bufpush(0x03BC); - break; - case 0x039D: - bufpush(0x03BD); - break; - case 0x039E: - bufpush(0x03BE); - break; - case 0x039F: - bufpush(0x03BF); - break; - case 0x03A0: - bufpush(0x03C0); - break; - case 0x03A1: - bufpush(0x03C1); - break; - case 0x03A3: - bufpush(0x03C3); - break; - case 0x03A4: - bufpush(0x03C4); - break; - case 0x03A5: - bufpush(0x03C5); - break; - case 0x03A6: - bufpush(0x03C6); - break; - case 0x03A7: - bufpush(0x03C7); - break; - case 0x03A8: - bufpush(0x03C8); - break; - case 0x03A9: - bufpush(0x03C9); - break; - case 0x03AA: - bufpush(0x03CA); - break; - case 0x03AB: - bufpush(0x03CB); - break; - case 0x03B0: - bufpush(0x03C5); - bufpush(0x0308); - bufpush(0x0301); - break; - case 0x03C2: - bufpush(0x03C3); - break; - case 0x03D0: - bufpush(0x03B2); - break; - case 0x03D1: - bufpush(0x03B8); - break; - case 0x03D5: - bufpush(0x03C6); - break; - case 0x03D6: - bufpush(0x03C0); - break; - case 0x03D8: - bufpush(0x03D9); - break; - case 0x03DA: - bufpush(0x03DB); - break; - case 0x03DC: - bufpush(0x03DD); - break; - case 0x03DE: - bufpush(0x03DF); - break; - case 0x03E0: - bufpush(0x03E1); - break; - case 0x03E2: - bufpush(0x03E3); - break; - case 0x03E4: - bufpush(0x03E5); - break; - case 0x03E6: - bufpush(0x03E7); - break; - case 0x03E8: - bufpush(0x03E9); - break; - case 0x03EA: - bufpush(0x03EB); - break; - case 0x03EC: - bufpush(0x03ED); - break; - case 0x03EE: - bufpush(0x03EF); - break; - case 0x03F0: - bufpush(0x03BA); - break; - case 0x03F1: - bufpush(0x03C1); - break; - case 0x03F2: - bufpush(0x03C3); - break; - case 0x03F4: - bufpush(0x03B8); - break; - case 0x03F5: - bufpush(0x03B5); - break; - case 0x0400: - bufpush(0x0450); - break; - case 0x0401: - bufpush(0x0451); - break; - case 0x0402: - bufpush(0x0452); - break; - case 0x0403: - bufpush(0x0453); - break; - case 0x0404: - bufpush(0x0454); - break; - case 0x0405: - bufpush(0x0455); - break; - case 0x0406: - bufpush(0x0456); - break; - case 0x0407: - bufpush(0x0457); - break; - case 0x0408: - bufpush(0x0458); - break; - case 0x0409: - bufpush(0x0459); - break; - case 0x040A: - bufpush(0x045A); - break; - case 0x040B: - bufpush(0x045B); - break; - case 0x040C: - bufpush(0x045C); - break; - case 0x040D: - bufpush(0x045D); - break; - case 0x040E: - bufpush(0x045E); - break; - case 0x040F: - bufpush(0x045F); - break; - case 0x0410: - bufpush(0x0430); - break; - case 0x0411: - bufpush(0x0431); - break; - case 0x0412: - bufpush(0x0432); - break; - case 0x0413: - bufpush(0x0433); - break; - case 0x0414: - bufpush(0x0434); - break; - case 0x0415: - bufpush(0x0435); - break; - case 0x0416: - bufpush(0x0436); - break; - case 0x0417: - bufpush(0x0437); - break; - case 0x0418: - bufpush(0x0438); - break; - case 0x0419: - bufpush(0x0439); - break; - case 0x041A: - bufpush(0x043A); - break; - case 0x041B: - bufpush(0x043B); - break; - case 0x041C: - bufpush(0x043C); - break; - case 0x041D: - bufpush(0x043D); - break; - case 0x041E: - bufpush(0x043E); - break; - case 0x041F: - bufpush(0x043F); - break; - case 0x0420: - bufpush(0x0440); - break; - case 0x0421: - bufpush(0x0441); - break; - case 0x0422: - bufpush(0x0442); - break; - case 0x0423: - bufpush(0x0443); - break; - case 0x0424: - bufpush(0x0444); - break; - case 0x0425: - bufpush(0x0445); - break; - case 0x0426: - bufpush(0x0446); - break; - case 0x0427: - bufpush(0x0447); - break; - case 0x0428: - bufpush(0x0448); - break; - case 0x0429: - bufpush(0x0449); - break; - case 0x042A: - bufpush(0x044A); - break; - case 0x042B: - bufpush(0x044B); - break; - case 0x042C: - bufpush(0x044C); - break; - case 0x042D: - bufpush(0x044D); - break; - case 0x042E: - bufpush(0x044E); - break; - case 0x042F: - bufpush(0x044F); - break; - case 0x0460: - bufpush(0x0461); - break; - case 0x0462: - bufpush(0x0463); - break; - case 0x0464: - bufpush(0x0465); - break; - case 0x0466: - bufpush(0x0467); - break; - case 0x0468: - bufpush(0x0469); - break; - case 0x046A: - bufpush(0x046B); - break; - case 0x046C: - bufpush(0x046D); - break; - case 0x046E: - bufpush(0x046F); - break; - case 0x0470: - bufpush(0x0471); - break; - case 0x0472: - bufpush(0x0473); - break; - case 0x0474: - bufpush(0x0475); - break; - case 0x0476: - bufpush(0x0477); - break; - case 0x0478: - bufpush(0x0479); - break; - case 0x047A: - bufpush(0x047B); - break; - case 0x047C: - bufpush(0x047D); - break; - case 0x047E: - bufpush(0x047F); - break; - case 0x0480: - bufpush(0x0481); - break; - case 0x048A: - bufpush(0x048B); - break; - case 0x048C: - bufpush(0x048D); - break; - case 0x048E: - bufpush(0x048F); - break; - case 0x0490: - bufpush(0x0491); - break; - case 0x0492: - bufpush(0x0493); - break; - case 0x0494: - bufpush(0x0495); - break; - case 0x0496: - bufpush(0x0497); - break; - case 0x0498: - bufpush(0x0499); - break; - case 0x049A: - bufpush(0x049B); - break; - case 0x049C: - bufpush(0x049D); - break; - case 0x049E: - bufpush(0x049F); - break; - case 0x04A0: - bufpush(0x04A1); - break; - case 0x04A2: - bufpush(0x04A3); - break; - case 0x04A4: - bufpush(0x04A5); - break; - case 0x04A6: - bufpush(0x04A7); - break; - case 0x04A8: - bufpush(0x04A9); - break; - case 0x04AA: - bufpush(0x04AB); - break; - case 0x04AC: - bufpush(0x04AD); - break; - case 0x04AE: - bufpush(0x04AF); - break; - case 0x04B0: - bufpush(0x04B1); - break; - case 0x04B2: - bufpush(0x04B3); - break; - case 0x04B4: - bufpush(0x04B5); - break; - case 0x04B6: - bufpush(0x04B7); - break; - case 0x04B8: - bufpush(0x04B9); - break; - case 0x04BA: - bufpush(0x04BB); - break; - case 0x04BC: - bufpush(0x04BD); - break; - case 0x04BE: - bufpush(0x04BF); - break; - case 0x04C1: - bufpush(0x04C2); - break; - case 0x04C3: - bufpush(0x04C4); - break; - case 0x04C5: - bufpush(0x04C6); - break; - case 0x04C7: - bufpush(0x04C8); - break; - case 0x04C9: - bufpush(0x04CA); - break; - case 0x04CB: - bufpush(0x04CC); - break; - case 0x04CD: - bufpush(0x04CE); - break; - case 0x04D0: - bufpush(0x04D1); - break; - case 0x04D2: - bufpush(0x04D3); - break; - case 0x04D4: - bufpush(0x04D5); - break; - case 0x04D6: - bufpush(0x04D7); - break; - case 0x04D8: - bufpush(0x04D9); - break; - case 0x04DA: - bufpush(0x04DB); - break; - case 0x04DC: - bufpush(0x04DD); - break; - case 0x04DE: - bufpush(0x04DF); - break; - case 0x04E0: - bufpush(0x04E1); - break; - case 0x04E2: - bufpush(0x04E3); - break; - case 0x04E4: - bufpush(0x04E5); - break; - case 0x04E6: - bufpush(0x04E7); - break; - case 0x04E8: - bufpush(0x04E9); - break; - case 0x04EA: - bufpush(0x04EB); - break; - case 0x04EC: - bufpush(0x04ED); - break; - case 0x04EE: - bufpush(0x04EF); - break; - case 0x04F0: - bufpush(0x04F1); - break; - case 0x04F2: - bufpush(0x04F3); - break; - case 0x04F4: - bufpush(0x04F5); - break; - case 0x04F8: - bufpush(0x04F9); - break; - case 0x0500: - bufpush(0x0501); - break; - case 0x0502: - bufpush(0x0503); - break; - case 0x0504: - bufpush(0x0505); - break; - case 0x0506: - bufpush(0x0507); - break; - case 0x0508: - bufpush(0x0509); - break; - case 0x050A: - bufpush(0x050B); - break; - case 0x050C: - bufpush(0x050D); - break; - case 0x050E: - bufpush(0x050F); - break; - case 0x0531: - bufpush(0x0561); - break; - case 0x0532: - bufpush(0x0562); - break; - case 0x0533: - bufpush(0x0563); - break; - case 0x0534: - bufpush(0x0564); - break; - case 0x0535: - bufpush(0x0565); - break; - case 0x0536: - bufpush(0x0566); - break; - case 0x0537: - bufpush(0x0567); - break; - case 0x0538: - bufpush(0x0568); - break; - case 0x0539: - bufpush(0x0569); - break; - case 0x053A: - bufpush(0x056A); - break; - case 0x053B: - bufpush(0x056B); - break; - case 0x053C: - bufpush(0x056C); - break; - case 0x053D: - bufpush(0x056D); - break; - case 0x053E: - bufpush(0x056E); - break; - case 0x053F: - bufpush(0x056F); - break; - case 0x0540: - bufpush(0x0570); - break; - case 0x0541: - bufpush(0x0571); - break; - case 0x0542: - bufpush(0x0572); - break; - case 0x0543: - bufpush(0x0573); - break; - case 0x0544: - bufpush(0x0574); - break; - case 0x0545: - bufpush(0x0575); - break; - case 0x0546: - bufpush(0x0576); - break; - case 0x0547: - bufpush(0x0577); - break; - case 0x0548: - bufpush(0x0578); - break; - case 0x0549: - bufpush(0x0579); - break; - case 0x054A: - bufpush(0x057A); - break; - case 0x054B: - bufpush(0x057B); - break; - case 0x054C: - bufpush(0x057C); - break; - case 0x054D: - bufpush(0x057D); - break; - case 0x054E: - bufpush(0x057E); - break; - case 0x054F: - bufpush(0x057F); - break; - case 0x0550: - bufpush(0x0580); - break; - case 0x0551: - bufpush(0x0581); - break; - case 0x0552: - bufpush(0x0582); - break; - case 0x0553: - bufpush(0x0583); - break; - case 0x0554: - bufpush(0x0584); - break; - case 0x0555: - bufpush(0x0585); - break; - case 0x0556: - bufpush(0x0586); - break; - case 0x0587: - bufpush(0x0565); - bufpush(0x0582); - break; - case 0x1E00: - bufpush(0x1E01); - break; - case 0x1E02: - bufpush(0x1E03); - break; - case 0x1E04: - bufpush(0x1E05); - break; - case 0x1E06: - bufpush(0x1E07); - break; - case 0x1E08: - bufpush(0x1E09); - break; - case 0x1E0A: - bufpush(0x1E0B); - break; - case 0x1E0C: - bufpush(0x1E0D); - break; - case 0x1E0E: - bufpush(0x1E0F); - break; - case 0x1E10: - bufpush(0x1E11); - break; - case 0x1E12: - bufpush(0x1E13); - break; - case 0x1E14: - bufpush(0x1E15); - break; - case 0x1E16: - bufpush(0x1E17); - break; - case 0x1E18: - bufpush(0x1E19); - break; - case 0x1E1A: - bufpush(0x1E1B); - break; - case 0x1E1C: - bufpush(0x1E1D); - break; - case 0x1E1E: - bufpush(0x1E1F); - break; - case 0x1E20: - bufpush(0x1E21); - break; - case 0x1E22: - bufpush(0x1E23); - break; - case 0x1E24: - bufpush(0x1E25); - break; - case 0x1E26: - bufpush(0x1E27); - break; - case 0x1E28: - bufpush(0x1E29); - break; - case 0x1E2A: - bufpush(0x1E2B); - break; - case 0x1E2C: - bufpush(0x1E2D); - break; - case 0x1E2E: - bufpush(0x1E2F); - break; - case 0x1E30: - bufpush(0x1E31); - break; - case 0x1E32: - bufpush(0x1E33); - break; - case 0x1E34: - bufpush(0x1E35); - break; - case 0x1E36: - bufpush(0x1E37); - break; - case 0x1E38: - bufpush(0x1E39); - break; - case 0x1E3A: - bufpush(0x1E3B); - break; - case 0x1E3C: - bufpush(0x1E3D); - break; - case 0x1E3E: - bufpush(0x1E3F); - break; - case 0x1E40: - bufpush(0x1E41); - break; - case 0x1E42: - bufpush(0x1E43); - break; - case 0x1E44: - bufpush(0x1E45); - break; - case 0x1E46: - bufpush(0x1E47); - break; - case 0x1E48: - bufpush(0x1E49); - break; - case 0x1E4A: - bufpush(0x1E4B); - break; - case 0x1E4C: - bufpush(0x1E4D); - break; - case 0x1E4E: - bufpush(0x1E4F); - break; - case 0x1E50: - bufpush(0x1E51); - break; - case 0x1E52: - bufpush(0x1E53); - break; - case 0x1E54: - bufpush(0x1E55); - break; - case 0x1E56: - bufpush(0x1E57); - break; - case 0x1E58: - bufpush(0x1E59); - break; - case 0x1E5A: - bufpush(0x1E5B); - break; - case 0x1E5C: - bufpush(0x1E5D); - break; - case 0x1E5E: - bufpush(0x1E5F); - break; - case 0x1E60: - bufpush(0x1E61); - break; - case 0x1E62: - bufpush(0x1E63); - break; - case 0x1E64: - bufpush(0x1E65); - break; - case 0x1E66: - bufpush(0x1E67); - break; - case 0x1E68: - bufpush(0x1E69); - break; - case 0x1E6A: - bufpush(0x1E6B); - break; - case 0x1E6C: - bufpush(0x1E6D); - break; - case 0x1E6E: - bufpush(0x1E6F); - break; - case 0x1E70: - bufpush(0x1E71); - break; - case 0x1E72: - bufpush(0x1E73); - break; - case 0x1E74: - bufpush(0x1E75); - break; - case 0x1E76: - bufpush(0x1E77); - break; - case 0x1E78: - bufpush(0x1E79); - break; - case 0x1E7A: - bufpush(0x1E7B); - break; - case 0x1E7C: - bufpush(0x1E7D); - break; - case 0x1E7E: - bufpush(0x1E7F); - break; - case 0x1E80: - bufpush(0x1E81); - break; - case 0x1E82: - bufpush(0x1E83); - break; - case 0x1E84: - bufpush(0x1E85); - break; - case 0x1E86: - bufpush(0x1E87); - break; - case 0x1E88: - bufpush(0x1E89); - break; - case 0x1E8A: - bufpush(0x1E8B); - break; - case 0x1E8C: - bufpush(0x1E8D); - break; - case 0x1E8E: - bufpush(0x1E8F); - break; - case 0x1E90: - bufpush(0x1E91); - break; - case 0x1E92: - bufpush(0x1E93); - break; - case 0x1E94: - bufpush(0x1E95); - break; - case 0x1E96: - bufpush(0x0068); - bufpush(0x0331); - break; - case 0x1E97: - bufpush(0x0074); - bufpush(0x0308); - break; - case 0x1E98: - bufpush(0x0077); - bufpush(0x030A); - break; - case 0x1E99: - bufpush(0x0079); - bufpush(0x030A); - break; - case 0x1E9A: - bufpush(0x0061); - bufpush(0x02BE); - break; - case 0x1E9B: - bufpush(0x1E61); - break; - case 0x1EA0: - bufpush(0x1EA1); - break; - case 0x1EA2: - bufpush(0x1EA3); - break; - case 0x1EA4: - bufpush(0x1EA5); - break; - case 0x1EA6: - bufpush(0x1EA7); - break; - case 0x1EA8: - bufpush(0x1EA9); - break; - case 0x1EAA: - bufpush(0x1EAB); - break; - case 0x1EAC: - bufpush(0x1EAD); - break; - case 0x1EAE: - bufpush(0x1EAF); - break; - case 0x1EB0: - bufpush(0x1EB1); - break; - case 0x1EB2: - bufpush(0x1EB3); - break; - case 0x1EB4: - bufpush(0x1EB5); - break; - case 0x1EB6: - bufpush(0x1EB7); - break; - case 0x1EB8: - bufpush(0x1EB9); - break; - case 0x1EBA: - bufpush(0x1EBB); - break; - case 0x1EBC: - bufpush(0x1EBD); - break; - case 0x1EBE: - bufpush(0x1EBF); - break; - case 0x1EC0: - bufpush(0x1EC1); - break; - case 0x1EC2: - bufpush(0x1EC3); - break; - case 0x1EC4: - bufpush(0x1EC5); - break; - case 0x1EC6: - bufpush(0x1EC7); - break; - case 0x1EC8: - bufpush(0x1EC9); - break; - case 0x1ECA: - bufpush(0x1ECB); - break; - case 0x1ECC: - bufpush(0x1ECD); - break; - case 0x1ECE: - bufpush(0x1ECF); - break; - case 0x1ED0: - bufpush(0x1ED1); - break; - case 0x1ED2: - bufpush(0x1ED3); - break; - case 0x1ED4: - bufpush(0x1ED5); - break; - case 0x1ED6: - bufpush(0x1ED7); - break; - case 0x1ED8: - bufpush(0x1ED9); - break; - case 0x1EDA: - bufpush(0x1EDB); - break; - case 0x1EDC: - bufpush(0x1EDD); - break; - case 0x1EDE: - bufpush(0x1EDF); - break; - case 0x1EE0: - bufpush(0x1EE1); - break; - case 0x1EE2: - bufpush(0x1EE3); - break; - case 0x1EE4: - bufpush(0x1EE5); - break; - case 0x1EE6: - bufpush(0x1EE7); - break; - case 0x1EE8: - bufpush(0x1EE9); - break; - case 0x1EEA: - bufpush(0x1EEB); - break; - case 0x1EEC: - bufpush(0x1EED); - break; - case 0x1EEE: - bufpush(0x1EEF); - break; - case 0x1EF0: - bufpush(0x1EF1); - break; - case 0x1EF2: - bufpush(0x1EF3); - break; - case 0x1EF4: - bufpush(0x1EF5); - break; - case 0x1EF6: - bufpush(0x1EF7); - break; - case 0x1EF8: - bufpush(0x1EF9); - break; - case 0x1F08: - bufpush(0x1F00); - break; - case 0x1F09: - bufpush(0x1F01); - break; - case 0x1F0A: - bufpush(0x1F02); - break; - case 0x1F0B: - bufpush(0x1F03); - break; - case 0x1F0C: - bufpush(0x1F04); - break; - case 0x1F0D: - bufpush(0x1F05); - break; - case 0x1F0E: - bufpush(0x1F06); - break; - case 0x1F0F: - bufpush(0x1F07); - break; - case 0x1F18: - bufpush(0x1F10); - break; - case 0x1F19: - bufpush(0x1F11); - break; - case 0x1F1A: - bufpush(0x1F12); - break; - case 0x1F1B: - bufpush(0x1F13); - break; - case 0x1F1C: - bufpush(0x1F14); - break; - case 0x1F1D: - bufpush(0x1F15); - break; - case 0x1F28: - bufpush(0x1F20); - break; - case 0x1F29: - bufpush(0x1F21); - break; - case 0x1F2A: - bufpush(0x1F22); - break; - case 0x1F2B: - bufpush(0x1F23); - break; - case 0x1F2C: - bufpush(0x1F24); - break; - case 0x1F2D: - bufpush(0x1F25); - break; - case 0x1F2E: - bufpush(0x1F26); - break; - case 0x1F2F: - bufpush(0x1F27); - break; - case 0x1F38: - bufpush(0x1F30); - break; - case 0x1F39: - bufpush(0x1F31); - break; - case 0x1F3A: - bufpush(0x1F32); - break; - case 0x1F3B: - bufpush(0x1F33); - break; - case 0x1F3C: - bufpush(0x1F34); - break; - case 0x1F3D: - bufpush(0x1F35); - break; - case 0x1F3E: - bufpush(0x1F36); - break; - case 0x1F3F: - bufpush(0x1F37); - break; - case 0x1F48: - bufpush(0x1F40); - break; - case 0x1F49: - bufpush(0x1F41); - break; - case 0x1F4A: - bufpush(0x1F42); - break; - case 0x1F4B: - bufpush(0x1F43); - break; - case 0x1F4C: - bufpush(0x1F44); - break; - case 0x1F4D: - bufpush(0x1F45); - break; - case 0x1F50: - bufpush(0x03C5); - bufpush(0x0313); - break; - case 0x1F52: - bufpush(0x03C5); - bufpush(0x0313); - bufpush(0x0300); - break; - case 0x1F54: - bufpush(0x03C5); - bufpush(0x0313); - bufpush(0x0301); - break; - case 0x1F56: - bufpush(0x03C5); - bufpush(0x0313); - bufpush(0x0342); - break; - case 0x1F59: - bufpush(0x1F51); - break; - case 0x1F5B: - bufpush(0x1F53); - break; - case 0x1F5D: - bufpush(0x1F55); - break; - case 0x1F5F: - bufpush(0x1F57); - break; - case 0x1F68: - bufpush(0x1F60); - break; - case 0x1F69: - bufpush(0x1F61); - break; - case 0x1F6A: - bufpush(0x1F62); - break; - case 0x1F6B: - bufpush(0x1F63); - break; - case 0x1F6C: - bufpush(0x1F64); - break; - case 0x1F6D: - bufpush(0x1F65); - break; - case 0x1F6E: - bufpush(0x1F66); - break; - case 0x1F6F: - bufpush(0x1F67); - break; - case 0x1F80: - bufpush(0x1F00); - bufpush(0x03B9); - break; - case 0x1F81: - bufpush(0x1F01); - bufpush(0x03B9); - break; - case 0x1F82: - bufpush(0x1F02); - bufpush(0x03B9); - break; - case 0x1F83: - bufpush(0x1F03); - bufpush(0x03B9); - break; - case 0x1F84: - bufpush(0x1F04); - bufpush(0x03B9); - break; - case 0x1F85: - bufpush(0x1F05); - bufpush(0x03B9); - break; - case 0x1F86: - bufpush(0x1F06); - bufpush(0x03B9); - break; - case 0x1F87: - bufpush(0x1F07); - bufpush(0x03B9); - break; - case 0x1F88: - bufpush(0x1F00); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F89: - bufpush(0x1F01); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F8A: - bufpush(0x1F02); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F8B: - bufpush(0x1F03); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F8C: - bufpush(0x1F04); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F8D: - bufpush(0x1F05); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F8E: - bufpush(0x1F06); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F8F: - bufpush(0x1F07); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F90: - bufpush(0x1F20); - bufpush(0x03B9); - break; - case 0x1F91: - bufpush(0x1F21); - bufpush(0x03B9); - break; - case 0x1F92: - bufpush(0x1F22); - bufpush(0x03B9); - break; - case 0x1F93: - bufpush(0x1F23); - bufpush(0x03B9); - break; - case 0x1F94: - bufpush(0x1F24); - bufpush(0x03B9); - break; - case 0x1F95: - bufpush(0x1F25); - bufpush(0x03B9); - break; - case 0x1F96: - bufpush(0x1F26); - bufpush(0x03B9); - break; - case 0x1F97: - bufpush(0x1F27); - bufpush(0x03B9); - break; - case 0x1F98: - bufpush(0x1F20); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F99: - bufpush(0x1F21); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F9A: - bufpush(0x1F22); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F9B: - bufpush(0x1F23); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F9C: - bufpush(0x1F24); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F9D: - bufpush(0x1F25); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F9E: - bufpush(0x1F26); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F9F: - bufpush(0x1F27); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FA0: - bufpush(0x1F60); - bufpush(0x03B9); - break; - case 0x1FA1: - bufpush(0x1F61); - bufpush(0x03B9); - break; - case 0x1FA2: - bufpush(0x1F62); - bufpush(0x03B9); - break; - case 0x1FA3: - bufpush(0x1F63); - bufpush(0x03B9); - break; - case 0x1FA4: - bufpush(0x1F64); - bufpush(0x03B9); - break; - case 0x1FA5: - bufpush(0x1F65); - bufpush(0x03B9); - break; - case 0x1FA6: - bufpush(0x1F66); - bufpush(0x03B9); - break; - case 0x1FA7: - bufpush(0x1F67); - bufpush(0x03B9); - break; - case 0x1FA8: - bufpush(0x1F60); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FA9: - bufpush(0x1F61); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FAA: - bufpush(0x1F62); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FAB: - bufpush(0x1F63); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FAC: - bufpush(0x1F64); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FAD: - bufpush(0x1F65); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FAE: - bufpush(0x1F66); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FAF: - bufpush(0x1F67); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FB2: - bufpush(0x1F70); - bufpush(0x03B9); - break; - case 0x1FB3: - bufpush(0x03B1); - bufpush(0x03B9); - break; - case 0x1FB4: - bufpush(0x03AC); - bufpush(0x03B9); - break; - case 0x1FB6: - bufpush(0x03B1); - bufpush(0x0342); - break; - case 0x1FB7: - bufpush(0x03B1); - bufpush(0x0342); - bufpush(0x03B9); - break; - case 0x1FB8: - bufpush(0x1FB0); - break; - case 0x1FB9: - bufpush(0x1FB1); - break; - case 0x1FBA: - bufpush(0x1F70); - break; - case 0x1FBB: - bufpush(0x1F71); - break; - case 0x1FBC: - bufpush(0x03B1); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FBE: - bufpush(0x03B9); - break; - case 0x1FC2: - bufpush(0x1F74); - bufpush(0x03B9); - break; - case 0x1FC3: - bufpush(0x03B7); - bufpush(0x03B9); - break; - case 0x1FC4: - bufpush(0x03AE); - bufpush(0x03B9); - break; - case 0x1FC6: - bufpush(0x03B7); - bufpush(0x0342); - break; - case 0x1FC7: - bufpush(0x03B7); - bufpush(0x0342); - bufpush(0x03B9); - break; - case 0x1FC8: - bufpush(0x1F72); - break; - case 0x1FC9: - bufpush(0x1F73); - break; - case 0x1FCA: - bufpush(0x1F74); - break; - case 0x1FCB: - bufpush(0x1F75); - break; - case 0x1FCC: - bufpush(0x03B7); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FD2: - bufpush(0x03B9); - bufpush(0x0308); - bufpush(0x0300); - break; - case 0x1FD3: - bufpush(0x03B9); - bufpush(0x0308); - bufpush(0x0301); - break; - case 0x1FD6: - bufpush(0x03B9); - bufpush(0x0342); - break; - case 0x1FD7: - bufpush(0x03B9); - bufpush(0x0308); - bufpush(0x0342); - break; - case 0x1FD8: - bufpush(0x1FD0); - break; - case 0x1FD9: - bufpush(0x1FD1); - break; - case 0x1FDA: - bufpush(0x1F76); - break; - case 0x1FDB: - bufpush(0x1F77); - break; - case 0x1FE2: - bufpush(0x03C5); - bufpush(0x0308); - bufpush(0x0300); - break; - case 0x1FE3: - bufpush(0x03C5); - bufpush(0x0308); - bufpush(0x0301); - break; - case 0x1FE4: - bufpush(0x03C1); - bufpush(0x0313); - break; - case 0x1FE6: - bufpush(0x03C5); - bufpush(0x0342); - break; - case 0x1FE7: - bufpush(0x03C5); - bufpush(0x0308); - bufpush(0x0342); - break; - case 0x1FE8: - bufpush(0x1FE0); - break; - case 0x1FE9: - bufpush(0x1FE1); - break; - case 0x1FEA: - bufpush(0x1F7A); - break; - case 0x1FEB: - bufpush(0x1F7B); - break; - case 0x1FEC: - bufpush(0x1FE5); - break; - case 0x1FF2: - bufpush(0x1F7C); - bufpush(0x03B9); - break; - case 0x1FF3: - bufpush(0x03C9); - bufpush(0x03B9); - break; - case 0x1FF4: - bufpush(0x03CE); - bufpush(0x03B9); - break; - case 0x1FF6: - bufpush(0x03C9); - bufpush(0x0342); - break; - case 0x1FF7: - bufpush(0x03C9); - bufpush(0x0342); - bufpush(0x03B9); - break; - case 0x1FF8: - bufpush(0x1F78); - break; - case 0x1FF9: - bufpush(0x1F79); - break; - case 0x1FFA: - bufpush(0x1F7C); - break; - case 0x1FFB: - bufpush(0x1F7D); - break; - case 0x1FFC: - bufpush(0x03C9); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x2126: - bufpush(0x03C9); - break; - case 0x212A: - bufpush(0x006B); - break; - case 0x212B: - bufpush(0x00E5); - break; - case 0x2160: - bufpush(0x2170); - break; - case 0x2161: - bufpush(0x2171); - break; - case 0x2162: - bufpush(0x2172); - break; - case 0x2163: - bufpush(0x2173); - break; - case 0x2164: - bufpush(0x2174); - break; - case 0x2165: - bufpush(0x2175); - break; - case 0x2166: - bufpush(0x2176); - break; - case 0x2167: - bufpush(0x2177); - break; - case 0x2168: - bufpush(0x2178); - break; - case 0x2169: - bufpush(0x2179); - break; - case 0x216A: - bufpush(0x217A); - break; - case 0x216B: - bufpush(0x217B); - break; - case 0x216C: - bufpush(0x217C); - break; - case 0x216D: - bufpush(0x217D); - break; - case 0x216E: - bufpush(0x217E); - break; - case 0x216F: - bufpush(0x217F); - break; - case 0x24B6: - bufpush(0x24D0); - break; - case 0x24B7: - bufpush(0x24D1); - break; - case 0x24B8: - bufpush(0x24D2); - break; - case 0x24B9: - bufpush(0x24D3); - break; - case 0x24BA: - bufpush(0x24D4); - break; - case 0x24BB: - bufpush(0x24D5); - break; - case 0x24BC: - bufpush(0x24D6); - break; - case 0x24BD: - bufpush(0x24D7); - break; - case 0x24BE: - bufpush(0x24D8); - break; - case 0x24BF: - bufpush(0x24D9); - break; - case 0x24C0: - bufpush(0x24DA); - break; - case 0x24C1: - bufpush(0x24DB); - break; - case 0x24C2: - bufpush(0x24DC); - break; - case 0x24C3: - bufpush(0x24DD); - break; - case 0x24C4: - bufpush(0x24DE); - break; - case 0x24C5: - bufpush(0x24DF); - break; - case 0x24C6: - bufpush(0x24E0); - break; - case 0x24C7: - bufpush(0x24E1); - break; - case 0x24C8: - bufpush(0x24E2); - break; - case 0x24C9: - bufpush(0x24E3); - break; - case 0x24CA: - bufpush(0x24E4); - break; - case 0x24CB: - bufpush(0x24E5); - break; - case 0x24CC: - bufpush(0x24E6); - break; - case 0x24CD: - bufpush(0x24E7); - break; - case 0x24CE: - bufpush(0x24E8); - break; - case 0x24CF: - bufpush(0x24E9); - break; - case 0xFB00: - bufpush(0x0066); - bufpush(0x0066); - break; - case 0xFB01: - bufpush(0x0066); - bufpush(0x0069); - break; - case 0xFB02: - bufpush(0x0066); - bufpush(0x006C); - break; - case 0xFB03: - bufpush(0x0066); - bufpush(0x0066); - bufpush(0x0069); - break; - case 0xFB04: - bufpush(0x0066); - bufpush(0x0066); - bufpush(0x006C); - break; - case 0xFB05: - bufpush(0x0073); - bufpush(0x0074); - break; - case 0xFB06: - bufpush(0x0073); - bufpush(0x0074); - break; - case 0xFB13: - bufpush(0x0574); - bufpush(0x0576); - break; - case 0xFB14: - bufpush(0x0574); - bufpush(0x0565); - break; - case 0xFB15: - bufpush(0x0574); - bufpush(0x056B); - break; - case 0xFB16: - bufpush(0x057E); - bufpush(0x0576); - break; - case 0xFB17: - bufpush(0x0574); - bufpush(0x056D); - break; - case 0xFF21: - bufpush(0xFF41); - break; - case 0xFF22: - bufpush(0xFF42); - break; - case 0xFF23: - bufpush(0xFF43); - break; - case 0xFF24: - bufpush(0xFF44); - break; - case 0xFF25: - bufpush(0xFF45); - break; - case 0xFF26: - bufpush(0xFF46); - break; - case 0xFF27: - bufpush(0xFF47); - break; - case 0xFF28: - bufpush(0xFF48); - break; - case 0xFF29: - bufpush(0xFF49); - break; - case 0xFF2A: - bufpush(0xFF4A); - break; - case 0xFF2B: - bufpush(0xFF4B); - break; - case 0xFF2C: - bufpush(0xFF4C); - break; - case 0xFF2D: - bufpush(0xFF4D); - break; - case 0xFF2E: - bufpush(0xFF4E); - break; - case 0xFF2F: - bufpush(0xFF4F); - break; - case 0xFF30: - bufpush(0xFF50); - break; - case 0xFF31: - bufpush(0xFF51); - break; - case 0xFF32: - bufpush(0xFF52); - break; - case 0xFF33: - bufpush(0xFF53); - break; - case 0xFF34: - bufpush(0xFF54); - break; - case 0xFF35: - bufpush(0xFF55); - break; - case 0xFF36: - bufpush(0xFF56); - break; - case 0xFF37: - bufpush(0xFF57); - break; - case 0xFF38: - bufpush(0xFF58); - break; - case 0xFF39: - bufpush(0xFF59); - break; - case 0xFF3A: - bufpush(0xFF5A); - break; - case 0x10400: - bufpush(0x10428); - break; - case 0x10401: - bufpush(0x10429); - break; - case 0x10402: - bufpush(0x1042A); - break; - case 0x10403: - bufpush(0x1042B); - break; - case 0x10404: - bufpush(0x1042C); - break; - case 0x10405: - bufpush(0x1042D); - break; - case 0x10406: - bufpush(0x1042E); - break; - case 0x10407: - bufpush(0x1042F); - break; - case 0x10408: - bufpush(0x10430); - break; - case 0x10409: - bufpush(0x10431); - break; - case 0x1040A: - bufpush(0x10432); - break; - case 0x1040B: - bufpush(0x10433); - break; - case 0x1040C: - bufpush(0x10434); - break; - case 0x1040D: - bufpush(0x10435); - break; - case 0x1040E: - bufpush(0x10436); - break; - case 0x1040F: - bufpush(0x10437); - break; - case 0x10410: - bufpush(0x10438); - break; - case 0x10411: - bufpush(0x10439); - break; - case 0x10412: - bufpush(0x1043A); - break; - case 0x10413: - bufpush(0x1043B); - break; - case 0x10414: - bufpush(0x1043C); - break; - case 0x10415: - bufpush(0x1043D); - break; - case 0x10416: - bufpush(0x1043E); - break; - case 0x10417: - bufpush(0x1043F); - break; - case 0x10418: - bufpush(0x10440); - break; - case 0x10419: - bufpush(0x10441); - break; - case 0x1041A: - bufpush(0x10442); - break; - case 0x1041B: - bufpush(0x10443); - break; - case 0x1041C: - bufpush(0x10444); - break; - case 0x1041D: - bufpush(0x10445); - break; - case 0x1041E: - bufpush(0x10446); - break; - case 0x1041F: - bufpush(0x10447); - break; - case 0x10420: - bufpush(0x10448); - break; - case 0x10421: - bufpush(0x10449); - break; - case 0x10422: - bufpush(0x1044A); - break; - case 0x10423: - bufpush(0x1044B); - break; - case 0x10424: - bufpush(0x1044C); - break; - case 0x10425: - bufpush(0x1044D); - break; - } diff --git a/src/chunk.h b/src/chunk.h new file mode 100644 index 0000000..f37a2f3 --- /dev/null +++ b/src/chunk.h @@ -0,0 +1,92 @@ +#ifndef _CHUNK_H_ +#define _CHUNK_H_ + +#include <string.h> +#include <ctype.h> +#include <stdlib.h> +#include <assert.h> +#include "buffer.h" + +typedef struct { + const unsigned char *data; + int len; + int alloc; +} chunk; + +static inline void chunk_free(chunk *c) +{ + if (c->alloc) + free((char *)c->data); + + c->data = NULL; + c->alloc = 0; + c->len = 0; +} + +static inline void chunk_ltrim(chunk *c) +{ + assert(!c->alloc); + + while (c->len && isspace(c->data[0])) { + c->data++; + c->len--; + } +} + +static inline void chunk_rtrim(chunk *c) +{ + while (c->len > 0) { + if (!isspace(c->data[c->len - 1])) + break; + + c->len--; + } +} + +static inline void chunk_trim(chunk *c) +{ + chunk_ltrim(c); + chunk_rtrim(c); +} + +static inline int chunk_strchr(chunk *ch, int c, int offset) +{ + const unsigned char *p = memchr(ch->data + offset, c, ch->len - offset); + return p ? (int)(p - ch->data) : ch->len; +} + +static inline unsigned char *chunk_to_cstr(chunk *c) +{ + unsigned char *str; + + str = malloc(c->len + 1); + memcpy(str, c->data, c->len); + str[c->len] = 0; + + return str; +} + +static inline chunk chunk_literal(const char *data) +{ + chunk c = {(const unsigned char *)data, data ? strlen(data) : 0, 0}; + return c; +} + +static inline chunk chunk_dup(const chunk *ch, int pos, int len) +{ + chunk c = {ch->data + pos, len, 0}; + return c; +} + +static inline chunk chunk_buf_detach(strbuf *buf) +{ + chunk c; + + c.len = buf->size; + c.data = strbuf_detach(buf); + c.alloc = 1; + + return c; +} + +#endif diff --git a/src/detab.c b/src/detab.c deleted file mode 100644 index e03fcf7..0000000 --- a/src/detab.c +++ /dev/null @@ -1,48 +0,0 @@ -#include "bstrlib.h" - -// UTF-8 aware detab: assumes s has no newlines, or only a final newline. -// Return 0 on success, BSTR_ERR if invalid UTF-8. -extern int bdetab(bstring s, int utf8) -{ - unsigned char c; - int pos = 0; // a count of characters - int byte = 0; // a count of bytes - int high_chars_to_skip = 0; - int numspaces = 0; - while ((c = bchar(s, byte))) { - if (utf8 && high_chars_to_skip > 0) { - if (c >= 0x80) { - high_chars_to_skip--; - byte++; - } else { - return BSTR_ERR; // invalid utf-8 - } - } else if (c == '\t') { - bdelete(s, byte, 1); // delete tab character - numspaces = 4 - (pos % 4); - binsertch(s, byte, numspaces, ' '); - byte += numspaces; - pos += numspaces; - } else if (c <= 0x80 || !utf8) { - byte++; - pos++; - } else { // multibyte utf8 sequences - if (c >> 1 == 0176) { - high_chars_to_skip = 5; - } else if (c >> 2 == 076) { - high_chars_to_skip = 4; - } else if (c >> 3 == 036) { - high_chars_to_skip = 3; - } else if (c >> 4 == 016) { - high_chars_to_skip = 2; - } else if (c >> 5 == 06) { - high_chars_to_skip = 1; - } else { - return BSTR_ERR; // invalid utf-8 - } - pos++; - byte++; - } - } - return 0; -} diff --git a/src/getopt.c b/src/getopt.c deleted file mode 100644 index 321dd9f..0000000 --- a/src/getopt.c +++ /dev/null @@ -1,199 +0,0 @@ -/* $Id: getopt.c 4022 2008-03-31 06:11:07Z rra $ - * - * Replacement implementation of getopt. - * - * This is a replacement implementation for getopt based on the my_getopt - * distribution by Benjamin Sittler. Only the getopt interface is included, - * since remctl doesn't use GNU long options, and the code has been rearranged - * and reworked somewhat to fit with the remctl coding style. - * - * Copyright 1997, 2000, 2001, 2002 Benjamin Sittler - * Copyright 2008 Russ Allbery <rra@stanford.edu> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include <config.h> -#include <portable/system.h> -#include <portable/getopt.h> - -/* - * If we're running the test suite, rename getopt and the global variables to - * avoid conflicts with the system version. - */ -#if TESTING -# define getopt test_getopt -int test_getopt(int, char **, const char *); -# define optind test_optind -# define opterr test_opterr -# define optopt test_optopt -# define optarg test_optarg -#endif - -/* Initialize global interface variables. */ -int optind = 1; -int opterr = 1; -int optopt = 0; -char *optarg = NULL; - -/* - * This is the plain old UNIX getopt, with GNU-style extensions. If you're - * porting some piece of UNIX software, this is all you need. It supports - * GNU-style permutation and optional arguments, but does not support the GNU - * -W extension. - * - * This function is not re-entrant or thread-safe, has static variables, and - * generally isn't a great interface, but normally you only call it once. - */ -int -getopt(int argc, char *argv[], const char *optstring) -{ - const char *p; - size_t offset = 0; - char mode = '\0'; - int colon_mode = 0; - int option = -1; - - /* Holds the current position in the parameter being parsed. */ - static int charind = 0; - - /* - * By default, getopt permutes argv as it scans and leaves all non-options - * at the end. This can be changed with the first character of optstring - * or the environment variable POSIXLY_CORRECT. With a first character of - * '+' or when POSIXLY_CORRECT is set, option processing stops at the - * first non-option. If the first character is '-', each non-option argv - * element is handled as if it were the argument of an option with - * character code 1. mode holds this character. - * - * After the optional leading '+' and '-', optstring may contain ':'. If - * present, missing arguments return ':' instead of '?'. colon_mode holds - * this setting. - */ - if (getenv("POSIXLY_CORRECT") != NULL) { - mode = '+'; - colon_mode = '+'; - } else { - if (optstring[offset] == '+' || optstring[offset] == '-') { - mode = optstring[offset]; - offset++; - } - if (optstring[offset] == ':') { - colon_mode = 1; - offset++; - } - } - - /* - * charind holds where we left off. If it's set, we were in the middle - * of an argv element; if not, we pick up with the next element of - * optind. - */ - optarg = NULL; - if (charind == 0) { - if (optind >= argc) - option = -1; - else if (strcmp(argv[optind], "--") == 0) { - optind++; - option = -1; - } else if (argv[optind][0] != '-' || argv[optind][1] == '\0') { - char *tmp; - int i, j, k, end; - - if (mode == '+') - option = -1; - else if (mode == '-') { - optarg = argv[optind]; - optind++; - option = 1; - } else { - for (i = optind + 1, j = optind; i < argc; i++) - if ((argv[i][0] == '-') && (argv[i][1] != '\0')) { - optind = i; - option = getopt(argc, argv, optstring); - while (i > j) { - --i; - tmp = argv[i]; - end = (charind == 0) ? optind - 1 : optind; - for (k = i; k + 1 <= end; k++) { - argv[k] = argv[k + 1]; - } - argv[end] = tmp; - --optind; - } - break; - } - if (i == argc) - option = -1; - } - return option; - } else { - charind = 1; - } - } - if (charind != 0) { - optopt = argv[optind][charind]; - for (p = optstring + offset; *p != '\0'; p++) - if (optopt == *p) { - p++; - if (*p == ':') { - if (argv[optind][charind + 1] != '\0') { - optarg = &argv[optind][charind + 1]; - optind++; - charind = 0; - } else { - p++; - if (*p != ':') { - charind = 0; - optind++; - if (optind >= argc) { - if (opterr) - fprintf(stderr, "%s: option requires" - " an argument -- %c\n", argv[0], - optopt); - option = colon_mode ? ':' : '?'; - goto done; - } else { - optarg = argv[optind]; - optind++; - } - } - } - } - option = optopt; - } - if (option == -1) { - if (opterr) - fprintf(stderr, "%s: illegal option -- %c\n", argv[0], optopt); - option = '?'; - } - } - -done: - if (charind != 0) { - charind++; - if (argv[optind][charind] == '\0') { - optind++; - charind = 0; - } - } - if (optind > argc) - optind = argc; - return option; -} diff --git a/src/html.c b/src/html.c deleted file mode 100644 index aeec5f1..0000000 --- a/src/html.c +++ /dev/null @@ -1,276 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> -#include <stdbool.h> -#include "bstrlib.h" -#include "stmd.h" -#include "debug.h" -#include "scanners.h" - -// Functions to convert block and inline lists to HTML strings. - -// Escape special characters in HTML. More efficient than -// three calls to bfindreplace. If preserve_entities is set, -// existing entities are left alone. -static bstring escape_html(bstring inp, bool preserve_entities) -{ - int pos = 0; - int match; - char c; - bstring escapable = blk2bstr("&<>\"", 4); - bstring ent; - bstring s = bstrcpy(inp); - while ((pos = binchr(s, pos, escapable)) != BSTR_ERR) { - c = bchar(s,pos); - switch (c) { - case '<': - bdelete(s, pos, 1); - ent = blk2bstr("<", 4); - binsert(s, pos, ent, ' '); - bdestroy(ent); - pos += 4; - break; - case '>': - bdelete(s, pos, 1); - ent = blk2bstr(">", 4); - binsert(s, pos, ent, ' '); - bdestroy(ent); - pos += 4; - break; - case '&': - if (preserve_entities && (match = scan_entity(s, pos))) { - pos += match; - } else { - bdelete(s, pos, 1); - ent = blk2bstr("&", 5); - binsert(s, pos, ent, ' '); - bdestroy(ent); - pos += 5; - } - break; - case '"': - bdelete(s, pos, 1); - ent = blk2bstr(""", 6); - binsert(s, pos, ent, ' '); - bdestroy(ent); - pos += 6; - break; - default: - bdelete(s, pos, 1); - log_err("unexpected character %02x", c); - } - } - bdestroy(escapable); - return s; -} - -static inline void cr(bstring buffer) -{ - int c = bchar(buffer, blength(buffer) - 1); - if (c != '\n' && c) { - bconchar(buffer, '\n'); - } -} - -// Convert a block list to HTML. Returns 0 on success, and sets result. -extern int blocks_to_html(block* b, bstring* result, bool tight) -{ - bstring contents = NULL; - bstring escaped, escaped2; - struct bstrList * info_words; - struct ListData * data; - bstring mbstart; - bstring html = blk2bstr("", 0); - - while(b != NULL) { - switch(b->tag) { - case document: - check(blocks_to_html(b->children, &contents, false) == 0, - "error converting blocks to html"); - bformata(html, "%s", contents->data); - bdestroy(contents); - break; - case paragraph: - check(inlines_to_html(b->inline_content, &contents) == 0, - "error converting inlines to html"); - if (tight) { - bformata(html, "%s", contents->data); - } else { - cr(html); - bformata(html, "<p>%s</p>", contents->data); - cr(html); - } - bdestroy(contents); - break; - case block_quote: - check(blocks_to_html(b->children, &contents, false) == 0, - "error converting blocks to html"); - cr(html); - bformata(html, "<blockquote>\n%s</blockquote>", contents->data); - cr(html); - bdestroy(contents); - break; - case list_item: - check(blocks_to_html(b->children, &contents, tight) == 0, - "error converting blocks to html"); - brtrimws(contents); - cr(html); - bformata(html, "<li>%s</li>", contents->data); - cr(html); - bdestroy(contents); - break; - case list: - // make sure a list starts at the beginning of the line: - cr(html); - data = &(b->attributes.list_data); - check(blocks_to_html(b->children, &contents, data->tight) == 0, - "error converting blocks to html"); - mbstart = bformat(" start=\"%d\"", data->start); - bformata(html, "<%s%s>\n%s</%s>", - data->list_type == bullet ? "ul" : "ol", - data->start == 1 ? "" : (char*) mbstart->data, - contents->data, - data->list_type == bullet ? "ul" : "ol"); - cr(html); - bdestroy(contents); - bdestroy(mbstart); - break; - case atx_header: - case setext_header: - check(inlines_to_html(b->inline_content, &contents) == 0, - "error converting inlines to html"); - cr(html); - bformata(html, "<h%d>%s</h%d>", - b->attributes.header_level, - contents->data, - b->attributes.header_level); - cr(html); - bdestroy(contents); - break; - case indented_code: - escaped = escape_html(b->string_content, false); - cr(html); - bformata(html, "<pre><code>%s</code></pre>", escaped->data); - cr(html); - bdestroy(escaped); - break; - case fenced_code: - escaped = escape_html(b->string_content, false); - cr(html); - bformata(html, "<pre><code"); - if (blength(b->attributes.fenced_code_data.info) > 0) { - escaped2 = escape_html(b->attributes.fenced_code_data.info, true); - info_words = bsplit(escaped2, ' '); - bformata(html, " class=\"language-%s\"", info_words->entry[0]->data); - bdestroy(escaped2); - bstrListDestroy(info_words); - } - bformata(html, ">%s</code></pre>", escaped->data); - cr(html); - bdestroy(escaped); - break; - case html_block: - bformata(html, "%s", b->string_content->data); - break; - case hrule: - bformata(html, "<hr />"); - cr(html); - break; - case reference_def: - break; - default: - log_warn("block type %d not implemented\n", b->tag); - break; - } - b = b->next; - } - *result = html; - return 0; - error: - return -1; -} - -// Convert an inline list to HTML. Returns 0 on success, and sets result. -extern int inlines_to_html(inl* ils, bstring* result) -{ - bstring contents = NULL; - bstring html = blk2bstr("", 0); - bstring mbtitle, escaped, escaped2; - - while(ils != NULL) { - switch(ils->tag) { - case str: - escaped = escape_html(ils->content.literal, false); - bformata(html, "%s", escaped->data); - bdestroy(escaped); - break; - case linebreak: - bformata(html, "<br />\n"); - break; - case softbreak: - bformata(html, "\n"); - break; - case code: - escaped = escape_html(ils->content.literal, false); - bformata(html, "<code>%s</code>", escaped->data); - bdestroy(escaped); - break; - case raw_html: - case entity: - bformata(html, "%s", ils->content.literal->data); - break; - case link: - check(inlines_to_html(ils->content.inlines, &contents) == 0, - "error converting inlines to html"); - if (blength(ils->content.linkable.title) > 0) { - escaped = escape_html(ils->content.linkable.title, true); - mbtitle = bformat(" title=\"%s\"", escaped->data); - bdestroy(escaped); - } else { - mbtitle = blk2bstr("",0); - } - escaped = escape_html(ils->content.linkable.url, true); - bformata(html, "<a href=\"%s\"%s>%s</a>", - escaped->data, - mbtitle->data, - contents->data); - bdestroy(escaped); - bdestroy(mbtitle); - bdestroy(contents); - break; - case image: - check(inlines_to_html(ils->content.inlines, &contents) == 0, - "error converting inlines to html"); - escaped = escape_html(ils->content.linkable.url, true); - escaped2 = escape_html(contents, false); - bdestroy(contents); - bformata(html, "<img src=\"%s\" alt=\"%s\"", - escaped->data, escaped2->data); - bdestroy(escaped); - bdestroy(escaped2); - if (blength(ils->content.linkable.title) > 0) { - escaped = escape_html(ils->content.linkable.title, true); - bformata(html, " title=\"%s\"", escaped->data); - bdestroy(escaped); - } - bformata(html, " />"); - break; - case strong: - check(inlines_to_html(ils->content.inlines, &contents) == 0, - "error converting inlines to html"); - bformata(html, "<strong>%s</strong>", contents->data); - bdestroy(contents); - break; - case emph: - check(inlines_to_html(ils->content.inlines, &contents) == 0, - "error converting inlines to html"); - bformata(html, "<em>%s</em>", contents->data); - bdestroy(contents); - break; - } - ils = ils->next; - } - *result = html; - return 0; - error: - return -1; -} diff --git a/src/html/houdini.h b/src/html/houdini.h new file mode 100644 index 0000000..5fd690d --- /dev/null +++ b/src/html/houdini.h @@ -0,0 +1,46 @@ +#ifndef __HOUDINI_H__ +#define __HOUDINI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include "buffer.h" + +#define likely(x) __builtin_expect((x),1) +#define unlikely(x) __builtin_expect((x),0) + +#ifdef HOUDINI_USE_LOCALE +# define _isxdigit(c) isxdigit(c) +# define _isdigit(c) isdigit(c) +#else +/* + * Helper _isdigit methods -- do not trust the current locale + * */ +# define _isxdigit(c) (strchr("0123456789ABCDEFabcdef", (c)) != NULL) +# define _isdigit(c) ((c) >= '0' && (c) <= '9') +#endif + +#define HOUDINI_ESCAPED_SIZE(x) (((x) * 12) / 10) +#define HOUDINI_UNESCAPED_SIZE(x) (x) + +extern size_t houdini_unescape_ent(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_html(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_html0(strbuf *ob, const uint8_t *src, size_t size, int secure); +extern int houdini_unescape_html(strbuf *ob, const uint8_t *src, size_t size); +extern void houdini_unescape_html_f(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_xml(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_uri(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_url(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_href(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_unescape_uri(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_unescape_url(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_js(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_unescape_js(strbuf *ob, const uint8_t *src, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/html/houdini_href_e.c b/src/html/houdini_href_e.c new file mode 100644 index 0000000..12456ce --- /dev/null +++ b/src/html/houdini_href_e.c @@ -0,0 +1,107 @@ +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include "html/houdini.h" + +/* + * The following characters will not be escaped: + * + * -_.+!*'(),%#@?=;:/,+&$ alphanum + * + * Note that this character set is the addition of: + * + * - The characters which are safe to be in an URL + * - The characters which are *not* safe to be in + * an URL because they are RESERVED characters. + * + * We asume (lazily) that any RESERVED char that + * appears inside an URL is actually meant to + * have its native function (i.e. as an URL + * component/separator) and hence needs no escaping. + * + * There are two exceptions: the chacters & (amp) + * and ' (single quote) do not appear in the table. + * They are meant to appear in the URL as components, + * yet they require special HTML-entity escaping + * to generate valid HTML markup. + * + * All other characters will be escaped to %XX. + * + */ +static const char HREF_SAFE[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +int +houdini_escape_href(strbuf *ob, const uint8_t *src, size_t size) +{ + static const uint8_t hex_chars[] = "0123456789ABCDEF"; + size_t i = 0, org; + uint8_t hex_str[3]; + + hex_str[0] = '%'; + + while (i < size) { + org = i; + while (i < size && HREF_SAFE[src[i]] != 0) + i++; + + if (likely(i > org)) + strbuf_put(ob, src + org, i - org); + + /* escaping */ + if (i >= size) + break; + + switch (src[i]) { + /* amp appears all the time in URLs, but needs + * HTML-entity escaping to be inside an href */ + case '&': + strbuf_puts(ob, "&"); + break; + + /* the single quote is a valid URL character + * according to the standard; it needs HTML + * entity escaping too */ + case '\'': + strbuf_puts(ob, "'"); + break; + + /* the space can be escaped to %20 or a plus + * sign. we're going with the generic escape + * for now. the plus thing is more commonly seen + * when building GET strings */ +#if 0 + case ' ': + strbuf_putc(ob, '+'); + break; +#endif + + /* every other character goes with a %XX escaping */ + default: + hex_str[1] = hex_chars[(src[i] >> 4) & 0xF]; + hex_str[2] = hex_chars[src[i] & 0xF]; + strbuf_put(ob, hex_str, 3); + } + + i++; + } + + return 1; +} diff --git a/src/html/houdini_html_e.c b/src/html/houdini_html_e.c new file mode 100644 index 0000000..f2e86fe --- /dev/null +++ b/src/html/houdini_html_e.c @@ -0,0 +1,81 @@ +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include "html/houdini.h" + +/** + * According to the OWASP rules: + * + * & --> & + * < --> < + * > --> > + * " --> " + * ' --> ' ' is not recommended + * / --> / forward slash is included as it helps end an HTML entity + * + */ +static const char HTML_ESCAPE_TABLE[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const char *HTML_ESCAPES[] = { + "", + """, + "&", + "'", + "/", + "<", + ">" +}; + +int +houdini_escape_html0(strbuf *ob, const uint8_t *src, size_t size, int secure) +{ + size_t i = 0, org, esc = 0; + + while (i < size) { + org = i; + while (i < size && (esc = HTML_ESCAPE_TABLE[src[i]]) == 0) + i++; + + if (i > org) + strbuf_put(ob, src + org, i - org); + + /* escaping */ + if (unlikely(i >= size)) + break; + + /* The forward slash is only escaped in secure mode */ + if ((src[i] == '/' || src[i] == '\'') && !secure) { + strbuf_putc(ob, src[i]); + } else { + strbuf_puts(ob, HTML_ESCAPES[esc]); + } + + i++; + } + + return 1; +} + +int +houdini_escape_html(strbuf *ob, const uint8_t *src, size_t size) +{ + return houdini_escape_html0(ob, src, size, 1); +} diff --git a/src/html/houdini_html_u.c b/src/html/houdini_html_u.c new file mode 100644 index 0000000..49b4956 --- /dev/null +++ b/src/html/houdini_html_u.c @@ -0,0 +1,111 @@ +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include "houdini.h" +#include "utf8.h" +#include "html_unescape.h" + +size_t +houdini_unescape_ent(strbuf *ob, const uint8_t *src, size_t size) +{ + size_t i = 0; + + if (size > 3 && src[0] == '#') { + int codepoint = 0; + + if (_isdigit(src[1])) { + for (i = 1; i < size && _isdigit(src[i]); ++i) { + int cp = (codepoint * 10) + (src[i] - '0'); + + if (cp < codepoint) + return 0; + + codepoint = cp; + } + } + + else if (src[1] == 'x' || src[1] == 'X') { + for (i = 2; i < size && _isxdigit(src[i]); ++i) { + int cp = (codepoint * 16) + ((src[i] | 32) % 39 - 9); + + if (cp < codepoint) + return 0; + + codepoint = cp; + } + } + + if (i < size && src[i] == ';' && codepoint) { + utf8proc_encode_char(codepoint, ob); + return i + 1; + } + } + + else { + if (size > MAX_WORD_LENGTH) + size = MAX_WORD_LENGTH; + + for (i = MIN_WORD_LENGTH; i < size; ++i) { + if (src[i] == ' ') + break; + + if (src[i] == ';') { + const struct html_ent *entity = find_entity((char *)src, i); + + if (entity != NULL) { + strbuf_put(ob, entity->utf8, entity->utf8_len); + return i + 1; + } + + break; + } + } + } + + return 0; +} + +int +houdini_unescape_html(strbuf *ob, const uint8_t *src, size_t size) +{ + size_t i = 0, org, ent; + + while (i < size) { + org = i; + while (i < size && src[i] != '&') + i++; + + if (likely(i > org)) { + if (unlikely(org == 0)) { + if (i >= size) + return 0; + + strbuf_grow(ob, HOUDINI_UNESCAPED_SIZE(size)); + } + + strbuf_put(ob, src + org, i - org); + } + + /* escaping */ + if (i >= size) + break; + + i++; + + ent = houdini_unescape_ent(ob, src + i, size - i); + i += ent; + + /* not really an entity */ + if (ent == 0) + strbuf_putc(ob, '&'); + } + + return 1; +} + +void houdini_unescape_html_f(strbuf *ob, const uint8_t *src, size_t size) +{ + if (!houdini_unescape_html(ob, src, size)) + strbuf_put(ob, src, size); +} diff --git a/src/html/html.c b/src/html/html.c new file mode 100644 index 0000000..ab6fc35 --- /dev/null +++ b/src/html/html.c @@ -0,0 +1,228 @@ +#include <stdlib.h> +#include <stdio.h> +#include <stdbool.h> +#include <string.h> +#include <assert.h> + +#include "stmd.h" +#include "debug.h" +#include "html/houdini.h" + +// Functions to convert node_block and inline lists to HTML strings. + +static void escape_html(strbuf *dest, const unsigned char *source, int length) +{ + if (length < 0) + length = strlen((char *)source); + + houdini_escape_html0(dest, source, (size_t)length, 0); +} + +static void escape_href(strbuf *dest, const unsigned char *source, int length) +{ + if (length < 0) + length = strlen((char *)source); + + houdini_escape_href(dest, source, (size_t)length); +} + +static inline void cr(strbuf *html) +{ + if (html->size && html->ptr[html->size - 1] != '\n') + strbuf_putc(html, '\n'); +} + +// Convert an inline list to HTML. Returns 0 on success, and sets result. +static void inlines_to_html(strbuf *html, node_inl* ils) +{ + strbuf scrap = GH_BUF_INIT; + + while(ils != NULL) { + switch(ils->tag) { + case INL_STRING: + escape_html(html, ils->content.literal.data, ils->content.literal.len); + break; + + case INL_LINEBREAK: + strbuf_puts(html, "<br />\n"); + break; + + case INL_SOFTBREAK: + strbuf_putc(html, '\n'); + break; + + case INL_CODE: + strbuf_puts(html, "<code>"); + escape_html(html, ils->content.literal.data, ils->content.literal.len); + strbuf_puts(html, "</code>"); + break; + + case INL_RAW_HTML: + strbuf_put(html, + ils->content.literal.data, + ils->content.literal.len); + break; + + case INL_LINK: + strbuf_puts(html, "<a href=\""); + if (ils->content.linkable.url) + escape_href(html, ils->content.linkable.url, -1); + + if (ils->content.linkable.title) { + strbuf_puts(html, "\" title=\""); + escape_html(html, ils->content.linkable.title, -1); + } + + strbuf_puts(html, "\">"); + inlines_to_html(html, ils->content.inlines); + strbuf_puts(html, "</a>"); + break; + + case INL_IMAGE: + strbuf_puts(html, "<img src=\""); + if (ils->content.linkable.url) + escape_href(html, ils->content.linkable.url, -1); + + inlines_to_html(&scrap, ils->content.inlines); + strbuf_puts(html, "\" alt=\""); + if (scrap.size) + escape_html(html, scrap.ptr, scrap.size); + strbuf_clear(&scrap); + + if (ils->content.linkable.title) { + strbuf_puts(html, "\" title=\""); + escape_html(html, ils->content.linkable.title, -1); + } + + strbuf_puts(html, "\"/>"); + break; + + case INL_STRONG: + strbuf_puts(html, "<strong>"); + inlines_to_html(html, ils->content.inlines); + strbuf_puts(html, "</strong>"); + break; + + case INL_EMPH: + strbuf_puts(html, "<em>"); + inlines_to_html(html, ils->content.inlines); + strbuf_puts(html, "</em>"); + break; + } + ils = ils->next; + } + + strbuf_free(&scrap); +} + +// Convert a node_block list to HTML. Returns 0 on success, and sets result. +static void blocks_to_html(strbuf *html, node_block *b, bool tight) +{ + struct ListData *data; + + while(b != NULL) { + switch(b->tag) { + case BLOCK_DOCUMENT: + blocks_to_html(html, b->children, false); + break; + + case BLOCK_PARAGRAPH: + if (tight) { + inlines_to_html(html, b->inline_content); + } else { + cr(html); + strbuf_puts(html, "<p>"); + inlines_to_html(html, b->inline_content); + strbuf_puts(html, "</p>\n"); + } + break; + + case BLOCK_BQUOTE: + cr(html); + strbuf_puts(html, "<blockquote>\n"); + blocks_to_html(html, b->children, false); + strbuf_puts(html, "</blockquote>\n"); + break; + + case BLOCK_LIST_ITEM: + cr(html); + strbuf_puts(html, "<li>"); + blocks_to_html(html, b->children, tight); + strbuf_trim(html); /* TODO: rtrim */ + strbuf_puts(html, "</li>\n"); + break; + + case BLOCK_LIST: + // make sure a list starts at the beginning of the line: + cr(html); + data = &(b->as.list); + + if (data->start > 1) { + strbuf_printf(html, "<%s start=\"%d\">\n", + data->list_type == bullet ? "ul" : "ol", + data->start); + } else { + strbuf_puts(html, data->list_type == bullet ? "<ul>\n" : "<ol>\n"); + } + + blocks_to_html(html, b->children, data->tight); + strbuf_puts(html, data->list_type == bullet ? "</ul>" : "</ol>"); + strbuf_putc(html, '\n'); + break; + + case BLOCK_ATX_HEADER: + case BLOCK_SETEXT_HEADER: + cr(html); + strbuf_printf(html, "<h%d>", b->as.header.level); + inlines_to_html(html, b->inline_content); + strbuf_printf(html, "</h%d>\n", b->as.header.level); + break; + + case BLOCK_INDENTED_CODE: + case BLOCK_FENCED_CODE: + cr(html); + + strbuf_puts(html, "<pre><code"); + + if (b->tag == BLOCK_FENCED_CODE) { + strbuf *info = &b->as.code.info; + + if (strbuf_len(info) > 0) { + int first_tag = strbuf_strchr(info, ' ', 0); + if (first_tag < 0) + first_tag = strbuf_len(info); + + strbuf_puts(html, " class=\"language-"); + escape_html(html, info->ptr, first_tag); + strbuf_putc(html, '"'); + } + } + + strbuf_putc(html, '>'); + escape_html(html, b->string_content.ptr, b->string_content.size); + strbuf_puts(html, "</code></pre>\n"); + break; + + case BLOCK_HTML: + strbuf_put(html, b->string_content.ptr, b->string_content.size); + break; + + case BLOCK_HRULE: + strbuf_puts(html, "<hr />\n"); + break; + + case BLOCK_REFERENCE_DEF: + break; + + default: + assert(false); + } + + b = b->next; + } +} + +void stmd_render_html(strbuf *html, node_block *root) +{ + blocks_to_html(html, root, false); +} diff --git a/src/html/html_unescape.gperf b/src/html/html_unescape.gperf new file mode 100644 index 0000000..4d46f67 --- /dev/null +++ b/src/html/html_unescape.gperf @@ -0,0 +1,2131 @@ +struct html_ent { + const char *entity; + unsigned int utf8_len; + unsigned char utf8[4]; +}; +%% +"Aacute", 2, {195, 129} +"aacute", 2, {195, 161} +"Abreve", 2, {196, 130} +"abreve", 2, {196, 131} +"ac", 3, {226, 136, 190} +"acd", 3, {226, 136, 191} +"acE", 3, {226, 136, 190} +"Acirc", 2, {195, 130} +"acirc", 2, {195, 162} +"acute", 2, {194, 180} +"Acy", 2, {208, 144} +"acy", 2, {208, 176} +"AElig", 2, {195, 134} +"aelig", 2, {195, 166} +"af", 3, {226, 129, 161} +"Afr", 4, {240, 157, 148, 132} +"afr", 4, {240, 157, 148, 158} +"Agrave", 2, {195, 128} +"agrave", 2, {195, 160} +"alefsym", 3, {226, 132, 181} +"aleph", 3, {226, 132, 181} +"Alpha", 2, {206, 145} +"alpha", 2, {206, 177} +"Amacr", 2, {196, 128} +"amacr", 2, {196, 129} +"amalg", 3, {226, 168, 191} +"amp", 1, {38} +"AMP", 1, {38} +"andand", 3, {226, 169, 149} +"And", 3, {226, 169, 147} +"and", 3, {226, 136, 167} +"andd", 3, {226, 169, 156} +"andslope", 3, {226, 169, 152} +"andv", 3, {226, 169, 154} +"ang", 3, {226, 136, 160} +"ange", 3, {226, 166, 164} +"angle", 3, {226, 136, 160} +"angmsdaa", 3, {226, 166, 168} +"angmsdab", 3, {226, 166, 169} +"angmsdac", 3, {226, 166, 170} +"angmsdad", 3, {226, 166, 171} +"angmsdae", 3, {226, 166, 172} +"angmsdaf", 3, {226, 166, 173} +"angmsdag", 3, {226, 166, 174} +"angmsdah", 3, {226, 166, 175} +"angmsd", 3, {226, 136, 161} +"angrt", 3, {226, 136, 159} +"angrtvb", 3, {226, 138, 190} +"angrtvbd", 3, {226, 166, 157} +"angsph", 3, {226, 136, 162} +"angst", 2, {195, 133} +"angzarr", 3, {226, 141, 188} +"Aogon", 2, {196, 132} +"aogon", 2, {196, 133} +"Aopf", 4, {240, 157, 148, 184} +"aopf", 4, {240, 157, 149, 146} +"apacir", 3, {226, 169, 175} +"ap", 3, {226, 137, 136} +"apE", 3, {226, 169, 176} +"ape", 3, {226, 137, 138} +"apid", 3, {226, 137, 139} +"apos", 1, {39} +"ApplyFunction", 3, {226, 129, 161} +"approx", 3, {226, 137, 136} +"approxeq", 3, {226, 137, 138} +"Aring", 2, {195, 133} +"aring", 2, {195, 165} +"Ascr", 4, {240, 157, 146, 156} +"ascr", 4, {240, 157, 146, 182} +"Assign", 3, {226, 137, 148} +"ast", 1, {42} +"asymp", 3, {226, 137, 136} +"asympeq", 3, {226, 137, 141} +"Atilde", 2, {195, 131} +"atilde", 2, {195, 163} +"Auml", 2, {195, 132} +"auml", 2, {195, 164} +"awconint", 3, {226, 136, 179} +"awint", 3, {226, 168, 145} +"backcong", 3, {226, 137, 140} +"backepsilon", 2, {207, 182} +"backprime", 3, {226, 128, 181} +"backsim", 3, {226, 136, 189} +"backsimeq", 3, {226, 139, 141} +"Backslash", 3, {226, 136, 150} +"Barv", 3, {226, 171, 167} +"barvee", 3, {226, 138, 189} +"barwed", 3, {226, 140, 133} +"Barwed", 3, {226, 140, 134} +"barwedge", 3, {226, 140, 133} +"bbrk", 3, {226, 142, 181} +"bbrktbrk", 3, {226, 142, 182} +"bcong", 3, {226, 137, 140} +"Bcy", 2, {208, 145} +"bcy", 2, {208, 177} +"bdquo", 3, {226, 128, 158} +"becaus", 3, {226, 136, 181} +"because", 3, {226, 136, 181} +"Because", 3, {226, 136, 181} +"bemptyv", 3, {226, 166, 176} +"bepsi", 2, {207, 182} +"bernou", 3, {226, 132, 172} +"Bernoullis", 3, {226, 132, 172} +"Beta", 2, {206, 146} +"beta", 2, {206, 178} +"beth", 3, {226, 132, 182} +"between", 3, {226, 137, 172} +"Bfr", 4, {240, 157, 148, 133} +"bfr", 4, {240, 157, 148, 159} +"bigcap", 3, {226, 139, 130} +"bigcirc", 3, {226, 151, 175} +"bigcup", 3, {226, 139, 131} +"bigodot", 3, {226, 168, 128} +"bigoplus", 3, {226, 168, 129} +"bigotimes", 3, {226, 168, 130} +"bigsqcup", 3, {226, 168, 134} +"bigstar", 3, {226, 152, 133} +"bigtriangledown", 3, {226, 150, 189} +"bigtriangleup", 3, {226, 150, 179} +"biguplus", 3, {226, 168, 132} +"bigvee", 3, {226, 139, 129} +"bigwedge", 3, {226, 139, 128} +"bkarow", 3, {226, 164, 141} +"blacklozenge", 3, {226, 167, 171} +"blacksquare", 3, {226, 150, 170} +"blacktriangle", 3, {226, 150, 180} +"blacktriangledown", 3, {226, 150, 190} +"blacktriangleleft", 3, {226, 151, 130} +"blacktriangleright", 3, {226, 150, 184} +"blank", 3, {226, 144, 163} +"blk12", 3, {226, 150, 146} +"blk14", 3, {226, 150, 145} +"blk34", 3, {226, 150, 147} +"block", 3, {226, 150, 136} +"bne", 1, {61} +"bnequiv", 3, {226, 137, 161} +"bNot", 3, {226, 171, 173} +"bnot", 3, {226, 140, 144} +"Bopf", 4, {240, 157, 148, 185} +"bopf", 4, {240, 157, 149, 147} +"bot", 3, {226, 138, 165} +"bottom", 3, {226, 138, 165} +"bowtie", 3, {226, 139, 136} +"boxbox", 3, {226, 167, 137} +"boxdl", 3, {226, 148, 144} +"boxdL", 3, {226, 149, 149} +"boxDl", 3, {226, 149, 150} +"boxDL", 3, {226, 149, 151} +"boxdr", 3, {226, 148, 140} +"boxdR", 3, {226, 149, 146} +"boxDr", 3, {226, 149, 147} +"boxDR", 3, {226, 149, 148} +"boxh", 3, {226, 148, 128} +"boxH", 3, {226, 149, 144} +"boxhd", 3, {226, 148, 172} +"boxHd", 3, {226, 149, 164} +"boxhD", 3, {226, 149, 165} +"boxHD", 3, {226, 149, 166} +"boxhu", 3, {226, 148, 180} +"boxHu", 3, {226, 149, 167} +"boxhU", 3, {226, 149, 168} +"boxHU", 3, {226, 149, 169} +"boxminus", 3, {226, 138, 159} +"boxplus", 3, {226, 138, 158} +"boxtimes", 3, {226, 138, 160} +"boxul", 3, {226, 148, 152} +"boxuL", 3, {226, 149, 155} +"boxUl", 3, {226, 149, 156} +"boxUL", 3, {226, 149, 157} +"boxur", 3, {226, 148, 148} +"boxuR", 3, {226, 149, 152} +"boxUr", 3, {226, 149, 153} +"boxUR", 3, {226, 149, 154} +"boxv", 3, {226, 148, 130} +"boxV", 3, {226, 149, 145} +"boxvh", 3, {226, 148, 188} +"boxvH", 3, {226, 149, 170} +"boxVh", 3, {226, 149, 171} +"boxVH", 3, {226, 149, 172} +"boxvl", 3, {226, 148, 164} +"boxvL", 3, {226, 149, 161} +"boxVl", 3, {226, 149, 162} +"boxVL", 3, {226, 149, 163} +"boxvr", 3, {226, 148, 156} +"boxvR", 3, {226, 149, 158} +"boxVr", 3, {226, 149, 159} +"boxVR", 3, {226, 149, 160} +"bprime", 3, {226, 128, 181} +"breve", 2, {203, 152} +"Breve", 2, {203, 152} +"brvbar", 2, {194, 166} +"bscr", 4, {240, 157, 146, 183} +"Bscr", 3, {226, 132, 172} +"bsemi", 3, {226, 129, 143} +"bsim", 3, {226, 136, 189} +"bsime", 3, {226, 139, 141} +"bsolb", 3, {226, 167, 133} +"bsol", 1, {92} +"bsolhsub", 3, {226, 159, 136} +"bull", 3, {226, 128, 162} +"bullet", 3, {226, 128, 162} +"bump", 3, {226, 137, 142} +"bumpE", 3, {226, 170, 174} +"bumpe", 3, {226, 137, 143} +"Bumpeq", 3, {226, 137, 142} +"bumpeq", 3, {226, 137, 143} +"Cacute", 2, {196, 134} +"cacute", 2, {196, 135} +"capand", 3, {226, 169, 132} +"capbrcup", 3, {226, 169, 137} +"capcap", 3, {226, 169, 139} +"cap", 3, {226, 136, 169} +"Cap", 3, {226, 139, 146} +"capcup", 3, {226, 169, 135} +"capdot", 3, {226, 169, 128} +"CapitalDifferentialD", 3, {226, 133, 133} +"caps", 3, {226, 136, 169} +"caret", 3, {226, 129, 129} +"caron", 2, {203, 135} +"Cayleys", 3, {226, 132, 173} +"ccaps", 3, {226, 169, 141} +"Ccaron", 2, {196, 140} +"ccaron", 2, {196, 141} +"Ccedil", 2, {195, 135} +"ccedil", 2, {195, 167} +"Ccirc", 2, {196, 136} +"ccirc", 2, {196, 137} +"Cconint", 3, {226, 136, 176} +"ccups", 3, {226, 169, 140} +"ccupssm", 3, {226, 169, 144} +"Cdot", 2, {196, 138} +"cdot", 2, {196, 139} +"cedil", 2, {194, 184} +"Cedilla", 2, {194, 184} +"cemptyv", 3, {226, 166, 178} +"cent", 2, {194, 162} +"centerdot", 2, {194, 183} +"CenterDot", 2, {194, 183} +"cfr", 4, {240, 157, 148, 160} +"Cfr", 3, {226, 132, 173} +"CHcy", 2, {208, 167} +"chcy", 2, {209, 135} +"check", 3, {226, 156, 147} +"checkmark", 3, {226, 156, 147} +"Chi", 2, {206, 167} +"chi", 2, {207, 135} +"circ", 2, {203, 134} +"circeq", 3, {226, 137, 151} +"circlearrowleft", 3, {226, 134, 186} +"circlearrowright", 3, {226, 134, 187} +"circledast", 3, {226, 138, 155} +"circledcirc", 3, {226, 138, 154} +"circleddash", 3, {226, 138, 157} +"CircleDot", 3, {226, 138, 153} +"circledR", 2, {194, 174} +"circledS", 3, {226, 147, 136} +"CircleMinus", 3, {226, 138, 150} +"CirclePlus", 3, {226, 138, 149} +"CircleTimes", 3, {226, 138, 151} +"cir", 3, {226, 151, 139} +"cirE", 3, {226, 167, 131} +"cire", 3, {226, 137, 151} +"cirfnint", 3, {226, 168, 144} +"cirmid", 3, {226, 171, 175} +"cirscir", 3, {226, 167, 130} +"ClockwiseContourIntegral", 3, {226, 136, 178} +"CloseCurlyDoubleQuote", 3, {226, 128, 157} +"CloseCurlyQuote", 3, {226, 128, 153} +"clubs", 3, {226, 153, 163} +"clubsuit", 3, {226, 153, 163} +"colon", 1, {58} +"Colon", 3, {226, 136, 183} +"Colone", 3, {226, 169, 180} +"colone", 3, {226, 137, 148} +"coloneq", 3, {226, 137, 148} +"comma", 1, {44} +"commat", 1, {64} +"comp", 3, {226, 136, 129} +"compfn", 3, {226, 136, 152} +"complement", 3, {226, 136, 129} +"complexes", 3, {226, 132, 130} +"cong", 3, {226, 137, 133} +"congdot", 3, {226, 169, 173} +"Congruent", 3, {226, 137, 161} +"conint", 3, {226, 136, 174} +"Conint", 3, {226, 136, 175} +"ContourIntegral", 3, {226, 136, 174} +"copf", 4, {240, 157, 149, 148} +"Copf", 3, {226, 132, 130} +"coprod", 3, {226, 136, 144} +"Coproduct", 3, {226, 136, 144} +"copy", 2, {194, 169} +"COPY", 2, {194, 169} +"copysr", 3, {226, 132, 151} +"CounterClockwiseContourIntegral", 3, {226, 136, 179} +"crarr", 3, {226, 134, 181} +"cross", 3, {226, 156, 151} +"Cross", 3, {226, 168, 175} +"Cscr", 4, {240, 157, 146, 158} +"cscr", 4, {240, 157, 146, 184} +"csub", 3, {226, 171, 143} +"csube", 3, {226, 171, 145} +"csup", 3, {226, 171, 144} +"csupe", 3, {226, 171, 146} +"ctdot", 3, {226, 139, 175} +"cudarrl", 3, {226, 164, 184} +"cudarrr", 3, {226, 164, 181} +"cuepr", 3, {226, 139, 158} +"cuesc", 3, {226, 139, 159} +"cularr", 3, {226, 134, 182} +"cularrp", 3, {226, 164, 189} +"cupbrcap", 3, {226, 169, 136} +"cupcap", 3, {226, 169, 134} +"CupCap", 3, {226, 137, 141} +"cup", 3, {226, 136, 170} +"Cup", 3, {226, 139, 147} +"cupcup", 3, {226, 169, 138} +"cupdot", 3, {226, 138, 141} +"cupor", 3, {226, 169, 133} +"cups", 3, {226, 136, 170} +"curarr", 3, {226, 134, 183} +"curarrm", 3, {226, 164, 188} +"curlyeqprec", 3, {226, 139, 158} +"curlyeqsucc", 3, {226, 139, 159} +"curlyvee", 3, {226, 139, 142} +"curlywedge", 3, {226, 139, 143} +"curren", 2, {194, 164} +"curvearrowleft", 3, {226, 134, 182} +"curvearrowright", 3, {226, 134, 183} +"cuvee", 3, {226, 139, 142} +"cuwed", 3, {226, 139, 143} +"cwconint", 3, {226, 136, 178} +"cwint", 3, {226, 136, 177} +"cylcty", 3, {226, 140, 173} +"dagger", 3, {226, 128, 160} +"Dagger", 3, {226, 128, 161} +"daleth", 3, {226, 132, 184} +"darr", 3, {226, 134, 147} +"Darr", 3, {226, 134, 161} +"dArr", 3, {226, 135, 147} +"dash", 3, {226, 128, 144} +"Dashv", 3, {226, 171, 164} +"dashv", 3, {226, 138, 163} +"dbkarow", 3, {226, 164, 143} +"dblac", 2, {203, 157} +"Dcaron", 2, {196, 142} +"dcaron", 2, {196, 143} +"Dcy", 2, {208, 148} +"dcy", 2, {208, 180} +"ddagger", 3, {226, 128, 161} +"ddarr", 3, {226, 135, 138} +"DD", 3, {226, 133, 133} +"dd", 3, {226, 133, 134} +"DDotrahd", 3, {226, 164, 145} +"ddotseq", 3, {226, 169, 183} +"deg", 2, {194, 176} +"Del", 3, {226, 136, 135} +"Delta", 2, {206, 148} +"delta", 2, {206, 180} +"demptyv", 3, {226, 166, 177} +"dfisht", 3, {226, 165, 191} +"Dfr", 4, {240, 157, 148, 135} +"dfr", 4, {240, 157, 148, 161} +"dHar", 3, {226, 165, 165} +"dharl", 3, {226, 135, 131} +"dharr", 3, {226, 135, 130} +"DiacriticalAcute", 2, {194, 180} +"DiacriticalDot", 2, {203, 153} +"DiacriticalDoubleAcute", 2, {203, 157} +"DiacriticalGrave", 1, {96} +"DiacriticalTilde", 2, {203, 156} +"diam", 3, {226, 139, 132} +"diamond", 3, {226, 139, 132} +"Diamond", 3, {226, 139, 132} +"diamondsuit", 3, {226, 153, 166} +"diams", 3, {226, 153, 166} +"die", 2, {194, 168} +"DifferentialD", 3, {226, 133, 134} +"digamma", 2, {207, 157} +"disin", 3, {226, 139, 178} +"div", 2, {195, 183} +"divide", 2, {195, 183} +"divideontimes", 3, {226, 139, 135} +"divonx", 3, {226, 139, 135} +"DJcy", 2, {208, 130} +"djcy", 2, {209, 146} +"dlcorn", 3, {226, 140, 158} +"dlcrop", 3, {226, 140, 141} +"dollar", 1, {36} +"Dopf", 4, {240, 157, 148, 187} +"dopf", 4, {240, 157, 149, 149} +"Dot", 2, {194, 168} +"dot", 2, {203, 153} +"DotDot", 3, {226, 131, 156} +"doteq", 3, {226, 137, 144} +"doteqdot", 3, {226, 137, 145} +"DotEqual", 3, {226, 137, 144} +"dotminus", 3, {226, 136, 184} +"dotplus", 3, {226, 136, 148} +"dotsquare", 3, {226, 138, 161} +"doublebarwedge", 3, {226, 140, 134} +"DoubleContourIntegral", 3, {226, 136, 175} +"DoubleDot", 2, {194, 168} +"DoubleDownArrow", 3, {226, 135, 147} +"DoubleLeftArrow", 3, {226, 135, 144} +"DoubleLeftRightArrow", 3, {226, 135, 148} +"DoubleLeftTee", 3, {226, 171, 164} +"DoubleLongLeftArrow", 3, {226, 159, 184} +"DoubleLongLeftRightArrow", 3, {226, 159, 186} +"DoubleLongRightArrow", 3, {226, 159, 185} +"DoubleRightArrow", 3, {226, 135, 146} +"DoubleRightTee", 3, {226, 138, 168} +"DoubleUpArrow", 3, {226, 135, 145} +"DoubleUpDownArrow", 3, {226, 135, 149} +"DoubleVerticalBar", 3, {226, 136, 165} +"DownArrowBar", 3, {226, 164, 147} +"downarrow", 3, {226, 134, 147} +"DownArrow", 3, {226, 134, 147} +"Downarrow", 3, {226, 135, 147} +"DownArrowUpArrow", 3, {226, 135, 181} +"DownBreve", 2, {204, 145} +"downdownarrows", 3, {226, 135, 138} +"downharpoonleft", 3, {226, 135, 131} +"downharpoonright", 3, {226, 135, 130} +"DownLeftRightVector", 3, {226, 165, 144} +"DownLeftTeeVector", 3, {226, 165, 158} +"DownLeftVectorBar", 3, {226, 165, 150} +"DownLeftVector", 3, {226, 134, 189} +"DownRightTeeVector", 3, {226, 165, 159} +"DownRightVectorBar", 3, {226, 165, 151} +"DownRightVector", 3, {226, 135, 129} +"DownTeeArrow", 3, {226, 134, 167} +"DownTee", 3, {226, 138, 164} +"drbkarow", 3, {226, 164, 144} +"drcorn", 3, {226, 140, 159} +"drcrop", 3, {226, 140, 140} +"Dscr", 4, {240, 157, 146, 159} +"dscr", 4, {240, 157, 146, 185} +"DScy", 2, {208, 133} +"dscy", 2, {209, 149} +"dsol", 3, {226, 167, 182} +"Dstrok", 2, {196, 144} +"dstrok", 2, {196, 145} +"dtdot", 3, {226, 139, 177} +"dtri", 3, {226, 150, 191} +"dtrif", 3, {226, 150, 190} +"duarr", 3, {226, 135, 181} +"duhar", 3, {226, 165, 175} +"dwangle", 3, {226, 166, 166} +"DZcy", 2, {208, 143} +"dzcy", 2, {209, 159} +"dzigrarr", 3, {226, 159, 191} +"Eacute", 2, {195, 137} +"eacute", 2, {195, 169} +"easter", 3, {226, 169, 174} +"Ecaron", 2, {196, 154} +"ecaron", 2, {196, 155} +"Ecirc", 2, {195, 138} +"ecirc", 2, {195, 170} +"ecir", 3, {226, 137, 150} +"ecolon", 3, {226, 137, 149} +"Ecy", 2, {208, 173} +"ecy", 2, {209, 141} +"eDDot", 3, {226, 169, 183} +"Edot", 2, {196, 150} +"edot", 2, {196, 151} +"eDot", 3, {226, 137, 145} +"ee", 3, {226, 133, 135} +"efDot", 3, {226, 137, 146} +"Efr", 4, {240, 157, 148, 136} +"efr", 4, {240, 157, 148, 162} +"eg", 3, {226, 170, 154} +"Egrave", 2, {195, 136} +"egrave", 2, {195, 168} +"egs", 3, {226, 170, 150} +"egsdot", 3, {226, 170, 152} +"el", 3, {226, 170, 153} +"Element", 3, {226, 136, 136} +"elinters", 3, {226, 143, 167} +"ell", 3, {226, 132, 147} +"els", 3, {226, 170, 149} +"elsdot", 3, {226, 170, 151} +"Emacr", 2, {196, 146} +"emacr", 2, {196, 147} +"empty", 3, {226, 136, 133} +"emptyset", 3, {226, 136, 133} +"EmptySmallSquare", 3, {226, 151, 187} +"emptyv", 3, {226, 136, 133} +"EmptyVerySmallSquare", 3, {226, 150, 171} +"emsp13", 3, {226, 128, 132} +"emsp14", 3, {226, 128, 133} +"emsp", 3, {226, 128, 131} +"ENG", 2, {197, 138} +"eng", 2, {197, 139} +"ensp", 3, {226, 128, 130} +"Eogon", 2, {196, 152} +"eogon", 2, {196, 153} +"Eopf", 4, {240, 157, 148, 188} +"eopf", 4, {240, 157, 149, 150} +"epar", 3, {226, 139, 149} +"eparsl", 3, {226, 167, 163} +"eplus", 3, {226, 169, 177} +"epsi", 2, {206, 181} +"Epsilon", 2, {206, 149} +"epsilon", 2, {206, 181} +"epsiv", 2, {207, 181} +"eqcirc", 3, {226, 137, 150} +"eqcolon", 3, {226, 137, 149} +"eqsim", 3, {226, 137, 130} +"eqslantgtr", 3, {226, 170, 150} +"eqslantless", 3, {226, 170, 149} +"Equal", 3, {226, 169, 181} +"equals", 1, {61} +"EqualTilde", 3, {226, 137, 130} +"equest", 3, {226, 137, 159} +"Equilibrium", 3, {226, 135, 140} +"equiv", 3, {226, 137, 161} +"equivDD", 3, {226, 169, 184} +"eqvparsl", 3, {226, 167, 165} +"erarr", 3, {226, 165, 177} +"erDot", 3, {226, 137, 147} +"escr", 3, {226, 132, 175} +"Escr", 3, {226, 132, 176} +"esdot", 3, {226, 137, 144} +"Esim", 3, {226, 169, 179} +"esim", 3, {226, 137, 130} +"Eta", 2, {206, 151} +"eta", 2, {206, 183} +"ETH", 2, {195, 144} +"eth", 2, {195, 176} +"Euml", 2, {195, 139} +"euml", 2, {195, 171} +"euro", 3, {226, 130, 172} +"excl", 1, {33} +"exist", 3, {226, 136, 131} +"Exists", 3, {226, 136, 131} +"expectation", 3, {226, 132, 176} +"exponentiale", 3, {226, 133, 135} +"ExponentialE", 3, {226, 133, 135} +"fallingdotseq", 3, {226, 137, 146} +"Fcy", 2, {208, 164} +"fcy", 2, {209, 132} +"female", 3, {226, 153, 128} +"ffilig", 3, {239, 172, 131} +"fflig", 3, {239, 172, 128} +"ffllig", 3, {239, 172, 132} +"Ffr", 4, {240, 157, 148, 137} +"ffr", 4, {240, 157, 148, 163} +"filig", 3, {239, 172, 129} +"FilledSmallSquare", 3, {226, 151, 188} +"FilledVerySmallSquare", 3, {226, 150, 170} +"fjlig", 1, {102} +"flat", 3, {226, 153, 173} +"fllig", 3, {239, 172, 130} +"fltns", 3, {226, 150, 177} +"fnof", 2, {198, 146} +"Fopf", 4, {240, 157, 148, 189} +"fopf", 4, {240, 157, 149, 151} +"forall", 3, {226, 136, 128} +"ForAll", 3, {226, 136, 128} +"fork", 3, {226, 139, 148} +"forkv", 3, {226, 171, 153} +"Fouriertrf", 3, {226, 132, 177} +"fpartint", 3, {226, 168, 141} +"frac12", 2, {194, 189} +"frac13", 3, {226, 133, 147} +"frac14", 2, {194, 188} +"frac15", 3, {226, 133, 149} +"frac16", 3, {226, 133, 153} +"frac18", 3, {226, 133, 155} +"frac23", 3, {226, 133, 148} +"frac25", 3, {226, 133, 150} +"frac34", 2, {194, 190} +"frac35", 3, {226, 133, 151} +"frac38", 3, {226, 133, 156} +"frac45", 3, {226, 133, 152} +"frac56", 3, {226, 133, 154} +"frac58", 3, {226, 133, 157} +"frac78", 3, {226, 133, 158} +"frasl", 3, {226, 129, 132} +"frown", 3, {226, 140, 162} +"fscr", 4, {240, 157, 146, 187} +"Fscr", 3, {226, 132, 177} +"gacute", 2, {199, 181} +"Gamma", 2, {206, 147} +"gamma", 2, {206, 179} +"Gammad", 2, {207, 156} +"gammad", 2, {207, 157} +"gap", 3, {226, 170, 134} +"Gbreve", 2, {196, 158} +"gbreve", 2, {196, 159} +"Gcedil", 2, {196, 162} +"Gcirc", 2, {196, 156} +"gcirc", 2, {196, 157} +"Gcy", 2, {208, 147} +"gcy", 2, {208, 179} +"Gdot", 2, {196, 160} +"gdot", 2, {196, 161} +"ge", 3, {226, 137, 165} +"gE", 3, {226, 137, 167} +"gEl", 3, {226, 170, 140} +"gel", 3, {226, 139, 155} +"geq", 3, {226, 137, 165} +"geqq", 3, {226, 137, 167} +"geqslant", 3, {226, 169, 190} +"gescc", 3, {226, 170, 169} +"ges", 3, {226, 169, 190} +"gesdot", 3, {226, 170, 128} +"gesdoto", 3, {226, 170, 130} +"gesdotol", 3, {226, 170, 132} +"gesl", 3, {226, 139, 155} +"gesles", 3, {226, 170, 148} +"Gfr", 4, {240, 157, 148, 138} +"gfr", 4, {240, 157, 148, 164} +"gg", 3, {226, 137, 171} +"Gg", 3, {226, 139, 153} +"ggg", 3, {226, 139, 153} +"gimel", 3, {226, 132, 183} +"GJcy", 2, {208, 131} +"gjcy", 2, {209, 147} +"gla", 3, {226, 170, 165} +"gl", 3, {226, 137, 183} +"glE", 3, {226, 170, 146} +"glj", 3, {226, 170, 164} +"gnap", 3, {226, 170, 138} +"gnapprox", 3, {226, 170, 138} +"gne", 3, {226, 170, 136} +"gnE", 3, {226, 137, 169} +"gneq", 3, {226, 170, 136} +"gneqq", 3, {226, 137, 169} +"gnsim", 3, {226, 139, 167} +"Gopf", 4, {240, 157, 148, 190} +"gopf", 4, {240, 157, 149, 152} +"grave", 1, {96} +"GreaterEqual", 3, {226, 137, 165} +"GreaterEqualLess", 3, {226, 139, 155} +"GreaterFullEqual", 3, {226, 137, 167} +"GreaterGreater", 3, {226, 170, 162} +"GreaterLess", 3, {226, 137, 183} +"GreaterSlantEqual", 3, {226, 169, 190} +"GreaterTilde", 3, {226, 137, 179} +"Gscr", 4, {240, 157, 146, 162} +"gscr", 3, {226, 132, 138} +"gsim", 3, {226, 137, 179} +"gsime", 3, {226, 170, 142} +"gsiml", 3, {226, 170, 144} +"gtcc", 3, {226, 170, 167} +"gtcir", 3, {226, 169, 186} +"gt", 1, {62} +"GT", 1, {62} +"Gt", 3, {226, 137, 171} +"gtdot", 3, {226, 139, 151} +"gtlPar", 3, {226, 166, 149} +"gtquest", 3, {226, 169, 188} +"gtrapprox", 3, {226, 170, 134} +"gtrarr", 3, {226, 165, 184} +"gtrdot", 3, {226, 139, 151} +"gtreqless", 3, {226, 139, 155} +"gtreqqless", 3, {226, 170, 140} +"gtrless", 3, {226, 137, 183} +"gtrsim", 3, {226, 137, 179} +"gvertneqq", 3, {226, 137, 169} +"gvnE", 3, {226, 137, 169} +"Hacek", 2, {203, 135} +"hairsp", 3, {226, 128, 138} +"half", 2, {194, 189} +"hamilt", 3, {226, 132, 139} +"HARDcy", 2, {208, 170} +"hardcy", 2, {209, 138} +"harrcir", 3, {226, 165, 136} +"harr", 3, {226, 134, 148} +"hArr", 3, {226, 135, 148} +"harrw", 3, {226, 134, 173} +"Hat", 1, {94} +"hbar", 3, {226, 132, 143} +"Hcirc", 2, {196, 164} +"hcirc", 2, {196, 165} +"hearts", 3, {226, 153, 165} +"heartsuit", 3, {226, 153, 165} +"hellip", 3, {226, 128, 166} +"hercon", 3, {226, 138, 185} +"hfr", 4, {240, 157, 148, 165} +"Hfr", 3, {226, 132, 140} +"HilbertSpace", 3, {226, 132, 139} +"hksearow", 3, {226, 164, 165} +"hkswarow", 3, {226, 164, 166} +"hoarr", 3, {226, 135, 191} +"homtht", 3, {226, 136, 187} +"hookleftarrow", 3, {226, 134, 169} +"hookrightarrow", 3, {226, 134, 170} +"hopf", 4, {240, 157, 149, 153} +"Hopf", 3, {226, 132, 141} +"horbar", 3, {226, 128, 149} +"HorizontalLine", 3, {226, 148, 128} +"hscr", 4, {240, 157, 146, 189} +"Hscr", 3, {226, 132, 139} +"hslash", 3, {226, 132, 143} +"Hstrok", 2, {196, 166} +"hstrok", 2, {196, 167} +"HumpDownHump", 3, {226, 137, 142} +"HumpEqual", 3, {226, 137, 143} +"hybull", 3, {226, 129, 131} +"hyphen", 3, {226, 128, 144} +"Iacute", 2, {195, 141} +"iacute", 2, {195, 173} +"ic", 3, {226, 129, 163} +"Icirc", 2, {195, 142} +"icirc", 2, {195, 174} +"Icy", 2, {208, 152} +"icy", 2, {208, 184} +"Idot", 2, {196, 176} +"IEcy", 2, {208, 149} +"iecy", 2, {208, 181} +"iexcl", 2, {194, 161} +"iff", 3, {226, 135, 148} +"ifr", 4, {240, 157, 148, 166} +"Ifr", 3, {226, 132, 145} +"Igrave", 2, {195, 140} +"igrave", 2, {195, 172} +"ii", 3, {226, 133, 136} +"iiiint", 3, {226, 168, 140} +"iiint", 3, {226, 136, 173} +"iinfin", 3, {226, 167, 156} +"iiota", 3, {226, 132, 169} +"IJlig", 2, {196, 178} +"ijlig", 2, {196, 179} +"Imacr", 2, {196, 170} +"imacr", 2, {196, 171} +"image", 3, {226, 132, 145} +"ImaginaryI", 3, {226, 133, 136} +"imagline", 3, {226, 132, 144} +"imagpart", 3, {226, 132, 145} +"imath", 2, {196, 177} +"Im", 3, {226, 132, 145} +"imof", 3, {226, 138, 183} +"imped", 2, {198, 181} +"Implies", 3, {226, 135, 146} +"incare", 3, {226, 132, 133} +"in", 3, {226, 136, 136} +"infin", 3, {226, 136, 158} +"infintie", 3, {226, 167, 157} +"inodot", 2, {196, 177} +"intcal", 3, {226, 138, 186} +"int", 3, {226, 136, 171} +"Int", 3, {226, 136, 172} +"integers", 3, {226, 132, 164} +"Integral", 3, {226, 136, 171} +"intercal", 3, {226, 138, 186} +"Intersection", 3, {226, 139, 130} +"intlarhk", 3, {226, 168, 151} +"intprod", 3, {226, 168, 188} +"InvisibleComma", 3, {226, 129, 163} +"InvisibleTimes", 3, {226, 129, 162} +"IOcy", 2, {208, 129} +"iocy", 2, {209, 145} +"Iogon", 2, {196, 174} +"iogon", 2, {196, 175} +"Iopf", 4, {240, 157, 149, 128} +"iopf", 4, {240, 157, 149, 154} +"Iota", 2, {206, 153} +"iota", 2, {206, 185} +"iprod", 3, {226, 168, 188} +"iquest", 2, {194, 191} +"iscr", 4, {240, 157, 146, 190} +"Iscr", 3, {226, 132, 144} +"isin", 3, {226, 136, 136} +"isindot", 3, {226, 139, 181} +"isinE", 3, {226, 139, 185} +"isins", 3, {226, 139, 180} +"isinsv", 3, {226, 139, 179} +"isinv", 3, {226, 136, 136} +"it", 3, {226, 129, 162} +"Itilde", 2, {196, 168} +"itilde", 2, {196, 169} +"Iukcy", 2, {208, 134} +"iukcy", 2, {209, 150} +"Iuml", 2, {195, 143} +"iuml", 2, {195, 175} +"Jcirc", 2, {196, 180} +"jcirc", 2, {196, 181} +"Jcy", 2, {208, 153} +"jcy", 2, {208, 185} +"Jfr", 4, {240, 157, 148, 141} +"jfr", 4, {240, 157, 148, 167} +"jmath", 2, {200, 183} +"Jopf", 4, {240, 157, 149, 129} +"jopf", 4, {240, 157, 149, 155} +"Jscr", 4, {240, 157, 146, 165} +"jscr", 4, {240, 157, 146, 191} +"Jsercy", 2, {208, 136} +"jsercy", 2, {209, 152} +"Jukcy", 2, {208, 132} +"jukcy", 2, {209, 148} +"Kappa", 2, {206, 154} +"kappa", 2, {206, 186} +"kappav", 2, {207, 176} +"Kcedil", 2, {196, 182} +"kcedil", 2, {196, 183} +"Kcy", 2, {208, 154} +"kcy", 2, {208, 186} +"Kfr", 4, {240, 157, 148, 142} +"kfr", 4, {240, 157, 148, 168} +"kgreen", 2, {196, 184} +"KHcy", 2, {208, 165} +"khcy", 2, {209, 133} +"KJcy", 2, {208, 140} +"kjcy", 2, {209, 156} +"Kopf", 4, {240, 157, 149, 130} +"kopf", 4, {240, 157, 149, 156} +"Kscr", 4, {240, 157, 146, 166} +"kscr", 4, {240, 157, 147, 128} +"lAarr", 3, {226, 135, 154} +"Lacute", 2, {196, 185} +"lacute", 2, {196, 186} +"laemptyv", 3, {226, 166, 180} +"lagran", 3, {226, 132, 146} +"Lambda", 2, {206, 155} +"lambda", 2, {206, 187} +"lang", 3, {226, 159, 168} +"Lang", 3, {226, 159, 170} +"langd", 3, {226, 166, 145} +"langle", 3, {226, 159, 168} +"lap", 3, {226, 170, 133} +"Laplacetrf", 3, {226, 132, 146} +"laquo", 2, {194, 171} +"larrb", 3, {226, 135, 164} +"larrbfs", 3, {226, 164, 159} +"larr", 3, {226, 134, 144} +"Larr", 3, {226, 134, 158} +"lArr", 3, {226, 135, 144} +"larrfs", 3, {226, 164, 157} +"larrhk", 3, {226, 134, 169} +"larrlp", 3, {226, 134, 171} +"larrpl", 3, {226, 164, 185} +"larrsim", 3, {226, 165, 179} +"larrtl", 3, {226, 134, 162} +"latail", 3, {226, 164, 153} +"lAtail", 3, {226, 164, 155} +"lat", 3, {226, 170, 171} +"late", 3, {226, 170, 173} +"lates", 3, {226, 170, 173} +"lbarr", 3, {226, 164, 140} +"lBarr", 3, {226, 164, 142} +"lbbrk", 3, {226, 157, 178} +"lbrace", 1, {123} +"lbrack", 1, {91} +"lbrke", 3, {226, 166, 139} +"lbrksld", 3, {226, 166, 143} +"lbrkslu", 3, {226, 166, 141} +"Lcaron", 2, {196, 189} +"lcaron", 2, {196, 190} +"Lcedil", 2, {196, 187} +"lcedil", 2, {196, 188} +"lceil", 3, {226, 140, 136} +"lcub", 1, {123} +"Lcy", 2, {208, 155} +"lcy", 2, {208, 187} +"ldca", 3, {226, 164, 182} +"ldquo", 3, {226, 128, 156} +"ldquor", 3, {226, 128, 158} +"ldrdhar", 3, {226, 165, 167} +"ldrushar", 3, {226, 165, 139} +"ldsh", 3, {226, 134, 178} +"le", 3, {226, 137, 164} +"lE", 3, {226, 137, 166} +"LeftAngleBracket", 3, {226, 159, 168} +"LeftArrowBar", 3, {226, 135, 164} +"leftarrow", 3, {226, 134, 144} +"LeftArrow", 3, {226, 134, 144} +"Leftarrow", 3, {226, 135, 144} +"LeftArrowRightArrow", 3, {226, 135, 134} +"leftarrowtail", 3, {226, 134, 162} +"LeftCeiling", 3, {226, 140, 136} +"LeftDoubleBracket", 3, {226, 159, 166} +"LeftDownTeeVector", 3, {226, 165, 161} +"LeftDownVectorBar", 3, {226, 165, 153} +"LeftDownVector", 3, {226, 135, 131} +"LeftFloor", 3, {226, 140, 138} +"leftharpoondown", 3, {226, 134, 189} +"leftharpoonup", 3, {226, 134, 188} +"leftleftarrows", 3, {226, 135, 135} +"leftrightarrow", 3, {226, 134, 148} +"LeftRightArrow", 3, {226, 134, 148} +"Leftrightarrow", 3, {226, 135, 148} +"leftrightarrows", 3, {226, 135, 134} +"leftrightharpoons", 3, {226, 135, 139} +"leftrightsquigarrow", 3, {226, 134, 173} +"LeftRightVector", 3, {226, 165, 142} +"LeftTeeArrow", 3, {226, 134, 164} +"LeftTee", 3, {226, 138, 163} +"LeftTeeVector", 3, {226, 165, 154} +"leftthreetimes", 3, {226, 139, 139} +"LeftTriangleBar", 3, {226, 167, 143} +"LeftTriangle", 3, {226, 138, 178} +"LeftTriangleEqual", 3, {226, 138, 180} +"LeftUpDownVector", 3, {226, 165, 145} +"LeftUpTeeVector", 3, {226, 165, 160} +"LeftUpVectorBar", 3, {226, 165, 152} +"LeftUpVector", 3, {226, 134, 191} +"LeftVectorBar", 3, {226, 165, 146} +"LeftVector", 3, {226, 134, 188} +"lEg", 3, {226, 170, 139} +"leg", 3, {226, 139, 154} +"leq", 3, {226, 137, 164} +"leqq", 3, {226, 137, 166} +"leqslant", 3, {226, 169, 189} +"lescc", 3, {226, 170, 168} +"les", 3, {226, 169, 189} +"lesdot", 3, {226, 169, 191} +"lesdoto", 3, {226, 170, 129} +"lesdotor", 3, {226, 170, 131} +"lesg", 3, {226, 139, 154} +"lesges", 3, {226, 170, 147} +"lessapprox", 3, {226, 170, 133} +"lessdot", 3, {226, 139, 150} +"lesseqgtr", 3, {226, 139, 154} +"lesseqqgtr", 3, {226, 170, 139} +"LessEqualGreater", 3, {226, 139, 154} +"LessFullEqual", 3, {226, 137, 166} +"LessGreater", 3, {226, 137, 182} +"lessgtr", 3, {226, 137, 182} +"LessLess", 3, {226, 170, 161} +"lesssim", 3, {226, 137, 178} +"LessSlantEqual", 3, {226, 169, 189} +"LessTilde", 3, {226, 137, 178} +"lfisht", 3, {226, 165, 188} +"lfloor", 3, {226, 140, 138} +"Lfr", 4, {240, 157, 148, 143} +"lfr", 4, {240, 157, 148, 169} +"lg", 3, {226, 137, 182} +"lgE", 3, {226, 170, 145} +"lHar", 3, {226, 165, 162} +"lhard", 3, {226, 134, 189} +"lharu", 3, {226, 134, 188} +"lharul", 3, {226, 165, 170} +"lhblk", 3, {226, 150, 132} +"LJcy", 2, {208, 137} +"ljcy", 2, {209, 153} +"llarr", 3, {226, 135, 135} +"ll", 3, {226, 137, 170} +"Ll", 3, {226, 139, 152} +"llcorner", 3, {226, 140, 158} +"Lleftarrow", 3, {226, 135, 154} +"llhard", 3, {226, 165, 171} +"lltri", 3, {226, 151, 186} +"Lmidot", 2, {196, 191} +"lmidot", 2, {197, 128} +"lmoustache", 3, {226, 142, 176} +"lmoust", 3, {226, 142, 176} +"lnap", 3, {226, 170, 137} +"lnapprox", 3, {226, 170, 137} +"lne", 3, {226, 170, 135} +"lnE", 3, {226, 137, 168} +"lneq", 3, {226, 170, 135} +"lneqq", 3, {226, 137, 168} +"lnsim", 3, {226, 139, 166} +"loang", 3, {226, 159, 172} +"loarr", 3, {226, 135, 189} +"lobrk", 3, {226, 159, 166} +"longleftarrow", 3, {226, 159, 181} +"LongLeftArrow", 3, {226, 159, 181} +"Longleftarrow", 3, {226, 159, 184} +"longleftrightarrow", 3, {226, 159, 183} +"LongLeftRightArrow", 3, {226, 159, 183} +"Longleftrightarrow", 3, {226, 159, 186} +"longmapsto", 3, {226, 159, 188} +"longrightarrow", 3, {226, 159, 182} +"LongRightArrow", 3, {226, 159, 182} +"Longrightarrow", 3, {226, 159, 185} +"looparrowleft", 3, {226, 134, 171} +"looparrowright", 3, {226, 134, 172} +"lopar", 3, {226, 166, 133} +"Lopf", 4, {240, 157, 149, 131} +"lopf", 4, {240, 157, 149, 157} +"loplus", 3, {226, 168, 173} +"lotimes", 3, {226, 168, 180} +"lowast", 3, {226, 136, 151} +"lowbar", 1, {95} +"LowerLeftArrow", 3, {226, 134, 153} +"LowerRightArrow", 3, {226, 134, 152} +"loz", 3, {226, 151, 138} +"lozenge", 3, {226, 151, 138} +"lozf", 3, {226, 167, 171} +"lpar", 1, {40} +"lparlt", 3, {226, 166, 147} +"lrarr", 3, {226, 135, 134} +"lrcorner", 3, {226, 140, 159} +"lrhar", 3, {226, 135, 139} +"lrhard", 3, {226, 165, 173} +"lrm", 3, {226, 128, 142} +"lrtri", 3, {226, 138, 191} +"lsaquo", 3, {226, 128, 185} +"lscr", 4, {240, 157, 147, 129} +"Lscr", 3, {226, 132, 146} +"lsh", 3, {226, 134, 176} +"Lsh", 3, {226, 134, 176} +"lsim", 3, {226, 137, 178} +"lsime", 3, {226, 170, 141} +"lsimg", 3, {226, 170, 143} +"lsqb", 1, {91} +"lsquo", 3, {226, 128, 152} +"lsquor", 3, {226, 128, 154} +"Lstrok", 2, {197, 129} +"lstrok", 2, {197, 130} +"ltcc", 3, {226, 170, 166} +"ltcir", 3, {226, 169, 185} +"lt", 1, {60} +"LT", 1, {60} +"Lt", 3, {226, 137, 170} +"ltdot", 3, {226, 139, 150} +"lthree", 3, {226, 139, 139} +"ltimes", 3, {226, 139, 137} +"ltlarr", 3, {226, 165, 182} +"ltquest", 3, {226, 169, 187} +"ltri", 3, {226, 151, 131} +"ltrie", 3, {226, 138, 180} +"ltrif", 3, {226, 151, 130} +"ltrPar", 3, {226, 166, 150} +"lurdshar", 3, {226, 165, 138} +"luruhar", 3, {226, 165, 166} +"lvertneqq", 3, {226, 137, 168} +"lvnE", 3, {226, 137, 168} +"macr", 2, {194, 175} +"male", 3, {226, 153, 130} +"malt", 3, {226, 156, 160} +"maltese", 3, {226, 156, 160} +"Map", 3, {226, 164, 133} +"map", 3, {226, 134, 166} +"mapsto", 3, {226, 134, 166} +"mapstodown", 3, {226, 134, 167} +"mapstoleft", 3, {226, 134, 164} +"mapstoup", 3, {226, 134, 165} +"marker", 3, {226, 150, 174} +"mcomma", 3, {226, 168, 169} +"Mcy", 2, {208, 156} +"mcy", 2, {208, 188} +"mdash", 3, {226, 128, 148} +"mDDot", 3, {226, 136, 186} +"measuredangle", 3, {226, 136, 161} +"MediumSpace", 3, {226, 129, 159} +"Mellintrf", 3, {226, 132, 179} +"Mfr", 4, {240, 157, 148, 144} +"mfr", 4, {240, 157, 148, 170} +"mho", 3, {226, 132, 167} +"micro", 2, {194, 181} +"midast", 1, {42} +"midcir", 3, {226, 171, 176} +"mid", 3, {226, 136, 163} +"middot", 2, {194, 183} +"minusb", 3, {226, 138, 159} +"minus", 3, {226, 136, 146} +"minusd", 3, {226, 136, 184} +"minusdu", 3, {226, 168, 170} +"MinusPlus", 3, {226, 136, 147} +"mlcp", 3, {226, 171, 155} +"mldr", 3, {226, 128, 166} +"mnplus", 3, {226, 136, 147} +"models", 3, {226, 138, 167} +"Mopf", 4, {240, 157, 149, 132} +"mopf", 4, {240, 157, 149, 158} +"mp", 3, {226, 136, 147} +"mscr", 4, {240, 157, 147, 130} +"Mscr", 3, {226, 132, 179} +"mstpos", 3, {226, 136, 190} +"Mu", 2, {206, 156} +"mu", 2, {206, 188} +"multimap", 3, {226, 138, 184} +"mumap", 3, {226, 138, 184} +"nabla", 3, {226, 136, 135} +"Nacute", 2, {197, 131} +"nacute", 2, {197, 132} +"nang", 3, {226, 136, 160} +"nap", 3, {226, 137, 137} +"napE", 3, {226, 169, 176} +"napid", 3, {226, 137, 139} +"napos", 2, {197, 137} +"napprox", 3, {226, 137, 137} +"natural", 3, {226, 153, 174} +"naturals", 3, {226, 132, 149} +"natur", 3, {226, 153, 174} +"nbsp", 2, {194, 160} +"nbump", 3, {226, 137, 142} +"nbumpe", 3, {226, 137, 143} +"ncap", 3, {226, 169, 131} +"Ncaron", 2, {197, 135} +"ncaron", 2, {197, 136} +"Ncedil", 2, {197, 133} +"ncedil", 2, {197, 134} +"ncong", 3, {226, 137, 135} +"ncongdot", 3, {226, 169, 173} +"ncup", 3, {226, 169, 130} +"Ncy", 2, {208, 157} +"ncy", 2, {208, 189} +"ndash", 3, {226, 128, 147} +"nearhk", 3, {226, 164, 164} +"nearr", 3, {226, 134, 151} +"neArr", 3, {226, 135, 151} +"nearrow", 3, {226, 134, 151} +"ne", 3, {226, 137, 160} +"nedot", 3, {226, 137, 144} +"NegativeMediumSpace", 3, {226, 128, 139} +"NegativeThickSpace", 3, {226, 128, 139} +"NegativeThinSpace", 3, {226, 128, 139} +"NegativeVeryThinSpace", 3, {226, 128, 139} +"nequiv", 3, {226, 137, 162} +"nesear", 3, {226, 164, 168} +"nesim", 3, {226, 137, 130} +"NestedGreaterGreater", 3, {226, 137, 171} +"NestedLessLess", 3, {226, 137, 170} +"NewLine", 1, {10} +"nexist", 3, {226, 136, 132} +"nexists", 3, {226, 136, 132} +"Nfr", 4, {240, 157, 148, 145} +"nfr", 4, {240, 157, 148, 171} +"ngE", 3, {226, 137, 167} +"nge", 3, {226, 137, 177} +"ngeq", 3, {226, 137, 177} +"ngeqq", 3, {226, 137, 167} +"ngeqslant", 3, {226, 169, 190} +"nges", 3, {226, 169, 190} +"nGg", 3, {226, 139, 153} +"ngsim", 3, {226, 137, 181} +"nGt", 3, {226, 137, 171} +"ngt", 3, {226, 137, 175} +"ngtr", 3, {226, 137, 175} +"nGtv", 3, {226, 137, 171} +"nharr", 3, {226, 134, 174} +"nhArr", 3, {226, 135, 142} +"nhpar", 3, {226, 171, 178} +"ni", 3, {226, 136, 139} +"nis", 3, {226, 139, 188} +"nisd", 3, {226, 139, 186} +"niv", 3, {226, 136, 139} +"NJcy", 2, {208, 138} +"njcy", 2, {209, 154} +"nlarr", 3, {226, 134, 154} +"nlArr", 3, {226, 135, 141} +"nldr", 3, {226, 128, 165} +"nlE", 3, {226, 137, 166} +"nle", 3, {226, 137, 176} +"nleftarrow", 3, {226, 134, 154} +"nLeftarrow", 3, {226, 135, 141} +"nleftrightarrow", 3, {226, 134, 174} +"nLeftrightarrow", 3, {226, 135, 142} +"nleq", 3, {226, 137, 176} +"nleqq", 3, {226, 137, 166} +"nleqslant", 3, {226, 169, 189} +"nles", 3, {226, 169, 189} +"nless", 3, {226, 137, 174} +"nLl", 3, {226, 139, 152} +"nlsim", 3, {226, 137, 180} +"nLt", 3, {226, 137, 170} +"nlt", 3, {226, 137, 174} +"nltri", 3, {226, 139, 170} +"nltrie", 3, {226, 139, 172} +"nLtv", 3, {226, 137, 170} +"nmid", 3, {226, 136, 164} +"NoBreak", 3, {226, 129, 160} +"NonBreakingSpace", 2, {194, 160} +"nopf", 4, {240, 157, 149, 159} +"Nopf", 3, {226, 132, 149} +"Not", 3, {226, 171, 172} +"not", 2, {194, 172} +"NotCongruent", 3, {226, 137, 162} +"NotCupCap", 3, {226, 137, 173} +"NotDoubleVerticalBar", 3, {226, 136, 166} +"NotElement", 3, {226, 136, 137} +"NotEqual", 3, {226, 137, 160} +"NotEqualTilde", 3, {226, 137, 130} +"NotExists", 3, {226, 136, 132} +"NotGreater", 3, {226, 137, 175} +"NotGreaterEqual", 3, {226, 137, 177} +"NotGreaterFullEqual", 3, {226, 137, 167} +"NotGreaterGreater", 3, {226, 137, 171} +"NotGreaterLess", 3, {226, 137, 185} +"NotGreaterSlantEqual", 3, {226, 169, 190} +"NotGreaterTilde", 3, {226, 137, 181} +"NotHumpDownHump", 3, {226, 137, 142} +"NotHumpEqual", 3, {226, 137, 143} +"notin", 3, {226, 136, 137} +"notindot", 3, {226, 139, 181} +"notinE", 3, {226, 139, 185} +"notinva", 3, {226, 136, 137} +"notinvb", 3, {226, 139, 183} +"notinvc", 3, {226, 139, 182} +"NotLeftTriangleBar", 3, {226, 167, 143} +"NotLeftTriangle", 3, {226, 139, 170} +"NotLeftTriangleEqual", 3, {226, 139, 172} +"NotLess", 3, {226, 137, 174} +"NotLessEqual", 3, {226, 137, 176} +"NotLessGreater", 3, {226, 137, 184} +"NotLessLess", 3, {226, 137, 170} +"NotLessSlantEqual", 3, {226, 169, 189} +"NotLessTilde", 3, {226, 137, 180} +"NotNestedGreaterGreater", 3, {226, 170, 162} +"NotNestedLessLess", 3, {226, 170, 161} +"notni", 3, {226, 136, 140} +"notniva", 3, {226, 136, 140} +"notnivb", 3, {226, 139, 190} +"notnivc", 3, {226, 139, 189} +"NotPrecedes", 3, {226, 138, 128} +"NotPrecedesEqual", 3, {226, 170, 175} +"NotPrecedesSlantEqual", 3, {226, 139, 160} +"NotReverseElement", 3, {226, 136, 140} +"NotRightTriangleBar", 3, {226, 167, 144} +"NotRightTriangle", 3, {226, 139, 171} +"NotRightTriangleEqual", 3, {226, 139, 173} +"NotSquareSubset", 3, {226, 138, 143} +"NotSquareSubsetEqual", 3, {226, 139, 162} +"NotSquareSuperset", 3, {226, 138, 144} +"NotSquareSupersetEqual", 3, {226, 139, 163} +"NotSubset", 3, {226, 138, 130} +"NotSubsetEqual", 3, {226, 138, 136} +"NotSucceeds", 3, {226, 138, 129} +"NotSucceedsEqual", 3, {226, 170, 176} +"NotSucceedsSlantEqual", 3, {226, 139, 161} +"NotSucceedsTilde", 3, {226, 137, 191} +"NotSuperset", 3, {226, 138, 131} +"NotSupersetEqual", 3, {226, 138, 137} +"NotTilde", 3, {226, 137, 129} +"NotTildeEqual", 3, {226, 137, 132} +"NotTildeFullEqual", 3, {226, 137, 135} +"NotTildeTilde", 3, {226, 137, 137} +"NotVerticalBar", 3, {226, 136, 164} +"nparallel", 3, {226, 136, 166} +"npar", 3, {226, 136, 166} +"nparsl", 3, {226, 171, 189} +"npart", 3, {226, 136, 130} +"npolint", 3, {226, 168, 148} +"npr", 3, {226, 138, 128} +"nprcue", 3, {226, 139, 160} +"nprec", 3, {226, 138, 128} +"npreceq", 3, {226, 170, 175} +"npre", 3, {226, 170, 175} +"nrarrc", 3, {226, 164, 179} +"nrarr", 3, {226, 134, 155} +"nrArr", 3, {226, 135, 143} +"nrarrw", 3, {226, 134, 157} +"nrightarrow", 3, {226, 134, 155} +"nRightarrow", 3, {226, 135, 143} +"nrtri", 3, {226, 139, 171} +"nrtrie", 3, {226, 139, 173} +"nsc", 3, {226, 138, 129} +"nsccue", 3, {226, 139, 161} +"nsce", 3, {226, 170, 176} +"Nscr", 4, {240, 157, 146, 169} +"nscr", 4, {240, 157, 147, 131} +"nshortmid", 3, {226, 136, 164} +"nshortparallel", 3, {226, 136, 166} +"nsim", 3, {226, 137, 129} +"nsime", 3, {226, 137, 132} +"nsimeq", 3, {226, 137, 132} +"nsmid", 3, {226, 136, 164} +"nspar", 3, {226, 136, 166} +"nsqsube", 3, {226, 139, 162} +"nsqsupe", 3, {226, 139, 163} +"nsub", 3, {226, 138, 132} +"nsubE", 3, {226, 171, 133} +"nsube", 3, {226, 138, 136} +"nsubset", 3, {226, 138, 130} +"nsubseteq", 3, {226, 138, 136} +"nsubseteqq", 3, {226, 171, 133} +"nsucc", 3, {226, 138, 129} +"nsucceq", 3, {226, 170, 176} +"nsup", 3, {226, 138, 133} +"nsupE", 3, {226, 171, 134} +"nsupe", 3, {226, 138, 137} +"nsupset", 3, {226, 138, 131} +"nsupseteq", 3, {226, 138, 137} +"nsupseteqq", 3, {226, 171, 134} +"ntgl", 3, {226, 137, 185} +"Ntilde", 2, {195, 145} +"ntilde", 2, {195, 177} +"ntlg", 3, {226, 137, 184} +"ntriangleleft", 3, {226, 139, 170} +"ntrianglelefteq", 3, {226, 139, 172} +"ntriangleright", 3, {226, 139, 171} +"ntrianglerighteq", 3, {226, 139, 173} +"Nu", 2, {206, 157} +"nu", 2, {206, 189} +"num", 1, {35} +"numero", 3, {226, 132, 150} +"numsp", 3, {226, 128, 135} +"nvap", 3, {226, 137, 141} +"nvdash", 3, {226, 138, 172} +"nvDash", 3, {226, 138, 173} +"nVdash", 3, {226, 138, 174} +"nVDash", 3, {226, 138, 175} +"nvge", 3, {226, 137, 165} +"nvgt", 1, {62} +"nvHarr", 3, {226, 164, 132} +"nvinfin", 3, {226, 167, 158} +"nvlArr", 3, {226, 164, 130} +"nvle", 3, {226, 137, 164} +"nvlt", 1, {60} +"nvltrie", 3, {226, 138, 180} +"nvrArr", 3, {226, 164, 131} +"nvrtrie", 3, {226, 138, 181} +"nvsim", 3, {226, 136, 188} +"nwarhk", 3, {226, 164, 163} +"nwarr", 3, {226, 134, 150} +"nwArr", 3, {226, 135, 150} +"nwarrow", 3, {226, 134, 150} +"nwnear", 3, {226, 164, 167} +"Oacute", 2, {195, 147} +"oacute", 2, {195, 179} +"oast", 3, {226, 138, 155} +"Ocirc", 2, {195, 148} +"ocirc", 2, {195, 180} +"ocir", 3, {226, 138, 154} +"Ocy", 2, {208, 158} +"ocy", 2, {208, 190} +"odash", 3, {226, 138, 157} +"Odblac", 2, {197, 144} +"odblac", 2, {197, 145} +"odiv", 3, {226, 168, 184} +"odot", 3, {226, 138, 153} +"odsold", 3, {226, 166, 188} +"OElig", 2, {197, 146} +"oelig", 2, {197, 147} +"ofcir", 3, {226, 166, 191} +"Ofr", 4, {240, 157, 148, 146} +"ofr", 4, {240, 157, 148, 172} +"ogon", 2, {203, 155} +"Ograve", 2, {195, 146} +"ograve", 2, {195, 178} +"ogt", 3, {226, 167, 129} +"ohbar", 3, {226, 166, 181} +"ohm", 2, {206, 169} +"oint", 3, {226, 136, 174} +"olarr", 3, {226, 134, 186} +"olcir", 3, {226, 166, 190} +"olcross", 3, {226, 166, 187} +"oline", 3, {226, 128, 190} +"olt", 3, {226, 167, 128} +"Omacr", 2, {197, 140} +"omacr", 2, {197, 141} +"Omega", 2, {206, 169} +"omega", 2, {207, 137} +"Omicron", 2, {206, 159} +"omicron", 2, {206, 191} +"omid", 3, {226, 166, 182} +"ominus", 3, {226, 138, 150} +"Oopf", 4, {240, 157, 149, 134} +"oopf", 4, {240, 157, 149, 160} +"opar", 3, {226, 166, 183} +"OpenCurlyDoubleQuote", 3, {226, 128, 156} +"OpenCurlyQuote", 3, {226, 128, 152} +"operp", 3, {226, 166, 185} +"oplus", 3, {226, 138, 149} +"orarr", 3, {226, 134, 187} +"Or", 3, {226, 169, 148} +"or", 3, {226, 136, 168} +"ord", 3, {226, 169, 157} +"order", 3, {226, 132, 180} +"orderof", 3, {226, 132, 180} +"ordf", 2, {194, 170} +"ordm", 2, {194, 186} +"origof", 3, {226, 138, 182} +"oror", 3, {226, 169, 150} +"orslope", 3, {226, 169, 151} +"orv", 3, {226, 169, 155} +"oS", 3, {226, 147, 136} +"Oscr", 4, {240, 157, 146, 170} +"oscr", 3, {226, 132, 180} +"Oslash", 2, {195, 152} +"oslash", 2, {195, 184} +"osol", 3, {226, 138, 152} +"Otilde", 2, {195, 149} +"otilde", 2, {195, 181} +"otimesas", 3, {226, 168, 182} +"Otimes", 3, {226, 168, 183} +"otimes", 3, {226, 138, 151} +"Ouml", 2, {195, 150} +"ouml", 2, {195, 182} +"ovbar", 3, {226, 140, 189} +"OverBar", 3, {226, 128, 190} +"OverBrace", 3, {226, 143, 158} +"OverBracket", 3, {226, 142, 180} +"OverParenthesis", 3, {226, 143, 156} +"para", 2, {194, 182} +"parallel", 3, {226, 136, 165} +"par", 3, {226, 136, 165} +"parsim", 3, {226, 171, 179} +"parsl", 3, {226, 171, 189} +"part", 3, {226, 136, 130} +"PartialD", 3, {226, 136, 130} +"Pcy", 2, {208, 159} +"pcy", 2, {208, 191} +"percnt", 1, {37} +"period", 1, {46} +"permil", 3, {226, 128, 176} +"perp", 3, {226, 138, 165} +"pertenk", 3, {226, 128, 177} +"Pfr", 4, {240, 157, 148, 147} +"pfr", 4, {240, 157, 148, 173} +"Phi", 2, {206, 166} +"phi", 2, {207, 134} +"phiv", 2, {207, 149} +"phmmat", 3, {226, 132, 179} +"phone", 3, {226, 152, 142} +"Pi", 2, {206, 160} +"pi", 2, {207, 128} +"pitchfork", 3, {226, 139, 148} +"piv", 2, {207, 150} +"planck", 3, {226, 132, 143} +"planckh", 3, {226, 132, 142} +"plankv", 3, {226, 132, 143} +"plusacir", 3, {226, 168, 163} +"plusb", 3, {226, 138, 158} +"pluscir", 3, {226, 168, 162} +"plus", 1, {43} +"plusdo", 3, {226, 136, 148} +"plusdu", 3, {226, 168, 165} +"pluse", 3, {226, 169, 178} +"PlusMinus", 2, {194, 177} +"plusmn", 2, {194, 177} +"plussim", 3, {226, 168, 166} +"plustwo", 3, {226, 168, 167} +"pm", 2, {194, 177} +"Poincareplane", 3, {226, 132, 140} +"pointint", 3, {226, 168, 149} +"popf", 4, {240, 157, 149, 161} +"Popf", 3, {226, 132, 153} +"pound", 2, {194, 163} +"prap", 3, {226, 170, 183} +"Pr", 3, {226, 170, 187} +"pr", 3, {226, 137, 186} +"prcue", 3, {226, 137, 188} +"precapprox", 3, {226, 170, 183} +"prec", 3, {226, 137, 186} +"preccurlyeq", 3, {226, 137, 188} +"Precedes", 3, {226, 137, 186} +"PrecedesEqual", 3, {226, 170, 175} +"PrecedesSlantEqual", 3, {226, 137, 188} +"PrecedesTilde", 3, {226, 137, 190} +"preceq", 3, {226, 170, 175} +"precnapprox", 3, {226, 170, 185} +"precneqq", 3, {226, 170, 181} +"precnsim", 3, {226, 139, 168} +"pre", 3, {226, 170, 175} +"prE", 3, {226, 170, 179} +"precsim", 3, {226, 137, 190} +"prime", 3, {226, 128, 178} +"Prime", 3, {226, 128, 179} +"primes", 3, {226, 132, 153} +"prnap", 3, {226, 170, 185} +"prnE", 3, {226, 170, 181} +"prnsim", 3, {226, 139, 168} +"prod", 3, {226, 136, 143} +"Product", 3, {226, 136, 143} +"profalar", 3, {226, 140, 174} +"profline", 3, {226, 140, 146} +"profsurf", 3, {226, 140, 147} +"prop", 3, {226, 136, 157} +"Proportional", 3, {226, 136, 157} +"Proportion", 3, {226, 136, 183} +"propto", 3, {226, 136, 157} +"prsim", 3, {226, 137, 190} +"prurel", 3, {226, 138, 176} +"Pscr", 4, {240, 157, 146, 171} +"pscr", 4, {240, 157, 147, 133} +"Psi", 2, {206, 168} +"psi", 2, {207, 136} +"puncsp", 3, {226, 128, 136} +"Qfr", 4, {240, 157, 148, 148} +"qfr", 4, {240, 157, 148, 174} +"qint", 3, {226, 168, 140} +"qopf", 4, {240, 157, 149, 162} +"Qopf", 3, {226, 132, 154} +"qprime", 3, {226, 129, 151} +"Qscr", 4, {240, 157, 146, 172} +"qscr", 4, {240, 157, 147, 134} +"quaternions", 3, {226, 132, 141} +"quatint", 3, {226, 168, 150} +"quest", 1, {63} +"questeq", 3, {226, 137, 159} +"quot", 1, {34} +"QUOT", 1, {34} +"rAarr", 3, {226, 135, 155} +"race", 3, {226, 136, 189} +"Racute", 2, {197, 148} +"racute", 2, {197, 149} +"radic", 3, {226, 136, 154} +"raemptyv", 3, {226, 166, 179} +"rang", 3, {226, 159, 169} +"Rang", 3, {226, 159, 171} +"rangd", 3, {226, 166, 146} +"range", 3, {226, 166, 165} +"rangle", 3, {226, 159, 169} +"raquo", 2, {194, 187} +"rarrap", 3, {226, 165, 181} +"rarrb", 3, {226, 135, 165} +"rarrbfs", 3, {226, 164, 160} +"rarrc", 3, {226, 164, 179} +"rarr", 3, {226, 134, 146} +"Rarr", 3, {226, 134, 160} +"rArr", 3, {226, 135, 146} +"rarrfs", 3, {226, 164, 158} +"rarrhk", 3, {226, 134, 170} +"rarrlp", 3, {226, 134, 172} +"rarrpl", 3, {226, 165, 133} +"rarrsim", 3, {226, 165, 180} +"Rarrtl", 3, {226, 164, 150} +"rarrtl", 3, {226, 134, 163} +"rarrw", 3, {226, 134, 157} +"ratail", 3, {226, 164, 154} +"rAtail", 3, {226, 164, 156} +"ratio", 3, {226, 136, 182} +"rationals", 3, {226, 132, 154} +"rbarr", 3, {226, 164, 141} +"rBarr", 3, {226, 164, 143} +"RBarr", 3, {226, 164, 144} +"rbbrk", 3, {226, 157, 179} +"rbrace", 1, {125} +"rbrack", 1, {93} +"rbrke", 3, {226, 166, 140} +"rbrksld", 3, {226, 166, 142} +"rbrkslu", 3, {226, 166, 144} +"Rcaron", 2, {197, 152} +"rcaron", 2, {197, 153} +"Rcedil", 2, {197, 150} +"rcedil", 2, {197, 151} +"rceil", 3, {226, 140, 137} +"rcub", 1, {125} +"Rcy", 2, {208, 160} +"rcy", 2, {209, 128} +"rdca", 3, {226, 164, 183} +"rdldhar", 3, {226, 165, 169} +"rdquo", 3, {226, 128, 157} +"rdquor", 3, {226, 128, 157} +"rdsh", 3, {226, 134, 179} +"real", 3, {226, 132, 156} +"realine", 3, {226, 132, 155} +"realpart", 3, {226, 132, 156} +"reals", 3, {226, 132, 157} +"Re", 3, {226, 132, 156} +"rect", 3, {226, 150, 173} +"reg", 2, {194, 174} +"REG", 2, {194, 174} +"ReverseElement", 3, {226, 136, 139} +"ReverseEquilibrium", 3, {226, 135, 139} +"ReverseUpEquilibrium", 3, {226, 165, 175} +"rfisht", 3, {226, 165, 189} +"rfloor", 3, {226, 140, 139} +"rfr", 4, {240, 157, 148, 175} +"Rfr", 3, {226, 132, 156} +"rHar", 3, {226, 165, 164} +"rhard", 3, {226, 135, 129} +"rharu", 3, {226, 135, 128} +"rharul", 3, {226, 165, 172} +"Rho", 2, {206, 161} +"rho", 2, {207, 129} +"rhov", 2, {207, 177} +"RightAngleBracket", 3, {226, 159, 169} +"RightArrowBar", 3, {226, 135, 165} +"rightarrow", 3, {226, 134, 146} +"RightArrow", 3, {226, 134, 146} +"Rightarrow", 3, {226, 135, 146} +"RightArrowLeftArrow", 3, {226, 135, 132} +"rightarrowtail", 3, {226, 134, 163} +"RightCeiling", 3, {226, 140, 137} +"RightDoubleBracket", 3, {226, 159, 167} +"RightDownTeeVector", 3, {226, 165, 157} +"RightDownVectorBar", 3, {226, 165, 149} +"RightDownVector", 3, {226, 135, 130} +"RightFloor", 3, {226, 140, 139} +"rightharpoondown", 3, {226, 135, 129} +"rightharpoonup", 3, {226, 135, 128} +"rightleftarrows", 3, {226, 135, 132} +"rightleftharpoons", 3, {226, 135, 140} +"rightrightarrows", 3, {226, 135, 137} +"rightsquigarrow", 3, {226, 134, 157} +"RightTeeArrow", 3, {226, 134, 166} +"RightTee", 3, {226, 138, 162} +"RightTeeVector", 3, {226, 165, 155} +"rightthreetimes", 3, {226, 139, 140} +"RightTriangleBar", 3, {226, 167, 144} +"RightTriangle", 3, {226, 138, 179} +"RightTriangleEqual", 3, {226, 138, 181} +"RightUpDownVector", 3, {226, 165, 143} +"RightUpTeeVector", 3, {226, 165, 156} +"RightUpVectorBar", 3, {226, 165, 148} +"RightUpVector", 3, {226, 134, 190} +"RightVectorBar", 3, {226, 165, 147} +"RightVector", 3, {226, 135, 128} +"ring", 2, {203, 154} +"risingdotseq", 3, {226, 137, 147} +"rlarr", 3, {226, 135, 132} +"rlhar", 3, {226, 135, 140} +"rlm", 3, {226, 128, 143} +"rmoustache", 3, {226, 142, 177} +"rmoust", 3, {226, 142, 177} +"rnmid", 3, {226, 171, 174} +"roang", 3, {226, 159, 173} +"roarr", 3, {226, 135, 190} +"robrk", 3, {226, 159, 167} +"ropar", 3, {226, 166, 134} +"ropf", 4, {240, 157, 149, 163} +"Ropf", 3, {226, 132, 157} +"roplus", 3, {226, 168, 174} +"rotimes", 3, {226, 168, 181} +"RoundImplies", 3, {226, 165, 176} +"rpar", 1, {41} +"rpargt", 3, {226, 166, 148} +"rppolint", 3, {226, 168, 146} +"rrarr", 3, {226, 135, 137} +"Rrightarrow", 3, {226, 135, 155} +"rsaquo", 3, {226, 128, 186} +"rscr", 4, {240, 157, 147, 135} +"Rscr", 3, {226, 132, 155} +"rsh", 3, {226, 134, 177} +"Rsh", 3, {226, 134, 177} +"rsqb", 1, {93} +"rsquo", 3, {226, 128, 153} +"rsquor", 3, {226, 128, 153} +"rthree", 3, {226, 139, 140} +"rtimes", 3, {226, 139, 138} +"rtri", 3, {226, 150, 185} +"rtrie", 3, {226, 138, 181} +"rtrif", 3, {226, 150, 184} +"rtriltri", 3, {226, 167, 142} +"RuleDelayed", 3, {226, 167, 180} +"ruluhar", 3, {226, 165, 168} +"rx", 3, {226, 132, 158} +"Sacute", 2, {197, 154} +"sacute", 2, {197, 155} +"sbquo", 3, {226, 128, 154} +"scap", 3, {226, 170, 184} +"Scaron", 2, {197, 160} +"scaron", 2, {197, 161} +"Sc", 3, {226, 170, 188} +"sc", 3, {226, 137, 187} +"sccue", 3, {226, 137, 189} +"sce", 3, {226, 170, 176} +"scE", 3, {226, 170, 180} +"Scedil", 2, {197, 158} +"scedil", 2, {197, 159} +"Scirc", 2, {197, 156} +"scirc", 2, {197, 157} +"scnap", 3, {226, 170, 186} +"scnE", 3, {226, 170, 182} +"scnsim", 3, {226, 139, 169} +"scpolint", 3, {226, 168, 147} +"scsim", 3, {226, 137, 191} +"Scy", 2, {208, 161} +"scy", 2, {209, 129} +"sdotb", 3, {226, 138, 161} +"sdot", 3, {226, 139, 133} +"sdote", 3, {226, 169, 166} +"searhk", 3, {226, 164, 165} +"searr", 3, {226, 134, 152} +"seArr", 3, {226, 135, 152} +"searrow", 3, {226, 134, 152} +"sect", 2, {194, 167} +"semi", 1, {59} +"seswar", 3, {226, 164, 169} +"setminus", 3, {226, 136, 150} +"setmn", 3, {226, 136, 150} +"sext", 3, {226, 156, 182} +"Sfr", 4, {240, 157, 148, 150} +"sfr", 4, {240, 157, 148, 176} +"sfrown", 3, {226, 140, 162} +"sharp", 3, {226, 153, 175} +"SHCHcy", 2, {208, 169} +"shchcy", 2, {209, 137} +"SHcy", 2, {208, 168} +"shcy", 2, {209, 136} +"ShortDownArrow", 3, {226, 134, 147} +"ShortLeftArrow", 3, {226, 134, 144} +"shortmid", 3, {226, 136, 163} +"shortparallel", 3, {226, 136, 165} +"ShortRightArrow", 3, {226, 134, 146} +"ShortUpArrow", 3, {226, 134, 145} +"shy", 2, {194, 173} +"Sigma", 2, {206, 163} +"sigma", 2, {207, 131} +"sigmaf", 2, {207, 130} +"sigmav", 2, {207, 130} +"sim", 3, {226, 136, 188} +"simdot", 3, {226, 169, 170} +"sime", 3, {226, 137, 131} +"simeq", 3, {226, 137, 131} +"simg", 3, {226, 170, 158} +"simgE", 3, {226, 170, 160} +"siml", 3, {226, 170, 157} +"simlE", 3, {226, 170, 159} +"simne", 3, {226, 137, 134} +"simplus", 3, {226, 168, 164} +"simrarr", 3, {226, 165, 178} +"slarr", 3, {226, 134, 144} +"SmallCircle", 3, {226, 136, 152} +"smallsetminus", 3, {226, 136, 150} +"smashp", 3, {226, 168, 179} +"smeparsl", 3, {226, 167, 164} +"smid", 3, {226, 136, 163} +"smile", 3, {226, 140, 163} +"smt", 3, {226, 170, 170} +"smte", 3, {226, 170, 172} +"smtes", 3, {226, 170, 172} +"SOFTcy", 2, {208, 172} +"softcy", 2, {209, 140} +"solbar", 3, {226, 140, 191} +"solb", 3, {226, 167, 132} +"sol", 1, {47} +"Sopf", 4, {240, 157, 149, 138} +"sopf", 4, {240, 157, 149, 164} +"spades", 3, {226, 153, 160} +"spadesuit", 3, {226, 153, 160} +"spar", 3, {226, 136, 165} +"sqcap", 3, {226, 138, 147} +"sqcaps", 3, {226, 138, 147} +"sqcup", 3, {226, 138, 148} +"sqcups", 3, {226, 138, 148} +"Sqrt", 3, {226, 136, 154} +"sqsub", 3, {226, 138, 143} +"sqsube", 3, {226, 138, 145} +"sqsubset", 3, {226, 138, 143} +"sqsubseteq", 3, {226, 138, 145} +"sqsup", 3, {226, 138, 144} +"sqsupe", 3, {226, 138, 146} +"sqsupset", 3, {226, 138, 144} +"sqsupseteq", 3, {226, 138, 146} +"square", 3, {226, 150, 161} +"Square", 3, {226, 150, 161} +"SquareIntersection", 3, {226, 138, 147} +"SquareSubset", 3, {226, 138, 143} +"SquareSubsetEqual", 3, {226, 138, 145} +"SquareSuperset", 3, {226, 138, 144} +"SquareSupersetEqual", 3, {226, 138, 146} +"SquareUnion", 3, {226, 138, 148} +"squarf", 3, {226, 150, 170} +"squ", 3, {226, 150, 161} +"squf", 3, {226, 150, 170} +"srarr", 3, {226, 134, 146} +"Sscr", 4, {240, 157, 146, 174} +"sscr", 4, {240, 157, 147, 136} +"ssetmn", 3, {226, 136, 150} +"ssmile", 3, {226, 140, 163} +"sstarf", 3, {226, 139, 134} +"Star", 3, {226, 139, 134} +"star", 3, {226, 152, 134} +"starf", 3, {226, 152, 133} +"straightepsilon", 2, {207, 181} +"straightphi", 2, {207, 149} +"strns", 2, {194, 175} +"sub", 3, {226, 138, 130} +"Sub", 3, {226, 139, 144} +"subdot", 3, {226, 170, 189} +"subE", 3, {226, 171, 133} +"sube", 3, {226, 138, 134} +"subedot", 3, {226, 171, 131} +"submult", 3, {226, 171, 129} +"subnE", 3, {226, 171, 139} +"subne", 3, {226, 138, 138} +"subplus", 3, {226, 170, 191} +"subrarr", 3, {226, 165, 185} +"subset", 3, {226, 138, 130} +"Subset", 3, {226, 139, 144} +"subseteq", 3, {226, 138, 134} +"subseteqq", 3, {226, 171, 133} +"SubsetEqual", 3, {226, 138, 134} +"subsetneq", 3, {226, 138, 138} +"subsetneqq", 3, {226, 171, 139} +"subsim", 3, {226, 171, 135} +"subsub", 3, {226, 171, 149} +"subsup", 3, {226, 171, 147} +"succapprox", 3, {226, 170, 184} +"succ", 3, {226, 137, 187} +"succcurlyeq", 3, {226, 137, 189} +"Succeeds", 3, {226, 137, 187} +"SucceedsEqual", 3, {226, 170, 176} +"SucceedsSlantEqual", 3, {226, 137, 189} +"SucceedsTilde", 3, {226, 137, 191} +"succeq", 3, {226, 170, 176} +"succnapprox", 3, {226, 170, 186} +"succneqq", 3, {226, 170, 182} +"succnsim", 3, {226, 139, 169} +"succsim", 3, {226, 137, 191} +"SuchThat", 3, {226, 136, 139} +"sum", 3, {226, 136, 145} +"Sum", 3, {226, 136, 145} +"sung", 3, {226, 153, 170} +"sup1", 2, {194, 185} +"sup2", 2, {194, 178} +"sup3", 2, {194, 179} +"sup", 3, {226, 138, 131} +"Sup", 3, {226, 139, 145} +"supdot", 3, {226, 170, 190} +"supdsub", 3, {226, 171, 152} +"supE", 3, {226, 171, 134} +"supe", 3, {226, 138, 135} +"supedot", 3, {226, 171, 132} +"Superset", 3, {226, 138, 131} +"SupersetEqual", 3, {226, 138, 135} +"suphsol", 3, {226, 159, 137} +"suphsub", 3, {226, 171, 151} +"suplarr", 3, {226, 165, 187} +"supmult", 3, {226, 171, 130} +"supnE", 3, {226, 171, 140} +"supne", 3, {226, 138, 139} +"supplus", 3, {226, 171, 128} +"supset", 3, {226, 138, 131} +"Supset", 3, {226, 139, 145} +"supseteq", 3, {226, 138, 135} +"supseteqq", 3, {226, 171, 134} +"supsetneq", 3, {226, 138, 139} +"supsetneqq", 3, {226, 171, 140} +"supsim", 3, {226, 171, 136} +"supsub", 3, {226, 171, 148} +"supsup", 3, {226, 171, 150} +"swarhk", 3, {226, 164, 166} +"swarr", 3, {226, 134, 153} +"swArr", 3, {226, 135, 153} +"swarrow", 3, {226, 134, 153} +"swnwar", 3, {226, 164, 170} +"szlig", 2, {195, 159} +"Tab", 1, {9} +"target", 3, {226, 140, 150} +"Tau", 2, {206, 164} +"tau", 2, {207, 132} +"tbrk", 3, {226, 142, 180} +"Tcaron", 2, {197, 164} +"tcaron", 2, {197, 165} +"Tcedil", 2, {197, 162} +"tcedil", 2, {197, 163} +"Tcy", 2, {208, 162} +"tcy", 2, {209, 130} +"tdot", 3, {226, 131, 155} +"telrec", 3, {226, 140, 149} +"Tfr", 4, {240, 157, 148, 151} +"tfr", 4, {240, 157, 148, 177} +"there4", 3, {226, 136, 180} +"therefore", 3, {226, 136, 180} +"Therefore", 3, {226, 136, 180} +"Theta", 2, {206, 152} +"theta", 2, {206, 184} +"thetasym", 2, {207, 145} +"thetav", 2, {207, 145} +"thickapprox", 3, {226, 137, 136} +"thicksim", 3, {226, 136, 188} +"ThickSpace", 3, {226, 129, 159} +"ThinSpace", 3, {226, 128, 137} +"thinsp", 3, {226, 128, 137} +"thkap", 3, {226, 137, 136} +"thksim", 3, {226, 136, 188} +"THORN", 2, {195, 158} +"thorn", 2, {195, 190} +"tilde", 2, {203, 156} +"Tilde", 3, {226, 136, 188} +"TildeEqual", 3, {226, 137, 131} +"TildeFullEqual", 3, {226, 137, 133} +"TildeTilde", 3, {226, 137, 136} +"timesbar", 3, {226, 168, 177} +"timesb", 3, {226, 138, 160} +"times", 2, {195, 151} +"timesd", 3, {226, 168, 176} +"tint", 3, {226, 136, 173} +"toea", 3, {226, 164, 168} +"topbot", 3, {226, 140, 182} +"topcir", 3, {226, 171, 177} +"top", 3, {226, 138, 164} +"Topf", 4, {240, 157, 149, 139} +"topf", 4, {240, 157, 149, 165} +"topfork", 3, {226, 171, 154} +"tosa", 3, {226, 164, 169} +"tprime", 3, {226, 128, 180} +"trade", 3, {226, 132, 162} +"TRADE", 3, {226, 132, 162} +"triangle", 3, {226, 150, 181} +"triangledown", 3, {226, 150, 191} +"triangleleft", 3, {226, 151, 131} +"trianglelefteq", 3, {226, 138, 180} +"triangleq", 3, {226, 137, 156} +"triangleright", 3, {226, 150, 185} +"trianglerighteq", 3, {226, 138, 181} +"tridot", 3, {226, 151, 172} +"trie", 3, {226, 137, 156} +"triminus", 3, {226, 168, 186} +"TripleDot", 3, {226, 131, 155} +"triplus", 3, {226, 168, 185} +"trisb", 3, {226, 167, 141} +"tritime", 3, {226, 168, 187} +"trpezium", 3, {226, 143, 162} +"Tscr", 4, {240, 157, 146, 175} +"tscr", 4, {240, 157, 147, 137} +"TScy", 2, {208, 166} +"tscy", 2, {209, 134} +"TSHcy", 2, {208, 139} +"tshcy", 2, {209, 155} +"Tstrok", 2, {197, 166} +"tstrok", 2, {197, 167} +"twixt", 3, {226, 137, 172} +"twoheadleftarrow", 3, {226, 134, 158} +"twoheadrightarrow", 3, {226, 134, 160} +"Uacute", 2, {195, 154} +"uacute", 2, {195, 186} +"uarr", 3, {226, 134, 145} +"Uarr", 3, {226, 134, 159} +"uArr", 3, {226, 135, 145} +"Uarrocir", 3, {226, 165, 137} +"Ubrcy", 2, {208, 142} +"ubrcy", 2, {209, 158} +"Ubreve", 2, {197, 172} +"ubreve", 2, {197, 173} +"Ucirc", 2, {195, 155} +"ucirc", 2, {195, 187} +"Ucy", 2, {208, 163} +"ucy", 2, {209, 131} +"udarr", 3, {226, 135, 133} +"Udblac", 2, {197, 176} +"udblac", 2, {197, 177} +"udhar", 3, {226, 165, 174} +"ufisht", 3, {226, 165, 190} +"Ufr", 4, {240, 157, 148, 152} +"ufr", 4, {240, 157, 148, 178} +"Ugrave", 2, {195, 153} +"ugrave", 2, {195, 185} +"uHar", 3, {226, 165, 163} +"uharl", 3, {226, 134, 191} +"uharr", 3, {226, 134, 190} +"uhblk", 3, {226, 150, 128} +"ulcorn", 3, {226, 140, 156} +"ulcorner", 3, {226, 140, 156} +"ulcrop", 3, {226, 140, 143} +"ultri", 3, {226, 151, 184} +"Umacr", 2, {197, 170} +"umacr", 2, {197, 171} +"uml", 2, {194, 168} +"UnderBar", 1, {95} +"UnderBrace", 3, {226, 143, 159} +"UnderBracket", 3, {226, 142, 181} +"UnderParenthesis", 3, {226, 143, 157} +"Union", 3, {226, 139, 131} +"UnionPlus", 3, {226, 138, 142} +"Uogon", 2, {197, 178} +"uogon", 2, {197, 179} +"Uopf", 4, {240, 157, 149, 140} +"uopf", 4, {240, 157, 149, 166} +"UpArrowBar", 3, {226, 164, 146} +"uparrow", 3, {226, 134, 145} +"UpArrow", 3, {226, 134, 145} +"Uparrow", 3, {226, 135, 145} +"UpArrowDownArrow", 3, {226, 135, 133} +"updownarrow", 3, {226, 134, 149} +"UpDownArrow", 3, {226, 134, 149} +"Updownarrow", 3, {226, 135, 149} +"UpEquilibrium", 3, {226, 165, 174} +"upharpoonleft", 3, {226, 134, 191} +"upharpoonright", 3, {226, 134, 190} +"uplus", 3, {226, 138, 142} +"UpperLeftArrow", 3, {226, 134, 150} +"UpperRightArrow", 3, {226, 134, 151} +"upsi", 2, {207, 133} +"Upsi", 2, {207, 146} +"upsih", 2, {207, 146} +"Upsilon", 2, {206, 165} +"upsilon", 2, {207, 133} +"UpTeeArrow", 3, {226, 134, 165} +"UpTee", 3, {226, 138, 165} +"upuparrows", 3, {226, 135, 136} +"urcorn", 3, {226, 140, 157} +"urcorner", 3, {226, 140, 157} +"urcrop", 3, {226, 140, 142} +"Uring", 2, {197, 174} +"uring", 2, {197, 175} +"urtri", 3, {226, 151, 185} +"Uscr", 4, {240, 157, 146, 176} +"uscr", 4, {240, 157, 147, 138} +"utdot", 3, {226, 139, 176} +"Utilde", 2, {197, 168} +"utilde", 2, {197, 169} +"utri", 3, {226, 150, 181} +"utrif", 3, {226, 150, 180} +"uuarr", 3, {226, 135, 136} +"Uuml", 2, {195, 156} +"uuml", 2, {195, 188} +"uwangle", 3, {226, 166, 167} +"vangrt", 3, {226, 166, 156} +"varepsilon", 2, {207, 181} +"varkappa", 2, {207, 176} +"varnothing", 3, {226, 136, 133} +"varphi", 2, {207, 149} +"varpi", 2, {207, 150} +"varpropto", 3, {226, 136, 157} +"varr", 3, {226, 134, 149} +"vArr", 3, {226, 135, 149} +"varrho", 2, {207, 177} +"varsigma", 2, {207, 130} +"varsubsetneq", 3, {226, 138, 138} +"varsubsetneqq", 3, {226, 171, 139} +"varsupsetneq", 3, {226, 138, 139} +"varsupsetneqq", 3, {226, 171, 140} +"vartheta", 2, {207, 145} +"vartriangleleft", 3, {226, 138, 178} +"vartriangleright", 3, {226, 138, 179} +"vBar", 3, {226, 171, 168} +"Vbar", 3, {226, 171, 171} +"vBarv", 3, {226, 171, 169} +"Vcy", 2, {208, 146} +"vcy", 2, {208, 178} +"vdash", 3, {226, 138, 162} +"vDash", 3, {226, 138, 168} +"Vdash", 3, {226, 138, 169} +"VDash", 3, {226, 138, 171} +"Vdashl", 3, {226, 171, 166} +"veebar", 3, {226, 138, 187} +"vee", 3, {226, 136, 168} +"Vee", 3, {226, 139, 129} +"veeeq", 3, {226, 137, 154} +"vellip", 3, {226, 139, 174} +"verbar", 1, {124} +"Verbar", 3, {226, 128, 150} +"vert", 1, {124} +"Vert", 3, {226, 128, 150} +"VerticalBar", 3, {226, 136, 163} +"VerticalLine", 1, {124} +"VerticalSeparator", 3, {226, 157, 152} +"VerticalTilde", 3, {226, 137, 128} +"VeryThinSpace", 3, {226, 128, 138} +"Vfr", 4, {240, 157, 148, 153} +"vfr", 4, {240, 157, 148, 179} +"vltri", 3, {226, 138, 178} +"vnsub", 3, {226, 138, 130} +"vnsup", 3, {226, 138, 131} +"Vopf", 4, {240, 157, 149, 141} +"vopf", 4, {240, 157, 149, 167} +"vprop", 3, {226, 136, 157} +"vrtri", 3, {226, 138, 179} +"Vscr", 4, {240, 157, 146, 177} +"vscr", 4, {240, 157, 147, 139} +"vsubnE", 3, {226, 171, 139} +"vsubne", 3, {226, 138, 138} +"vsupnE", 3, {226, 171, 140} +"vsupne", 3, {226, 138, 139} +"Vvdash", 3, {226, 138, 170} +"vzigzag", 3, {226, 166, 154} +"Wcirc", 2, {197, 180} +"wcirc", 2, {197, 181} +"wedbar", 3, {226, 169, 159} +"wedge", 3, {226, 136, 167} +"Wedge", 3, {226, 139, 128} +"wedgeq", 3, {226, 137, 153} +"weierp", 3, {226, 132, 152} +"Wfr", 4, {240, 157, 148, 154} +"wfr", 4, {240, 157, 148, 180} +"Wopf", 4, {240, 157, 149, 142} +"wopf", 4, {240, 157, 149, 168} +"wp", 3, {226, 132, 152} +"wr", 3, {226, 137, 128} +"wreath", 3, {226, 137, 128} +"Wscr", 4, {240, 157, 146, 178} +"wscr", 4, {240, 157, 147, 140} +"xcap", 3, {226, 139, 130} +"xcirc", 3, {226, 151, 175} +"xcup", 3, {226, 139, 131} +"xdtri", 3, {226, 150, 189} +"Xfr", 4, {240, 157, 148, 155} +"xfr", 4, {240, 157, 148, 181} +"xharr", 3, {226, 159, 183} +"xhArr", 3, {226, 159, 186} +"Xi", 2, {206, 158} +"xi", 2, {206, 190} +"xlarr", 3, {226, 159, 181} +"xlArr", 3, {226, 159, 184} +"xmap", 3, {226, 159, 188} +"xnis", 3, {226, 139, 187} +"xodot", 3, {226, 168, 128} +"Xopf", 4, {240, 157, 149, 143} +"xopf", 4, {240, 157, 149, 169} +"xoplus", 3, {226, 168, 129} +"xotime", 3, {226, 168, 130} +"xrarr", 3, {226, 159, 182} +"xrArr", 3, {226, 159, 185} +"Xscr", 4, {240, 157, 146, 179} +"xscr", 4, {240, 157, 147, 141} +"xsqcup", 3, {226, 168, 134} +"xuplus", 3, {226, 168, 132} +"xutri", 3, {226, 150, 179} +"xvee", 3, {226, 139, 129} +"xwedge", 3, {226, 139, 128} +"Yacute", 2, {195, 157} +"yacute", 2, {195, 189} +"YAcy", 2, {208, 175} +"yacy", 2, {209, 143} +"Ycirc", 2, {197, 182} +"ycirc", 2, {197, 183} +"Ycy", 2, {208, 171} +"ycy", 2, {209, 139} +"yen", 2, {194, 165} +"Yfr", 4, {240, 157, 148, 156} +"yfr", 4, {240, 157, 148, 182} +"YIcy", 2, {208, 135} +"yicy", 2, {209, 151} +"Yopf", 4, {240, 157, 149, 144} +"yopf", 4, {240, 157, 149, 170} +"Yscr", 4, {240, 157, 146, 180} +"yscr", 4, {240, 157, 147, 142} +"YUcy", 2, {208, 174} +"yucy", 2, {209, 142} +"yuml", 2, {195, 191} +"Yuml", 2, {197, 184} +"Zacute", 2, {197, 185} +"zacute", 2, {197, 186} +"Zcaron", 2, {197, 189} +"zcaron", 2, {197, 190} +"Zcy", 2, {208, 151} +"zcy", 2, {208, 183} +"Zdot", 2, {197, 187} +"zdot", 2, {197, 188} +"zeetrf", 3, {226, 132, 168} +"ZeroWidthSpace", 3, {226, 128, 139} +"Zeta", 2, {206, 150} +"zeta", 2, {206, 182} +"zfr", 4, {240, 157, 148, 183} +"Zfr", 3, {226, 132, 168} +"ZHcy", 2, {208, 150} +"zhcy", 2, {208, 182} +"zigrarr", 3, {226, 135, 157} +"zopf", 4, {240, 157, 149, 171} +"Zopf", 3, {226, 132, 164} +"Zscr", 4, {240, 157, 146, 181} +"zscr", 4, {240, 157, 147, 143} +"zwj", 3, {226, 128, 141} +"zwnj", 3, {226, 128, 140} diff --git a/src/html/html_unescape.h b/src/html/html_unescape.h new file mode 100644 index 0000000..5d12662 --- /dev/null +++ b/src/html/html_unescape.h @@ -0,0 +1,9746 @@ +/* C code produced by gperf version 3.0.4 */ +/* Command-line: gperf -I -t -N find_entity -H hash_entity -K entity -C -l --null-strings -m5 src/html/html_unescape.gperf */ +/* Computed positions: -k'1-7,10,12,$' */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>." +#endif + +#line 1 "src/html/html_unescape.gperf" +struct html_ent { + const char *entity; + unsigned int utf8_len; + unsigned char utf8[4]; +}; +#include <string.h> + +#define TOTAL_KEYWORDS 2125 +#define MIN_WORD_LENGTH 2 +#define MAX_WORD_LENGTH 31 +#define MIN_HASH_VALUE 39 +#define MAX_HASH_VALUE 16000 +/* maximum key range = 15962, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +hash_entity (str, len) + register const char *str; + register unsigned int len; +{ + static const unsigned short asso_values[] = + { + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 2, + 3, 7, 2, 4, 8, 16001, 10, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 1890, 1538, 220, 165, 1045, + 535, 1971, 1187, 1262, 35, 126, 201, 133, 350, 1487, + 1965, 3, 478, 134, 8, 147, 73, 41, 23, 212, + 9, 16001, 2, 16001, 2, 16001, 16001, 4154, 29, 3168, + 429, 10, 146, 1925, 2307, 280, 1313, 1924, 4, 651, + 27, 1031, 65, 176, 2, 6, 17, 15, 107, 482, + 3207, 3865, 757, 131, 178, 4, 4, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001 + }; + register int hval = len; + + switch (hval) + { + default: + hval += asso_values[(unsigned char)str[11]]; + /*FALLTHROUGH*/ + case 11: + case 10: + hval += asso_values[(unsigned char)str[9]]; + /*FALLTHROUGH*/ + case 9: + case 8: + case 7: + hval += asso_values[(unsigned char)str[6]]; + /*FALLTHROUGH*/ + case 6: + hval += asso_values[(unsigned char)str[5]]; + /*FALLTHROUGH*/ + case 5: + hval += asso_values[(unsigned char)str[4]+1]; + /*FALLTHROUGH*/ + case 4: + hval += asso_values[(unsigned char)str[3]+3]; + /*FALLTHROUGH*/ + case 3: + hval += asso_values[(unsigned char)str[2]+1]; + /*FALLTHROUGH*/ + case 2: + hval += asso_values[(unsigned char)str[1]+4]; + /*FALLTHROUGH*/ + case 1: + hval += asso_values[(unsigned char)str[0]]; + break; + } + return hval + asso_values[(unsigned char)str[len - 1]]; +} + +#ifdef __GNUC__ +__inline +#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ +__attribute__ ((__gnu_inline__)) +#endif +#endif +const struct html_ent * +find_entity (str, len) + register const char *str; + register unsigned int len; +{ + static const unsigned char lengthtable[] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, + 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 0, 0, 3, + 0, 0, 0, 0, 0, 0, 6, 0, 6, 5, 0, 5, 3, 4, + 3, 4, 0, 4, 0, 2, 5, 4, 0, 0, 0, 2, 0, 7, + 0, 7, 3, 0, 5, 0, 0, 0, 0, 0, 4, 0, 0, 6, + 0, 0, 0, 3, 6, 0, 4, 0, 0, 0, 0, 6, 4, 5, + 0, 0, 0, 5, 0, 5, 0, 6, 0, 0, 0, 4, 5, 5, + 5, 3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, + 0, 0, 0, 3, 4, 0, 3, 0, 0, 5, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 0, + 5, 0, 5, 6, 0, 6, 5, 0, 2, 5, 0, 5, 0, 0, + 0, 0, 4, 0, 0, 0, 3, 0, 3, 5, 0, 0, 5, 0, + 0, 0, 6, 0, 10, 0, 4, 0, 0, 5, 3, 5, 0, 0, + 0, 0, 0, 0, 0, 5, 0, 3, 0, 0, 0, 0, 6, 6, + 0, 6, 0, 0, 0, 0, 6, 0, 6, 0, 2, 0, 0, 0, + 4, 7, 0, 7, 0, 5, 0, 0, 0, 0, 0, 0, 0, 3, + 0, 4, 0, 4, 6, 0, 3, 0, 0, 0, 0, 0, 0, 4, + 4, 3, 0, 4, 0, 0, 2, 0, 0, 0, 4, 0, 4, 0, + 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 0, 2, 0, 0, 0, 5, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 3, 2, 4, 0, 6, 0, 0, 3, 0, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6, 0, 3, 4, 0, 0, 0, + 0, 4, 6, 0, 0, 0, 5, 5, 5, 0, 13, 0, 0, 4, + 0, 0, 5, 0, 4, 4, 5, 17, 18, 0, 0, 0, 0, 0, + 5, 0, 0, 17, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, + 5, 5, 0, 0, 0, 8, 0, 0, 0, 3, 0, 0, 6, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 5, 6, 0, 0, + 0, 4, 0, 0, 5, 0, 6, 6, 6, 6, 6, 6, 6, 0, + 0, 6, 0, 6, 0, 6, 6, 6, 6, 6, 6, 0, 0, 0, + 6, 0, 6, 3, 4, 0, 0, 4, 3, 5, 0, 0, 3, 0, + 0, 0, 11, 5, 0, 0, 0, 4, 0, 0, 6, 0, 0, 0, + 5, 0, 0, 0, 5, 0, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 0, 0, 0, 0, 0, 5, 3, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 4, 0, 4, + 0, 0, 0, 0, 0, 0, 6, 0, 0, 5, 0, 0, 0, 0, + 3, 6, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 4, 6, + 0, 0, 8, 0, 8, 0, 2, 0, 0, 0, 0, 4, 0, 0, + 0, 4, 0, 6, 0, 0, 0, 0, 6, 0, 4, 0, 0, 0, + 0, 6, 0, 5, 6, 2, 5, 8, 5, 0, 0, 4, 0, 4, + 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 9, 0, 4, 4, + 4, 0, 4, 6, 4, 4, 4, 0, 0, 0, 5, 4, 5, 4, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 4, 5, 4, + 5, 0, 0, 4, 0, 5, 0, 0, 0, 4, 0, 0, 0, 0, + 4, 4, 0, 5, 0, 0, 11, 0, 0, 6, 0, 0, 3, 0, + 0, 0, 0, 6, 0, 4, 0, 0, 4, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 7, 4, 4, 0, 7, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 3, 8, 4, 0, 0, 0, 5, 0, 6, 0, + 0, 0, 0, 6, 0, 4, 0, 0, 0, 5, 0, 6, 0, 0, + 0, 5, 5, 0, 0, 3, 6, 2, 0, 0, 4, 0, 0, 7, + 0, 4, 0, 4, 4, 4, 3, 5, 0, 0, 0, 0, 0, 0, + 6, 0, 4, 4, 0, 0, 0, 12, 13, 0, 0, 6, 8, 0, + 2, 0, 0, 17, 0, 0, 0, 4, 0, 5, 0, 7, 0, 5, + 0, 0, 0, 5, 4, 5, 0, 0, 3, 0, 0, 0, 5, 0, + 5, 12, 13, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 0, 0, 0, 7, 0, 0, 6, 6, 6, 0, 4, 0, + 0, 0, 0, 17, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 3, 6, 9, 0, 0, + 0, 9, 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 19, 0, 5, 0, 0, 17, 0, 0, + 14, 0, 0, 0, 0, 12, 4, 0, 0, 0, 4, 0, 2, 0, + 4, 0, 6, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 0, + 4, 0, 4, 4, 4, 0, 0, 0, 0, 4, 0, 4, 0, 4, + 9, 0, 0, 4, 2, 0, 0, 4, 2, 4, 4, 0, 0, 0, + 0, 4, 6, 0, 0, 6, 9, 4, 0, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 4, 2, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 6, 0, 0, + 0, 0, 6, 4, 6, 4, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 0, 9, 0, 0, 4, 0, 0, 0, 0, 0, + 7, 4, 4, 7, 0, 7, 5, 0, 0, 6, 4, 4, 4, 0, + 4, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 4, 4, 6, 0, 0, 0, 3, 5, 3, + 5, 11, 4, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 5, 0, 5, 0, 0, 0, 3, 5, 4, + 0, 0, 0, 5, 0, 6, 9, 7, 2, 0, 4, 0, 0, 4, + 0, 0, 0, 0, 4, 5, 6, 0, 0, 0, 0, 9, 10, 0, + 0, 0, 5, 0, 0, 0, 0, 11, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 4, 8, 6, 0, 0, 0, 0, 0, 8, 0, 0, + 0, 0, 0, 0, 0, 5, 6, 0, 0, 0, 13, 5, 5, 6, + 0, 0, 0, 0, 2, 0, 0, 0, 4, 2, 4, 0, 0, 6, + 4, 0, 4, 0, 0, 0, 4, 0, 21, 0, 0, 0, 6, 0, + 3, 0, 0, 0, 6, 6, 0, 3, 13, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 0, 0, 7, 0, 0, 0, 0, + 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 4, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 7, 3, 0, 0, + 0, 0, 0, 0, 0, 7, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, + 3, 15, 3, 3, 3, 0, 0, 0, 3, 3, 6, 3, 6, 0, + 0, 0, 0, 3, 0, 0, 4, 3, 0, 3, 0, 12, 0, 0, + 0, 3, 0, 4, 0, 0, 0, 3, 0, 12, 0, 4, 5, 0, + 9, 0, 0, 7, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 5, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, + 0, 5, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 5, + 0, 3, 3, 0, 0, 6, 0, 0, 0, 0, 0, 4, 0, 0, + 3, 3, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 3, 7, 0, 0, 8, 0, 0, 0, 0, + 0, 0, 3, 4, 0, 6, 0, 0, 0, 15, 0, 0, 0, 0, + 0, 0, 0, 9, 0, 0, 0, 2, 0, 0, 0, 0, 9, 3, + 0, 0, 0, 0, 0, 0, 6, 0, 0, 7, 3, 24, 0, 0, + 0, 0, 5, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 7, 4, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 3, 3, + 0, 4, 0, 7, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 5, 2, 0, 0, 0, 6, 0, 3, 8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 9, 5, 7, 0, 0, 0, 0, 0, 0, 0, + 0, 7, 15, 7, 8, 4, 0, 5, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 4, 4, 5, 0, 0, 0, 0, 6, 14, 3, + 15, 0, 6, 0, 0, 0, 3, 0, 3, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 0, 0, 0, + 0, 0, 0, 5, 0, 0, 5, 16, 0, 5, 10, 0, 0, 0, + 5, 7, 0, 5, 0, 0, 6, 0, 3, 0, 0, 11, 5, 0, + 0, 4, 5, 0, 0, 5, 0, 0, 3, 0, 0, 0, 0, 8, + 0, 0, 0, 5, 0, 0, 0, 6, 3, 0, 0, 0, 0, 0, + 5, 0, 0, 3, 3, 3, 0, 0, 0, 6, 0, 0, 5, 6, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 11, 0, 6, 0, 6, 0, 0, 13, 0, 0, 7, + 0, 0, 0, 0, 7, 0, 6, 4, 5, 0, 3, 0, 0, 5, + 3, 0, 0, 0, 0, 0, 6, 0, 0, 4, 0, 0, 0, 0, + 3, 6, 5, 0, 0, 0, 0, 11, 0, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, + 0, 11, 0, 5, 5, 0, 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 8, 0, 7, 4, 0, 0, 0, 0, 5, 4, 9, + 0, 0, 5, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 0, 6, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 4, 0, 0, 14, 5, 0, 0, 8, + 0, 0, 0, 20, 7, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 3, 0, 0, 4, 6, 0, 0, 0, 0, 6, 0, 0, 0, 7, + 0, 3, 6, 4, 6, 0, 0, 0, 0, 0, 0, 6, 3, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 11, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 4, + 0, 0, 0, 0, 0, 0, 0, 13, 18, 5, 0, 3, 0, 7, + 0, 4, 0, 0, 0, 4, 0, 0, 10, 11, 0, 0, 0, 6, + 0, 6, 0, 0, 5, 0, 5, 12, 12, 0, 0, 0, 4, 0, + 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, + 14, 0, 0, 0, 2, 4, 8, 4, 0, 3, 0, 0, 7, 0, + 3, 0, 0, 0, 3, 2, 0, 0, 0, 0, 6, 0, 6, 4, + 6, 7, 6, 6, 6, 0, 10, 0, 0, 0, 3, 6, 0, 4, + 0, 0, 0, 0, 0, 4, 0, 6, 6, 0, 4, 0, 0, 0, + 7, 0, 0, 7, 0, 0, 4, 0, 4, 0, 5, 6, 0, 6, + 0, 3, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 8, 14, 0, 3, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 7, 5, 0, 0, 0, 4, 0, 0, 0, + 17, 7, 0, 0, 4, 0, 0, 7, 0, 5, 0, 0, 7, 5, + 0, 0, 4, 0, 7, 2, 20, 0, 0, 0, 0, 13, 0, 0, + 0, 0, 6, 0, 7, 3, 5, 4, 0, 0, 0, 0, 5, 5, + 0, 0, 0, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 5, 0, 0, 6, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 4, 9, 0, 5, 12, 0, 0, 0, 0, 5, 0, 5, + 4, 0, 0, 0, 9, 0, 0, 0, 10, 10, 0, 0, 4, 6, + 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 6, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 6, 0, 0, 0, 0, 6, 6, 0, 3, 0, 0, 0, + 7, 0, 0, 0, 0, 7, 4, 0, 0, 0, 0, 0, 4, 0, + 9, 0, 0, 3, 0, 0, 0, 7, 0, 4, 0, 0, 5, 6, + 0, 0, 6, 3, 5, 4, 0, 0, 0, 0, 0, 6, 0, 5, + 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 5, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 6, 0, 0, 6, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 6, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10, 0, 0, 6, 0, 6, 0, 0, 6, + 0, 0, 18, 0, 6, 0, 20, 15, 0, 0, 4, 4, 0, 0, + 0, 6, 0, 0, 0, 3, 0, 0, 0, 0, 0, 5, 4, 4, + 0, 7, 0, 6, 0, 4, 0, 5, 0, 0, 0, 0, 5, 0, + 0, 0, 4, 4, 0, 0, 0, 0, 4, 0, 4, 0, 11, 0, + 20, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 0, 0, 8, 0, 0, 0, 6, 0, 0, 0, + 0, 4, 0, 0, 0, 0, 0, 4, 0, 0, 3, 0, 0, 6, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 9, 0, 0, 0, 5, + 0, 0, 0, 5, 0, 3, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 3, 0, 0, 17, 0, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 9, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 7, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 14, 0, + 0, 11, 0, 6, 0, 6, 0, 7, 5, 0, 0, 0, 6, 12, + 12, 0, 0, 0, 0, 16, 0, 14, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 0, 0, 7, + 0, 0, 5, 0, 0, 0, 0, 0, 0, 6, 0, 14, 0, 0, + 0, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, 0, 5, 0, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 5, 0, 0, 0, 0, 0, 0, + 5, 0, 5, 0, 0, 0, 0, 0, 11, 6, 6, 3, 0, 0, + 0, 0, 7, 0, 6, 0, 6, 6, 4, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, + 4, 4, 0, 0, 0, 0, 3, 3, 6, 0, 0, 0, 0, 0, + 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0, 4, 6, 0, + 4, 4, 0, 0, 0, 0, 13, 0, 4, 0, 0, 0, 0, 4, + 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 7, 0, + 0, 0, 10, 0, 9, 0, 0, 4, 6, 0, 5, 0, 0, 0, + 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, 0, 0, 0, 8, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 12, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, 18, 0, 0, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 7, 0, 0, 0, 0, 5, 0, 5, + 0, 0, 0, 6, 0, 0, 5, 0, 0, 6, 0, 6, 0, 0, + 13, 6, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 0, 6, 0, 6, 7, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 6, 15, 0, 0, 7, 0, 3, 0, 3, 0, 0, 0, + 9, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 15, + 0, 0, 0, 6, 0, 0, 6, 0, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 9, 4, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 2, 15, 0, 0, + 0, 5, 0, 5, 0, 4, 0, 0, 0, 0, 0, 0, 16, 0, + 3, 3, 10, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 4, + 5, 4, 0, 0, 6, 0, 5, 4, 0, 5, 5, 3, 5, 0, + 4, 0, 6, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 3, + 0, 0, 0, 0, 0, 3, 0, 0, 6, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 8, 6, 0, 0, 0, 0, 0, 0, 0, 5, 16, 0, + 5, 7, 0, 6, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7, 0, 7, 0, 0, 5, 0, 0, + 0, 0, 6, 0, 5, 4, 5, 0, 5, 5, 0, 0, 0, 0, + 5, 2, 6, 4, 0, 5, 0, 0, 5, 0, 4, 0, 0, 0, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, + 0, 6, 0, 0, 0, 0, 3, 5, 0, 0, 0, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 0, 6, 5, 0, 0, 4, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, + 0, 4, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 0, 4, 2, 6, 0, 6, 3, 3, 0, 0, + 3, 0, 4, 0, 6, 0, 3, 0, 0, 6, 0, 5, 31, 0, + 0, 0, 0, 0, 0, 0, 3, 6, 0, 0, 0, 0, 0, 0, + 0, 4, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 0, 6, + 0, 8, 0, 5, 4, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 5, 0, 0, 5, 0, + 0, 0, 19, 0, 0, 0, 0, 24, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 5, + 0, 0, 0, 6, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, + 0, 16, 5, 0, 0, 3, 4, 4, 0, 5, 4, 5, 0, 0, + 0, 13, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 6, 0, 3, + 0, 7, 0, 10, 0, 0, 0, 0, 6, 0, 6, 0, 0, 13, + 0, 0, 0, 5, 0, 8, 0, 6, 0, 6, 8, 6, 0, 0, + 6, 6, 0, 10, 0, 8, 6, 6, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 11, 0, 0, 0, 6, 0, 0, 0, + 0, 7, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 17, 6, 0, 0, 0, 0, 0, 16, 0, 0, + 0, 0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 0, 7, 0, + 14, 7, 6, 0, 6, 0, 7, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 10, 4, 14, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 4, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 6, 3, 8, 4, 6, 6, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 6, 0, 4, 0, 2, 0, 20, 21, 0, 0, 2, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 0, 0, 14, 4, 6, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 5, 0, 0, + 4, 6, 0, 2, 7, 0, 6, 5, 0, 8, 0, 0, 5, 0, + 4, 0, 0, 0, 5, 0, 4, 15, 5, 0, 4, 6, 0, 0, + 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 17, 5, 0, + 0, 0, 9, 6, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 0, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 7, 5, 0, + 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 12, 0, 0, 0, 6, 0, 0, 0, 0, 10, 3, 0, 0, + 0, 4, 0, 5, 0, 0, 0, 0, 0, 4, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 7, 0, 0, + 0, 0, 0, 0, 9, 0, 6, 0, 6, 0, 0, 0, 0, 19, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, + 0, 0, 0, 0, 0, 0, 5, 0, 0, 5, 0, 6, 3, 6, + 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 2, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 0, 6, 0, 6, 0, 6, 0, 0, + 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 17, 0, + 0, 7, 0, 0, 2, 6, 2, 0, 0, 0, 2, 0, 0, 0, + 0, 3, 8, 0, 0, 3, 0, 5, 0, 5, 6, 0, 0, 0, + 0, 18, 0, 0, 0, 0, 5, 0, 7, 0, 0, 9, 0, 0, + 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 0, 4, 0, 0, 4, 0, 9, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 5, 0, 4, 0, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 5, 0, 5, 6, + 0, 0, 0, 3, 3, 5, 0, 0, 0, 0, 6, 0, 0, 0, + 6, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 4, + 6, 13, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 13, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 8, 6, 8, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 0, 12, 0, 6, 0, 0, 0, 6, 0, 0, + 0, 6, 4, 0, 0, 7, 6, 5, 0, 0, 6, 0, 5, 5, + 5, 0, 0, 0, 9, 0, 0, 0, 0, 0, 5, 0, 6, 8, + 0, 0, 6, 0, 5, 8, 0, 0, 0, 6, 0, 4, 0, 9, + 0, 0, 0, 0, 4, 6, 4, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, + 11, 0, 0, 8, 9, 0, 0, 0, 0, 3, 5, 3, 0, 0, + 0, 0, 6, 4, 0, 0, 0, 9, 4, 3, 0, 2, 0, 0, + 0, 0, 0, 7, 5, 0, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 14, 3, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 10, 7, + 5, 0, 6, 0, 6, 0, 3, 17, 0, 0, 0, 0, 0, 0, + 20, 0, 14, 4, 0, 0, 0, 0, 0, 0, 19, 6, 6, 0, + 10, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 6, 0, + 0, 3, 0, 0, 0, 4, 5, 0, 0, 4, 0, 5, 0, 0, + 0, 0, 0, 0, 7, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 7, 0, 3, 0, 4, 0, 3, 0, 4, 0, 0, 13, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, + 6, 0, 0, 0, 0, 0, 7, 0, 13, 0, 0, 15, 0, 0, + 5, 9, 0, 0, 0, 6, 0, 6, 0, 0, 4, 6, 0, 0, + 6, 4, 4, 0, 16, 0, 4, 0, 3, 0, 0, 11, 5, 15, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 0, 0, 5, 0, 5, 4, 0, 0, 4, 0, + 20, 4, 0, 0, 0, 0, 0, 5, 15, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 22, 0, 0, 7, + 8, 0, 4, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 6, + 0, 0, 6, 7, 0, 0, 0, 0, 6, 0, 6, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 4, 0, 5, 0, 12, 15, 6, 0, + 13, 0, 4, 0, 5, 4, 6, 0, 0, 0, 0, 4, 0, 0, + 4, 3, 5, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 0, + 0, 0, 0, 0, 4, 0, 0, 9, 0, 0, 20, 0, 4, 10, + 0, 0, 0, 0, 4, 0, 5, 0, 0, 8, 6, 0, 5, 4, + 0, 0, 3, 0, 4, 0, 0, 6, 6, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 9, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 17, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 14, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 14, 0, 0, 0, 0, 0, 0, 5, 6, 0, 5, 0, 0, + 0, 0, 0, 0, 5, 0, 8, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 16, 15, 4, 0, 0, 11, 0, 0, 0, 8, 0, 0, + 0, 0, 0, 0, 0, 2, 0, 5, 0, 10, 0, 0, 5, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, + 5, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 4, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8, 6, 5, 4, 0, 0, 0, + 0, 5, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 6, 0, + 0, 0, 0, 2, 4, 5, 0, 0, 0, 8, 0, 0, 3, 0, + 8, 0, 0, 4, 18, 0, 0, 0, 0, 4, 5, 0, 0, 0, + 16, 0, 0, 0, 0, 7, 0, 2, 3, 5, 0, 0, 5, 0, + 4, 4, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 14, 0, 0, 0, 0, 5, 0, 0, 6, 0, 6, 0, + 5, 0, 5, 0, 5, 15, 0, 0, 8, 17, 12, 0, 0, 0, + 0, 0, 6, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 5, 0, 0, 20, 0, 0, 0, 0, 0, + 11, 0, 5, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 13, + 0, 0, 0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 5, + 8, 0, 0, 0, 0, 0, 6, 14, 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, + 0, 13, 0, 0, 0, 0, 0, 8, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 7, + 0, 0, 16, 0, 14, 0, 18, 13, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 16, 0, 0, 0, 0, 0, + 0, 14, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 5, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, + 0, 0, 0, 8, 17, 0, 0, 0, 5, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, 9, 0, 15, 0, 5, 0, 5, 0, + 0, 0, 0, 0, 0, 6, 5, 0, 0, 0, 0, 6, 4, 0, + 0, 9, 0, 0, 0, 0, 0, 6, 0, 6, 0, 0, 8, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, + 6, 2, 0, 0, 6, 0, 12, 6, 0, 0, 0, 16, 0, 0, + 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 0, 0, 14, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10, 8, 0, 5, 0, 0, 6, + 0, 0, 0, 6, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 5, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 8, 0, 0, 0, 14, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 5, 0, 9, 0, + 0, 0, 5, 0, 0, 0, 0, 4, 6, 0, 0, 0, 0, 0, + 0, 8, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 21, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 0, 6, 0, 0, 0, 0, 0, 3, 5, 0, + 0, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 2, 0, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 8, 5, 14, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 5, 6, 0, 0, 4, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 13, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 12, 0, 0, 0, 18, 10, 0, 0, 18, 0, 7, 0, 0, + 0, 6, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 0, 5, 0, 0, 0, 0, 6, 0, 0, 5, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 4, 0, + 0, 0, 5, 0, 12, 4, 12, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 0, 4, 0, 0, 0, 0, + 7, 5, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 5, 0, 0, 0, 5, 6, 7, 7, 0, 0, 0, 0, 0, 0, + 0, 6, 0, 8, 0, 0, 0, 0, 5, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, + 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 16, 0, 0, 0, 0, 0, 0, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, + 4, 6, 0, 0, 0, 5, 0, 0, 0, 8, 0, 0, 0, 0, + 0, 17, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 0, 0, 0, 0, 17, 0, 5, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 8, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 8, 4, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 0, 4, 6, 8, 0, 5, 0, + 0, 4, 4, 0, 5, 4, 5, 0, 0, 0, 0, 0, 0, 6, + 0, 0, 5, 0, 0, 18, 0, 5, 0, 0, 0, 19, 0, 0, + 8, 0, 14, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 0, 5, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 11, 0, 5, 13, 0, 0, 0, 7, + 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 3, 0, 0, + 4, 0, 6, 13, 0, 8, 0, 5, 0, 0, 0, 5, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, + 3, 0, 3, 0, 3, 0, 3, 3, 3, 4, 0, 4, 0, 3, + 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, + 4, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 5, + 0, 18, 0, 0, 15, 7, 0, 3, 0, 0, 6, 5, 0, 5, + 0, 3, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 7, + 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, + 7, 10, 0, 0, 0, 0, 0, 4, 0, 0, 9, 0, 0, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 11, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 12, 0, 0, 0, 5, 6, 0, 0, 0, 0, + 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 5, 0, 17, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, 0, 6, 5, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 15, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6, 0, 9, 6, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 7, 0, 0, 20, 0, 5, 0, 0, + 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 5, 0, 0, + 0, 3, 0, 0, 6, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 14, 0, 0, 0, 0, 5, 6, 0, 0, 0, 0, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, + 0, 0, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 8, 0, 0, 5, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 6, 8, 0, 0, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 17, 0, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 0, 13, 0, 0, 0, 0, 7, 0, 0, 3, 14, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 0, 7, 5, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 6, 11, 19, 0, + 0, 5, 17, 0, 0, 0, 0, 0, 16, 5, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, + 7, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 7, 8, 0, 0, 0, 0, 0, 13, 0, 16, 5, 4, + 0, 0, 0, 6, 0, 0, 5, 0, 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, + 9, 6, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 7, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, + 9, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 7, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 6, 0, 0, 0, + 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, + 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 4, 10, 0, 0, 0, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 10, 0, 10, 0, + 0, 0, 21, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, + 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 11, 0, 20, 0, 3, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 5, 14, 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 5, 0, + 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 4, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 0, 0, + 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 5, 0, 0, + 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 7, 0, + 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 16, 5, 0, 15, 0, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 6, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 11, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, 4, 7, 0, 0, 0, 0, 0, 6, + 0, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 8, 0, 0, + 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 4, + 0, 0, 11, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 18, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 18, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 15, 0, 0, + 0, 0, 5, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, + 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 12, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 13, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 18, 0, 0, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 15, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 11, 0, + 0, 5, 0, 0, 0, 7, 0, 0, 0, 11, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 21, 16, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10, 0, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, + 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15 + }; + static const struct html_ent wordlist[] = + { + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1502 "src/html/html_unescape.gperf" + {"rarr", 3, {226, 134, 146}}, + {(char*)0}, +#line 834 "src/html/html_unescape.gperf" + {"larr", 3, {226, 134, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 845 "src/html/html_unescape.gperf" + {"lat", 3, {226, 170, 171}}, + {(char*)0}, {(char*)0}, +#line 1904 "src/html/html_unescape.gperf" + {"uarr", 3, {226, 134, 145}}, + {(char*)0}, {(char*)0}, +#line 1236 "src/html/html_unescape.gperf" + {"npr", 3, {226, 138, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1511 "src/html/html_unescape.gperf" + {"rarrtl", 3, {226, 134, 163}}, + {(char*)0}, +#line 842 "src/html/html_unescape.gperf" + {"larrtl", 3, {226, 134, 162}}, +#line 1602 "src/html/html_unescape.gperf" + {"roarr", 3, {226, 135, 190}}, + {(char*)0}, +#line 964 "src/html/html_unescape.gperf" + {"loarr", 3, {226, 135, 189}}, +#line 1169 "src/html/html_unescape.gperf" + {"not", 2, {194, 172}}, +#line 1610 "src/html/html_unescape.gperf" + {"rpar", 1, {41}}, +#line 147 "src/html/html_unescape.gperf" + {"bot", 3, {226, 138, 165}}, +#line 990 "src/html/html_unescape.gperf" + {"lpar", 1, {40}}, + {(char*)0}, +#line 1716 "src/html/html_unescape.gperf" + {"spar", 3, {226, 136, 165}}, + {(char*)0}, +#line 946 "src/html/html_unescape.gperf" + {"ll", 3, {226, 137, 170}}, +#line 1927 "src/html/html_unescape.gperf" + {"uharr", 3, {226, 134, 190}}, +#line 506 "src/html/html_unescape.gperf" + {"epar", 3, {226, 139, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 483 "src/html/html_unescape.gperf" + {"el", 3, {226, 170, 153}}, + {(char*)0}, +#line 1608 "src/html/html_unescape.gperf" + {"rotimes", 3, {226, 168, 181}}, + {(char*)0}, +#line 982 "src/html/html_unescape.gperf" + {"lotimes", 3, {226, 168, 180}}, +#line 1389 "src/html/html_unescape.gperf" + {"par", 3, {226, 136, 165}}, + {(char*)0}, +#line 1133 "src/html/html_unescape.gperf" + {"nharr", 3, {226, 134, 174}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1232 "src/html/html_unescape.gperf" + {"npar", 3, {226, 136, 166}}, + {(char*)0}, {(char*)0}, +#line 1873 "src/html/html_unescape.gperf" + {"tprime", 3, {226, 128, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 487 "src/html/html_unescape.gperf" + {"els", 3, {226, 170, 149}}, +#line 507 "src/html/html_unescape.gperf" + {"eparsl", 3, {226, 167, 163}}, + {(char*)0}, +#line 501 "src/html/html_unescape.gperf" + {"ensp", 3, {226, 128, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 194 "src/html/html_unescape.gperf" + {"bprime", 3, {226, 128, 181}}, +#line 956 "src/html/html_unescape.gperf" + {"lnap", 3, {226, 170, 137}}, +#line 138 "src/html/html_unescape.gperf" + {"blk14", 3, {226, 150, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 137 "src/html/html_unescape.gperf" + {"blk12", 3, {226, 150, 146}}, + {(char*)0}, +#line 139 "src/html/html_unescape.gperf" + {"blk34", 3, {226, 150, 147}}, + {(char*)0}, +#line 1233 "src/html/html_unescape.gperf" + {"nparsl", 3, {226, 171, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1144 "src/html/html_unescape.gperf" + {"nldr", 3, {226, 128, 165}}, +#line 1595 "src/html/html_unescape.gperf" + {"rlarr", 3, {226, 135, 132}}, +#line 1234 "src/html/html_unescape.gperf" + {"npart", 3, {226, 136, 130}}, +#line 945 "src/html/html_unescape.gperf" + {"llarr", 3, {226, 135, 135}}, +#line 1159 "src/html/html_unescape.gperf" + {"nlt", 3, {226, 137, 174}}, +#line 1697 "src/html/html_unescape.gperf" + {"slarr", 3, {226, 134, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1231 "src/html/html_unescape.gperf" + {"nparallel", 3, {226, 136, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1826 "src/html/html_unescape.gperf" + {"Tau", 2, {206, 164}}, +#line 1992 "src/html/html_unescape.gperf" + {"varr", 3, {226, 134, 149}}, + {(char*)0}, +#line 1739 "src/html/html_unescape.gperf" + {"squ", 3, {226, 150, 161}}, + {(char*)0}, {(char*)0}, +#line 1142 "src/html/html_unescape.gperf" + {"nlarr", 3, {226, 134, 154}}, + {(char*)0}, {(char*)0}, +#line 1827 "src/html/html_unescape.gperf" + {"tau", 2, {207, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 958 "src/html/html_unescape.gperf" + {"lne", 3, {226, 170, 135}}, +#line 1613 "src/html/html_unescape.gperf" + {"rrarr", 3, {226, 135, 137}}, + {(char*)0}, +#line 992 "src/html/html_unescape.gperf" + {"lrarr", 3, {226, 135, 134}}, + {(char*)0}, +#line 1741 "src/html/html_unescape.gperf" + {"srarr", 3, {226, 134, 146}}, +#line 1557 "src/html/html_unescape.gperf" + {"rharul", 3, {226, 165, 172}}, + {(char*)0}, +#line 941 "src/html/html_unescape.gperf" + {"lharul", 3, {226, 165, 170}}, +#line 526 "src/html/html_unescape.gperf" + {"erarr", 3, {226, 165, 177}}, + {(char*)0}, +#line 1434 "src/html/html_unescape.gperf" + {"pr", 3, {226, 137, 186}}, +#line 1556 "src/html/html_unescape.gperf" + {"rharu", 3, {226, 135, 128}}, + {(char*)0}, +#line 940 "src/html/html_unescape.gperf" + {"lharu", 3, {226, 134, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1905 "src/html/html_unescape.gperf" + {"Uarr", 3, {226, 134, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1129 "src/html/html_unescape.gperf" + {"nGt", 3, {226, 137, 171}}, + {(char*)0}, +#line 141 "src/html/html_unescape.gperf" + {"bne", 1, {61}}, +#line 1242 "src/html/html_unescape.gperf" + {"nrarr", 3, {226, 134, 155}}, + {(char*)0}, {(char*)0}, +#line 1819 "src/html/html_unescape.gperf" + {"swarr", 3, {226, 134, 153}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1498 "src/html/html_unescape.gperf" + {"rarrap", 3, {226, 165, 181}}, + {(char*)0}, +#line 1967 "src/html/html_unescape.gperf" + {"upuparrows", 3, {226, 135, 136}}, + {(char*)0}, +#line 345 "src/html/html_unescape.gperf" + {"Darr", 3, {226, 134, 161}}, + {(char*)0}, {(char*)0}, +#line 1517 "src/html/html_unescape.gperf" + {"rbarr", 3, {226, 164, 141}}, +#line 398 "src/html/html_unescape.gperf" + {"Dot", 2, {194, 168}}, +#line 848 "src/html/html_unescape.gperf" + {"lbarr", 3, {226, 164, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1307 "src/html/html_unescape.gperf" + {"nwarr", 3, {226, 134, 150}}, + {(char*)0}, +#line 1704 "src/html/html_unescape.gperf" + {"smt", 3, {226, 170, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 497 "src/html/html_unescape.gperf" + {"emsp14", 3, {226, 128, 133}}, +#line 1508 "src/html/html_unescape.gperf" + {"rarrpl", 3, {226, 165, 133}}, + {(char*)0}, +#line 840 "src/html/html_unescape.gperf" + {"larrpl", 3, {226, 164, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1406 "src/html/html_unescape.gperf" + {"phmmat", 3, {226, 132, 179}}, + {(char*)0}, +#line 496 "src/html/html_unescape.gperf" + {"emsp13", 3, {226, 128, 132}}, + {(char*)0}, +#line 1014 "src/html/html_unescape.gperf" + {"LT", 1, {60}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 835 "src/html/html_unescape.gperf" + {"Larr", 3, {226, 134, 158}}, +#line 1525 "src/html/html_unescape.gperf" + {"rbrkslu", 3, {226, 166, 144}}, + {(char*)0}, +#line 855 "src/html/html_unescape.gperf" + {"lbrkslu", 3, {226, 166, 141}}, + {(char*)0}, +#line 1082 "src/html/html_unescape.gperf" + {"napos", 2, {197, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1146 "src/html/html_unescape.gperf" + {"nle", 3, {226, 137, 176}}, + {(char*)0}, +#line 1554 "src/html/html_unescape.gperf" + {"rHar", 3, {226, 165, 164}}, + {(char*)0}, +#line 938 "src/html/html_unescape.gperf" + {"lHar", 3, {226, 165, 162}}, +#line 1477 "src/html/html_unescape.gperf" + {"qprime", 3, {226, 129, 151}}, + {(char*)0}, +#line 829 "src/html/html_unescape.gperf" + {"lap", 3, {226, 170, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1087 "src/html/html_unescape.gperf" + {"nbsp", 2, {194, 160}}, +#line 1925 "src/html/html_unescape.gperf" + {"uHar", 3, {226, 165, 163}}, +#line 1868 "src/html/html_unescape.gperf" + {"top", 3, {226, 138, 164}}, + {(char*)0}, +#line 2004 "src/html/html_unescape.gperf" + {"Vbar", 3, {226, 171, 171}}, + {(char*)0}, {(char*)0}, +#line 947 "src/html/html_unescape.gperf" + {"Ll", 3, {226, 139, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1432 "src/html/html_unescape.gperf" + {"prap", 3, {226, 170, 183}}, + {(char*)0}, +#line 498 "src/html/html_unescape.gperf" + {"emsp", 3, {226, 128, 131}}, + {(char*)0}, {(char*)0}, +#line 1079 "src/html/html_unescape.gperf" + {"nap", 3, {226, 137, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 976 "src/html/html_unescape.gperf" + {"looparrowleft", 3, {226, 134, 171}}, + {(char*)0}, +#line 870 "src/html/html_unescape.gperf" + {"le", 3, {226, 137, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1670 "src/html/html_unescape.gperf" + {"sharp", 3, {226, 153, 175}}, + {(char*)0}, +#line 474 "src/html/html_unescape.gperf" + {"ee", 3, {226, 133, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 914 "src/html/html_unescape.gperf" + {"les", 3, {226, 169, 189}}, +#line 745 "src/html/html_unescape.gperf" + {"in", 3, {226, 136, 136}}, +#line 1461 "src/html/html_unescape.gperf" + {"prop", 3, {226, 136, 157}}, + {(char*)0}, +#line 1866 "src/html/html_unescape.gperf" + {"topbot", 3, {226, 140, 182}}, + {(char*)0}, {(char*)0}, +#line 750 "src/html/html_unescape.gperf" + {"int", 3, {226, 136, 171}}, + {(char*)0}, +#line 1105 "src/html/html_unescape.gperf" + {"ne", 3, {226, 137, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1237 "src/html/html_unescape.gperf" + {"nprcue", 3, {226, 139, 160}}, + {(char*)0}, +#line 1447 "src/html/html_unescape.gperf" + {"pre", 3, {226, 170, 175}}, +#line 509 "src/html/html_unescape.gperf" + {"epsi", 2, {206, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1960 "src/html/html_unescape.gperf" + {"upsi", 2, {207, 133}}, +#line 1839 "src/html/html_unescape.gperf" + {"there4", 3, {226, 136, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1523 "src/html/html_unescape.gperf" + {"rbrke", 3, {226, 166, 140}}, +#line 1658 "src/html/html_unescape.gperf" + {"searr", 3, {226, 134, 152}}, +#line 853 "src/html/html_unescape.gperf" + {"lbrke", 3, {226, 166, 139}}, + {(char*)0}, +#line 132 "src/html/html_unescape.gperf" + {"blacktriangle", 3, {226, 150, 180}}, + {(char*)0}, {(char*)0}, +#line 960 "src/html/html_unescape.gperf" + {"lneq", 3, {226, 170, 135}}, + {(char*)0}, {(char*)0}, +#line 961 "src/html/html_unescape.gperf" + {"lneqq", 3, {226, 137, 168}}, + {(char*)0}, +#line 1418 "src/html/html_unescape.gperf" + {"plus", 1, {43}}, +#line 1154 "src/html/html_unescape.gperf" + {"nles", 3, {226, 169, 189}}, +#line 1106 "src/html/html_unescape.gperf" + {"nedot", 3, {226, 137, 144}}, +#line 134 "src/html/html_unescape.gperf" + {"blacktriangleleft", 3, {226, 151, 130}}, +#line 135 "src/html/html_unescape.gperf" + {"blacktriangleright", 3, {226, 150, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1102 "src/html/html_unescape.gperf" + {"nearr", 3, {226, 134, 151}}, + {(char*)0}, {(char*)0}, +#line 133 "src/html/html_unescape.gperf" + {"blacktriangledown", 3, {226, 150, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1155 "src/html/html_unescape.gperf" + {"nless", 3, {226, 137, 174}}, +#line 490 "src/html/html_unescape.gperf" + {"emacr", 2, {196, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2034 "src/html/html_unescape.gperf" + {"vprop", 3, {226, 136, 157}}, +#line 1934 "src/html/html_unescape.gperf" + {"umacr", 2, {197, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1701 "src/html/html_unescape.gperf" + {"smeparsl", 3, {226, 167, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1033 "src/html/html_unescape.gperf" + {"Map", 3, {226, 164, 133}}, + {(char*)0}, {(char*)0}, +#line 1420 "src/html/html_unescape.gperf" + {"plusdu", 3, {226, 168, 165}}, +#line 1168 "src/html/html_unescape.gperf" + {"Not", 3, {226, 171, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2019 "src/html/html_unescape.gperf" + {"Verbar", 3, {226, 128, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1399 "src/html/html_unescape.gperf" + {"perp", 3, {226, 138, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 561 "src/html/html_unescape.gperf" + {"fltns", 3, {226, 150, 177}}, +#line 1423 "src/html/html_unescape.gperf" + {"plusmn", 2, {194, 177}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1151 "src/html/html_unescape.gperf" + {"nleq", 3, {226, 137, 176}}, + {(char*)0}, {(char*)0}, +#line 1152 "src/html/html_unescape.gperf" + {"nleqq", 3, {226, 137, 166}}, + {(char*)0}, +#line 579 "src/html/html_unescape.gperf" + {"frac34", 2, {194, 190}}, +#line 573 "src/html/html_unescape.gperf" + {"frac14", 2, {194, 188}}, +#line 2018 "src/html/html_unescape.gperf" + {"verbar", 1, {124}}, +#line 571 "src/html/html_unescape.gperf" + {"frac12", 2, {194, 189}}, +#line 580 "src/html/html_unescape.gperf" + {"frac35", 3, {226, 133, 151}}, +#line 574 "src/html/html_unescape.gperf" + {"frac15", 3, {226, 133, 149}}, +#line 582 "src/html/html_unescape.gperf" + {"frac45", 3, {226, 133, 152}}, + {(char*)0}, {(char*)0}, +#line 578 "src/html/html_unescape.gperf" + {"frac25", 3, {226, 133, 150}}, + {(char*)0}, +#line 572 "src/html/html_unescape.gperf" + {"frac13", 3, {226, 133, 147}}, + {(char*)0}, +#line 575 "src/html/html_unescape.gperf" + {"frac16", 3, {226, 133, 153}}, +#line 1466 "src/html/html_unescape.gperf" + {"prurel", 3, {226, 138, 176}}, +#line 577 "src/html/html_unescape.gperf" + {"frac23", 3, {226, 133, 148}}, +#line 581 "src/html/html_unescape.gperf" + {"frac38", 3, {226, 133, 156}}, +#line 576 "src/html/html_unescape.gperf" + {"frac18", 3, {226, 133, 155}}, +#line 583 "src/html/html_unescape.gperf" + {"frac56", 3, {226, 133, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 584 "src/html/html_unescape.gperf" + {"frac58", 3, {226, 133, 157}}, + {(char*)0}, +#line 585 "src/html/html_unescape.gperf" + {"frac78", 3, {226, 133, 158}}, +#line 910 "src/html/html_unescape.gperf" + {"leq", 3, {226, 137, 164}}, +#line 344 "src/html/html_unescape.gperf" + {"darr", 3, {226, 134, 147}}, + {(char*)0}, {(char*)0}, +#line 1961 "src/html/html_unescape.gperf" + {"Upsi", 2, {207, 146}}, +#line 399 "src/html/html_unescape.gperf" + {"dot", 2, {203, 153}}, +#line 1407 "src/html/html_unescape.gperf" + {"phone", 3, {226, 152, 142}}, + {(char*)0}, {(char*)0}, +#line 219 "src/html/html_unescape.gperf" + {"Cap", 3, {226, 139, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 131 "src/html/html_unescape.gperf" + {"blacksquare", 3, {226, 150, 170}}, +#line 1600 "src/html/html_unescape.gperf" + {"rnmid", 3, {226, 171, 174}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 911 "src/html/html_unescape.gperf" + {"leqq", 3, {226, 137, 166}}, + {(char*)0}, {(char*)0}, +#line 749 "src/html/html_unescape.gperf" + {"intcal", 3, {226, 138, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 372 "src/html/html_unescape.gperf" + {"dharr", 3, {226, 135, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1555 "src/html/html_unescape.gperf" + {"rhard", 3, {226, 135, 129}}, + {(char*)0}, +#line 939 "src/html/html_unescape.gperf" + {"lhard", 3, {226, 134, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1421 "src/html/html_unescape.gperf" + {"pluse", 3, {226, 169, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1933 "src/html/html_unescape.gperf" + {"Umacr", 2, {197, 170}}, +#line 2015 "src/html/html_unescape.gperf" + {"Vee", 3, {226, 139, 129}}, + {(char*)0}, {(char*)0}, +#line 1503 "src/html/html_unescape.gperf" + {"Rarr", 3, {226, 134, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 304 "src/html/html_unescape.gperf" + {"Cross", 3, {226, 168, 175}}, + {(char*)0}, +#line 1620 "src/html/html_unescape.gperf" + {"rsqb", 1, {93}}, + {(char*)0}, +#line 1006 "src/html/html_unescape.gperf" + {"lsqb", 1, {91}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1510 "src/html/html_unescape.gperf" + {"Rarrtl", 3, {226, 164, 150}}, + {(char*)0}, {(char*)0}, +#line 530 "src/html/html_unescape.gperf" + {"esdot", 3, {226, 137, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2014 "src/html/html_unescape.gperf" + {"vee", 3, {226, 136, 168}}, +#line 1089 "src/html/html_unescape.gperf" + {"nbumpe", 3, {226, 137, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 948 "src/html/html_unescape.gperf" + {"llcorner", 3, {226, 140, 158}}, +#line 570 "src/html/html_unescape.gperf" + {"fpartint", 3, {226, 168, 141}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1740 "src/html/html_unescape.gperf" + {"squf", 3, {226, 150, 170}}, +#line 1414 "src/html/html_unescape.gperf" + {"plankv", 3, {226, 132, 143}}, + {(char*)0}, {(char*)0}, +#line 525 "src/html/html_unescape.gperf" + {"eqvparsl", 3, {226, 167, 165}}, + {(char*)0}, +#line 1930 "src/html/html_unescape.gperf" + {"ulcorner", 3, {226, 140, 156}}, + {(char*)0}, +#line 2055 "src/html/html_unescape.gperf" + {"wp", 3, {226, 132, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 989 "src/html/html_unescape.gperf" + {"lozf", 3, {226, 167, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 299 "src/html/html_unescape.gperf" + {"COPY", 2, {194, 169}}, + {(char*)0}, +#line 1929 "src/html/html_unescape.gperf" + {"ulcorn", 3, {226, 140, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2013 "src/html/html_unescape.gperf" + {"veebar", 3, {226, 138, 187}}, + {(char*)0}, +#line 1392 "src/html/html_unescape.gperf" + {"part", 3, {226, 136, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1730 "src/html/html_unescape.gperf" + {"square", 3, {226, 150, 161}}, + {(char*)0}, +#line 1088 "src/html/html_unescape.gperf" + {"nbump", 3, {226, 137, 142}}, +#line 108 "src/html/html_unescape.gperf" + {"bernou", 3, {226, 132, 172}}, +#line 2056 "src/html/html_unescape.gperf" + {"wr", 3, {226, 137, 128}}, +#line 1518 "src/html/html_unescape.gperf" + {"rBarr", 3, {226, 164, 143}}, +#line 993 "src/html/html_unescape.gperf" + {"lrcorner", 3, {226, 140, 159}}, +#line 849 "src/html/html_unescape.gperf" + {"lBarr", 3, {226, 164, 142}}, + {(char*)0}, {(char*)0}, +#line 144 "src/html/html_unescape.gperf" + {"bnot", 3, {226, 140, 144}}, + {(char*)0}, +#line 1662 "src/html/html_unescape.gperf" + {"semi", 1, {59}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1969 "src/html/html_unescape.gperf" + {"urcorner", 3, {226, 140, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1218 "src/html/html_unescape.gperf" + {"NotSubset", 3, {226, 138, 130}}, + {(char*)0}, +#line 1605 "src/html/html_unescape.gperf" + {"ropf", 4, {240, 157, 149, 163}}, +#line 1476 "src/html/html_unescape.gperf" + {"Qopf", 3, {226, 132, 154}}, +#line 980 "src/html/html_unescape.gperf" + {"lopf", 4, {240, 157, 149, 157}}, + {(char*)0}, +#line 1713 "src/html/html_unescape.gperf" + {"sopf", 4, {240, 157, 149, 164}}, +#line 1968 "src/html/html_unescape.gperf" + {"urcorn", 3, {226, 140, 157}}, +#line 1869 "src/html/html_unescape.gperf" + {"Topf", 4, {240, 157, 149, 139}}, +#line 2127 "src/html/html_unescape.gperf" + {"Zopf", 3, {226, 132, 164}}, +#line 505 "src/html/html_unescape.gperf" + {"eopf", 4, {240, 157, 149, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1604 "src/html/html_unescape.gperf" + {"ropar", 3, {226, 166, 134}}, +#line 1945 "src/html/html_unescape.gperf" + {"uopf", 4, {240, 157, 149, 166}}, +#line 978 "src/html/html_unescape.gperf" + {"lopar", 3, {226, 166, 133}}, +#line 1870 "src/html/html_unescape.gperf" + {"topf", 4, {240, 157, 149, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 2075 "src/html/html_unescape.gperf" + {"Xopf", 4, {240, 157, 149, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1166 "src/html/html_unescape.gperf" + {"nopf", 4, {240, 157, 149, 159}}, + {(char*)0}, +#line 146 "src/html/html_unescape.gperf" + {"bopf", 4, {240, 157, 149, 147}}, +#line 512 "src/html/html_unescape.gperf" + {"epsiv", 2, {207, 181}}, +#line 562 "src/html/html_unescape.gperf" + {"fnof", 2, {198, 146}}, +#line 734 "src/html/html_unescape.gperf" + {"imacr", 2, {196, 171}}, + {(char*)0}, {(char*)0}, +#line 792 "src/html/html_unescape.gperf" + {"Jopf", 4, {240, 157, 149, 129}}, + {(char*)0}, +#line 1135 "src/html/html_unescape.gperf" + {"nhpar", 3, {226, 171, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2053 "src/html/html_unescape.gperf" + {"Wopf", 4, {240, 157, 149, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1721 "src/html/html_unescape.gperf" + {"Sqrt", 3, {226, 136, 154}}, +#line 1263 "src/html/html_unescape.gperf" + {"nsub", 3, {226, 138, 132}}, + {(char*)0}, +#line 1081 "src/html/html_unescape.gperf" + {"napid", 3, {226, 137, 139}}, + {(char*)0}, {(char*)0}, +#line 1224 "src/html/html_unescape.gperf" + {"NotSuperset", 3, {226, 138, 131}}, + {(char*)0}, {(char*)0}, +#line 197 "src/html/html_unescape.gperf" + {"brvbar", 2, {194, 166}}, + {(char*)0}, {(char*)0}, +#line 1711 "src/html/html_unescape.gperf" + {"sol", 1, {47}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 461 "src/html/html_unescape.gperf" + {"easter", 3, {226, 169, 174}}, + {(char*)0}, +#line 1429 "src/html/html_unescape.gperf" + {"popf", 4, {240, 157, 149, 161}}, + {(char*)0}, {(char*)0}, +#line 370 "src/html/html_unescape.gperf" + {"dHar", 3, {226, 165, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2032 "src/html/html_unescape.gperf" + {"Vopf", 4, {240, 157, 149, 141}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1274 "src/html/html_unescape.gperf" + {"nsupset", 3, {226, 138, 131}}, +#line 1271 "src/html/html_unescape.gperf" + {"nsup", 3, {226, 138, 133}}, +#line 2003 "src/html/html_unescape.gperf" + {"vBar", 3, {226, 171, 168}}, + {(char*)0}, +#line 1266 "src/html/html_unescape.gperf" + {"nsubset", 3, {226, 138, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1851 "src/html/html_unescape.gperf" + {"thkap", 3, {226, 137, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1137 "src/html/html_unescape.gperf" + {"nis", 3, {226, 139, 188}}, +#line 1460 "src/html/html_unescape.gperf" + {"profsurf", 3, {226, 140, 147}}, +#line 1710 "src/html/html_unescape.gperf" + {"solb", 3, {226, 167, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 962 "src/html/html_unescape.gperf" + {"lnsim", 3, {226, 139, 166}}, + {(char*)0}, +#line 1709 "src/html/html_unescape.gperf" + {"solbar", 3, {226, 140, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1731 "src/html/html_unescape.gperf" + {"Square", 3, {226, 150, 161}}, + {(char*)0}, +#line 2033 "src/html/html_unescape.gperf" + {"vopf", 4, {240, 157, 149, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1926 "src/html/html_unescape.gperf" + {"uharl", 3, {226, 134, 191}}, + {(char*)0}, +#line 1931 "src/html/html_unescape.gperf" + {"ulcrop", 3, {226, 140, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 515 "src/html/html_unescape.gperf" + {"eqsim", 3, {226, 137, 130}}, +#line 523 "src/html/html_unescape.gperf" + {"equiv", 3, {226, 137, 161}}, + {(char*)0}, {(char*)0}, +#line 486 "src/html/html_unescape.gperf" + {"ell", 3, {226, 132, 147}}, +#line 1700 "src/html/html_unescape.gperf" + {"smashp", 3, {226, 168, 179}}, +#line 1067 "src/html/html_unescape.gperf" + {"mp", 3, {226, 136, 147}}, + {(char*)0}, {(char*)0}, +#line 814 "src/html/html_unescape.gperf" + {"Kopf", 4, {240, 157, 149, 130}}, + {(char*)0}, {(char*)0}, +#line 1696 "src/html/html_unescape.gperf" + {"simrarr", 3, {226, 165, 178}}, + {(char*)0}, +#line 559 "src/html/html_unescape.gperf" + {"flat", 3, {226, 153, 173}}, + {(char*)0}, +#line 1065 "src/html/html_unescape.gperf" + {"Mopf", 4, {240, 157, 149, 132}}, +#line 1712 "src/html/html_unescape.gperf" + {"Sopf", 4, {240, 157, 149, 138}}, +#line 1062 "src/html/html_unescape.gperf" + {"mldr", 3, {226, 128, 166}}, +#line 1597 "src/html/html_unescape.gperf" + {"rlm", 3, {226, 128, 143}}, +#line 768 "src/html/html_unescape.gperf" + {"iprod", 3, {226, 168, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 991 "src/html/html_unescape.gperf" + {"lparlt", 3, {226, 166, 147}}, + {(char*)0}, +#line 564 "src/html/html_unescape.gperf" + {"fopf", 4, {240, 157, 149, 151}}, +#line 1944 "src/html/html_unescape.gperf" + {"Uopf", 4, {240, 157, 149, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1996 "src/html/html_unescape.gperf" + {"varsubsetneq", 3, {226, 138, 138}}, +#line 1997 "src/html/html_unescape.gperf" + {"varsubsetneqq", 3, {226, 171, 139}}, + {(char*)0}, {(char*)0}, +#line 1970 "src/html/html_unescape.gperf" + {"urcrop", 3, {226, 140, 142}}, +#line 928 "src/html/html_unescape.gperf" + {"LessLess", 3, {226, 170, 161}}, + {(char*)0}, +#line 1543 "src/html/html_unescape.gperf" + {"Re", 3, {226, 132, 156}}, + {(char*)0}, {(char*)0}, +#line 1202 "src/html/html_unescape.gperf" + {"NotNestedLessLess", 3, {226, 170, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 396 "src/html/html_unescape.gperf" + {"Dopf", 4, {240, 157, 148, 187}}, + {(char*)0}, +#line 568 "src/html/html_unescape.gperf" + {"forkv", 3, {226, 171, 153}}, + {(char*)0}, +#line 1261 "src/html/html_unescape.gperf" + {"nsqsube", 3, {226, 139, 162}}, + {(char*)0}, +#line 1273 "src/html/html_unescape.gperf" + {"nsupe", 3, {226, 138, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1265 "src/html/html_unescape.gperf" + {"nsube", 3, {226, 138, 136}}, +#line 1475 "src/html/html_unescape.gperf" + {"qopf", 4, {240, 157, 149, 162}}, +#line 1596 "src/html/html_unescape.gperf" + {"rlhar", 3, {226, 135, 140}}, + {(char*)0}, {(char*)0}, +#line 996 "src/html/html_unescape.gperf" + {"lrm", 3, {226, 128, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1157 "src/html/html_unescape.gperf" + {"nlsim", 3, {226, 137, 180}}, + {(char*)0}, +#line 1431 "src/html/html_unescape.gperf" + {"pound", 2, {194, 163}}, +#line 1998 "src/html/html_unescape.gperf" + {"varsupsetneq", 3, {226, 138, 139}}, +#line 1999 "src/html/html_unescape.gperf" + {"varsupsetneqq", 3, {226, 171, 140}}, + {(char*)0}, +#line 142 "src/html/html_unescape.gperf" + {"bnequiv", 3, {226, 137, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 979 "src/html/html_unescape.gperf" + {"Lopf", 4, {240, 157, 149, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1262 "src/html/html_unescape.gperf" + {"nsqsupe", 3, {226, 139, 163}}, + {(char*)0}, {(char*)0}, +#line 1507 "src/html/html_unescape.gperf" + {"rarrlp", 3, {226, 134, 172}}, +#line 2046 "src/html/html_unescape.gperf" + {"wedbar", 3, {226, 169, 159}}, +#line 839 "src/html/html_unescape.gperf" + {"larrlp", 3, {226, 134, 171}}, + {(char*)0}, +#line 2101 "src/html/html_unescape.gperf" + {"Yopf", 4, {240, 157, 149, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1210 "src/html/html_unescape.gperf" + {"NotReverseElement", 3, {226, 136, 140}}, + {(char*)0}, {(char*)0}, +#line 295 "src/html/html_unescape.gperf" + {"Copf", 3, {226, 132, 130}}, +#line 994 "src/html/html_unescape.gperf" + {"lrhar", 3, {226, 135, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1391 "src/html/html_unescape.gperf" + {"parsl", 3, {226, 171, 189}}, +#line 1935 "src/html/html_unescape.gperf" + {"uml", 2, {194, 168}}, +#line 1039 "src/html/html_unescape.gperf" + {"marker", 3, {226, 150, 174}}, +#line 1275 "src/html/html_unescape.gperf" + {"nsupseteq", 3, {226, 138, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1267 "src/html/html_unescape.gperf" + {"nsubseteq", 3, {226, 138, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1738 "src/html/html_unescape.gperf" + {"squarf", 3, {226, 150, 170}}, +#line 2021 "src/html/html_unescape.gperf" + {"Vert", 3, {226, 128, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1736 "src/html/html_unescape.gperf" + {"SquareSupersetEqual", 3, {226, 138, 146}}, + {(char*)0}, +#line 1465 "src/html/html_unescape.gperf" + {"prsim", 3, {226, 137, 190}}, + {(char*)0}, {(char*)0}, +#line 1734 "src/html/html_unescape.gperf" + {"SquareSubsetEqual", 3, {226, 138, 145}}, + {(char*)0}, {(char*)0}, +#line 1735 "src/html/html_unescape.gperf" + {"SquareSuperset", 3, {226, 138, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1733 "src/html/html_unescape.gperf" + {"SquareSubset", 3, {226, 138, 143}}, +#line 1290 "src/html/html_unescape.gperf" + {"nvap", 3, {226, 137, 141}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 765 "src/html/html_unescape.gperf" + {"iopf", 4, {240, 157, 149, 154}}, + {(char*)0}, +#line 1426 "src/html/html_unescape.gperf" + {"pm", 2, {194, 177}}, + {(char*)0}, +#line 2020 "src/html/html_unescape.gperf" + {"vert", 1, {124}}, + {(char*)0}, +#line 1845 "src/html/html_unescape.gperf" + {"thetav", 2, {207, 145}}, + {(char*)0}, {(char*)0}, +#line 987 "src/html/html_unescape.gperf" + {"loz", 3, {226, 151, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1034 "src/html/html_unescape.gperf" + {"map", 3, {226, 134, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 923 "src/html/html_unescape.gperf" + {"lesseqqgtr", 3, {226, 170, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1616 "src/html/html_unescape.gperf" + {"rscr", 4, {240, 157, 147, 135}}, +#line 1478 "src/html/html_unescape.gperf" + {"Qscr", 4, {240, 157, 146, 172}}, +#line 999 "src/html/html_unescape.gperf" + {"lscr", 4, {240, 157, 147, 129}}, + {(char*)0}, +#line 1743 "src/html/html_unescape.gperf" + {"sscr", 4, {240, 157, 147, 136}}, + {(char*)0}, +#line 1891 "src/html/html_unescape.gperf" + {"Tscr", 4, {240, 157, 146, 175}}, +#line 2128 "src/html/html_unescape.gperf" + {"Zscr", 4, {240, 157, 146, 181}}, +#line 528 "src/html/html_unescape.gperf" + {"escr", 3, {226, 132, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1975 "src/html/html_unescape.gperf" + {"uscr", 4, {240, 157, 147, 138}}, + {(char*)0}, +#line 1892 "src/html/html_unescape.gperf" + {"tscr", 4, {240, 157, 147, 137}}, + {(char*)0}, +#line 741 "src/html/html_unescape.gperf" + {"imof", 3, {226, 138, 183}}, +#line 297 "src/html/html_unescape.gperf" + {"Coproduct", 3, {226, 136, 144}}, + {(char*)0}, {(char*)0}, +#line 2081 "src/html/html_unescape.gperf" + {"Xscr", 4, {240, 157, 146, 179}}, +#line 2068 "src/html/html_unescape.gperf" + {"Xi", 2, {206, 158}}, + {(char*)0}, {(char*)0}, +#line 1253 "src/html/html_unescape.gperf" + {"nscr", 4, {240, 157, 147, 131}}, +#line 1136 "src/html/html_unescape.gperf" + {"ni", 3, {226, 136, 139}}, +#line 198 "src/html/html_unescape.gperf" + {"bscr", 4, {240, 157, 146, 183}}, +#line 1167 "src/html/html_unescape.gperf" + {"Nopf", 3, {226, 132, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 794 "src/html/html_unescape.gperf" + {"Jscr", 4, {240, 157, 146, 165}}, +#line 1443 "src/html/html_unescape.gperf" + {"preceq", 3, {226, 170, 175}}, + {(char*)0}, {(char*)0}, +#line 1303 "src/html/html_unescape.gperf" + {"nvrArr", 3, {226, 164, 131}}, +#line 88 "src/html/html_unescape.gperf" + {"backprime", 3, {226, 128, 181}}, +#line 2058 "src/html/html_unescape.gperf" + {"Wscr", 4, {240, 157, 146, 178}}, + {(char*)0}, +#line 1989 "src/html/html_unescape.gperf" + {"varphi", 2, {207, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1259 "src/html/html_unescape.gperf" + {"nsmid", 3, {226, 136, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 393 "src/html/html_unescape.gperf" + {"dlcorn", 3, {226, 140, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1468 "src/html/html_unescape.gperf" + {"pscr", 4, {240, 157, 147, 133}}, +#line 1409 "src/html/html_unescape.gperf" + {"pi", 2, {207, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 2036 "src/html/html_unescape.gperf" + {"Vscr", 4, {240, 157, 146, 177}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1113 "src/html/html_unescape.gperf" + {"nesim", 3, {226, 137, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1694 "src/html/html_unescape.gperf" + {"simne", 3, {226, 137, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1276 "src/html/html_unescape.gperf" + {"nsupseteqq", 3, {226, 171, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1268 "src/html/html_unescape.gperf" + {"nsubseteqq", 3, {226, 171, 133}}, +#line 441 "src/html/html_unescape.gperf" + {"drcorn", 3, {226, 140, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1521 "src/html/html_unescape.gperf" + {"rbrace", 1, {125}}, +#line 2037 "src/html/html_unescape.gperf" + {"vscr", 4, {240, 157, 147, 139}}, +#line 851 "src/html/html_unescape.gperf" + {"lbrace", 1, {123}}, +#line 397 "src/html/html_unescape.gperf" + {"dopf", 4, {240, 157, 149, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 586 "src/html/html_unescape.gperf" + {"frasl", 3, {226, 129, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 931 "src/html/html_unescape.gperf" + {"LessTilde", 3, {226, 137, 178}}, + {(char*)0}, {(char*)0}, +#line 816 "src/html/html_unescape.gperf" + {"Kscr", 4, {240, 157, 146, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1417 "src/html/html_unescape.gperf" + {"pluscir", 3, {226, 168, 162}}, +#line 1069 "src/html/html_unescape.gperf" + {"Mscr", 3, {226, 132, 179}}, +#line 1742 "src/html/html_unescape.gperf" + {"Sscr", 4, {240, 157, 146, 174}}, +#line 1524 "src/html/html_unescape.gperf" + {"rbrksld", 3, {226, 166, 142}}, + {(char*)0}, +#line 854 "src/html/html_unescape.gperf" + {"lbrksld", 3, {226, 166, 143}}, +#line 1519 "src/html/html_unescape.gperf" + {"RBarr", 3, {226, 164, 144}}, + {(char*)0}, {(char*)0}, +#line 1718 "src/html/html_unescape.gperf" + {"sqcaps", 3, {226, 138, 147}}, +#line 1504 "src/html/html_unescape.gperf" + {"rArr", 3, {226, 135, 146}}, +#line 143 "src/html/html_unescape.gperf" + {"bNot", 3, {226, 171, 173}}, +#line 836 "src/html/html_unescape.gperf" + {"lArr", 3, {226, 135, 144}}, + {(char*)0}, +#line 588 "src/html/html_unescape.gperf" + {"fscr", 4, {240, 157, 146, 187}}, +#line 1974 "src/html/html_unescape.gperf" + {"Uscr", 4, {240, 157, 146, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1906 "src/html/html_unescape.gperf" + {"uArr", 3, {226, 135, 145}}, + {(char*)0}, {(char*)0}, +#line 1606 "src/html/html_unescape.gperf" + {"Ropf", 3, {226, 132, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2054 "src/html/html_unescape.gperf" + {"wopf", 4, {240, 157, 149, 168}}, + {(char*)0}, {(char*)0}, +#line 443 "src/html/html_unescape.gperf" + {"Dscr", 4, {240, 157, 146, 159}}, +#line 1352 "src/html/html_unescape.gperf" + {"opar", 3, {226, 166, 183}}, +#line 1663 "src/html/html_unescape.gperf" + {"seswar", 3, {226, 164, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 363 "src/html/html_unescape.gperf" + {"Del", 3, {226, 136, 135}}, +#line 1486 "src/html/html_unescape.gperf" + {"rAarr", 3, {226, 135, 155}}, +#line 1559 "src/html/html_unescape.gperf" + {"rho", 2, {207, 129}}, +#line 818 "src/html/html_unescape.gperf" + {"lAarr", 3, {226, 135, 154}}, +#line 1438 "src/html/html_unescape.gperf" + {"preccurlyeq", 3, {226, 137, 188}}, +#line 1479 "src/html/html_unescape.gperf" + {"qscr", 4, {240, 157, 147, 134}}, + {(char*)0}, {(char*)0}, +#line 1029 "src/html/html_unescape.gperf" + {"macr", 2, {194, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1186 "src/html/html_unescape.gperf" + {"notin", 3, {226, 136, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 524 "src/html/html_unescape.gperf" + {"equivDD", 3, {226, 169, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1717 "src/html/html_unescape.gperf" + {"sqcap", 3, {226, 138, 147}}, + {(char*)0}, +#line 1260 "src/html/html_unescape.gperf" + {"nspar", 3, {226, 136, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1341 "src/html/html_unescape.gperf" + {"olt", 3, {226, 167, 128}}, +#line 1515 "src/html/html_unescape.gperf" + {"ratio", 3, {226, 136, 182}}, +#line 1000 "src/html/html_unescape.gperf" + {"Lscr", 3, {226, 132, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 371 "src/html/html_unescape.gperf" + {"dharl", 3, {226, 135, 131}}, + {(char*)0}, +#line 394 "src/html/html_unescape.gperf" + {"dlcrop", 3, {226, 140, 141}}, +#line 409 "src/html/html_unescape.gperf" + {"DoubleDot", 2, {194, 168}}, +#line 405 "src/html/html_unescape.gperf" + {"dotplus", 3, {226, 136, 148}}, +#line 1359 "src/html/html_unescape.gperf" + {"or", 3, {226, 136, 168}}, + {(char*)0}, +#line 2103 "src/html/html_unescape.gperf" + {"Yscr", 4, {240, 157, 146, 180}}, + {(char*)0}, {(char*)0}, +#line 563 "src/html/html_unescape.gperf" + {"Fopf", 4, {240, 157, 148, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 305 "src/html/html_unescape.gperf" + {"Cscr", 4, {240, 157, 146, 158}}, +#line 1337 "src/html/html_unescape.gperf" + {"olarr", 3, {226, 134, 186}}, +#line 1244 "src/html/html_unescape.gperf" + {"nrarrw", 3, {226, 134, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1027 "src/html/html_unescape.gperf" + {"lvertneqq", 3, {226, 137, 168}}, +#line 516 "src/html/html_unescape.gperf" + {"eqslantgtr", 3, {226, 170, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1854 "src/html/html_unescape.gperf" + {"thorn", 2, {195, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 517 "src/html/html_unescape.gperf" + {"eqslantless", 3, {226, 170, 149}}, + {(char*)0}, {(char*)0}, +#line 744 "src/html/html_unescape.gperf" + {"incare", 3, {226, 132, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1993 "src/html/html_unescape.gperf" + {"vArr", 3, {226, 135, 149}}, +#line 1612 "src/html/html_unescape.gperf" + {"rppolint", 3, {226, 168, 146}}, +#line 442 "src/html/html_unescape.gperf" + {"drcrop", 3, {226, 140, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1388 "src/html/html_unescape.gperf" + {"parallel", 3, {226, 136, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1357 "src/html/html_unescape.gperf" + {"orarr", 3, {226, 134, 187}}, +#line 1745 "src/html/html_unescape.gperf" + {"ssmile", 3, {226, 140, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 413 "src/html/html_unescape.gperf" + {"DoubleLeftTee", 3, {226, 171, 164}}, +#line 527 "src/html/html_unescape.gperf" + {"erDot", 3, {226, 137, 147}}, +#line 382 "src/html/html_unescape.gperf" + {"diams", 3, {226, 153, 166}}, +#line 1744 "src/html/html_unescape.gperf" + {"ssetmn", 3, {226, 136, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1369 "src/html/html_unescape.gperf" + {"oS", 3, {226, 147, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 770 "src/html/html_unescape.gperf" + {"iscr", 4, {240, 157, 146, 190}}, +#line 726 "src/html/html_unescape.gperf" + {"ii", 3, {226, 133, 136}}, +#line 1544 "src/html/html_unescape.gperf" + {"rect", 3, {226, 150, 173}}, + {(char*)0}, {(char*)0}, +#line 1250 "src/html/html_unescape.gperf" + {"nsccue", 3, {226, 139, 161}}, +#line 1661 "src/html/html_unescape.gperf" + {"sect", 2, {194, 167}}, + {(char*)0}, +#line 1061 "src/html/html_unescape.gperf" + {"mlcp", 3, {226, 171, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1366 "src/html/html_unescape.gperf" + {"oror", 3, {226, 169, 150}}, + {(char*)0}, +#line 408 "src/html/html_unescape.gperf" + {"DoubleContourIntegral", 3, {226, 136, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 519 "src/html/html_unescape.gperf" + {"equals", 1, {61}}, + {(char*)0}, +#line 680 "src/html/html_unescape.gperf" + {"Hat", 1, {94}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1746 "src/html/html_unescape.gperf" + {"sstarf", 3, {226, 139, 134}}, +#line 1070 "src/html/html_unescape.gperf" + {"mstpos", 3, {226, 136, 190}}, + {(char*)0}, +#line 383 "src/html/html_unescape.gperf" + {"die", 2, {194, 168}}, +#line 1045 "src/html/html_unescape.gperf" + {"measuredangle", 3, {226, 136, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 565 "src/html/html_unescape.gperf" + {"forall", 3, {226, 136, 128}}, + {(char*)0}, {(char*)0}, +#line 1190 "src/html/html_unescape.gperf" + {"notinvb", 3, {226, 139, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1066 "src/html/html_unescape.gperf" + {"mopf", 4, {240, 157, 149, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1139 "src/html/html_unescape.gperf" + {"niv", 3, {226, 136, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 2005 "src/html/html_unescape.gperf" + {"vBarv", 3, {226, 171, 169}}, + {(char*)0}, +#line 1252 "src/html/html_unescape.gperf" + {"Nscr", 4, {240, 157, 146, 169}}, + {(char*)0}, +#line 1397 "src/html/html_unescape.gperf" + {"period", 1, {46}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 103 "src/html/html_unescape.gperf" + {"becaus", 3, {226, 136, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 113 "src/html/html_unescape.gperf" + {"between", 3, {226, 137, 172}}, +#line 751 "src/html/html_unescape.gperf" + {"Int", 3, {226, 136, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 104 "src/html/html_unescape.gperf" + {"because", 3, {226, 136, 181}}, +#line 1411 "src/html/html_unescape.gperf" + {"piv", 2, {207, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1552 "src/html/html_unescape.gperf" + {"rfr", 4, {240, 157, 148, 175}}, +#line 1472 "src/html/html_unescape.gperf" + {"Qfr", 4, {240, 157, 148, 148}}, +#line 935 "src/html/html_unescape.gperf" + {"lfr", 4, {240, 157, 148, 169}}, + {(char*)0}, +#line 1668 "src/html/html_unescape.gperf" + {"sfr", 4, {240, 157, 148, 176}}, +#line 1149 "src/html/html_unescape.gperf" + {"nleftrightarrow", 3, {226, 134, 174}}, +#line 1837 "src/html/html_unescape.gperf" + {"Tfr", 4, {240, 157, 148, 151}}, +#line 2122 "src/html/html_unescape.gperf" + {"Zfr", 3, {226, 132, 168}}, +#line 477 "src/html/html_unescape.gperf" + {"efr", 4, {240, 157, 148, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1686 "src/html/html_unescape.gperf" + {"sim", 3, {226, 136, 188}}, +#line 1922 "src/html/html_unescape.gperf" + {"ufr", 4, {240, 157, 148, 178}}, +#line 1607 "src/html/html_unescape.gperf" + {"roplus", 3, {226, 168, 174}}, +#line 1838 "src/html/html_unescape.gperf" + {"tfr", 4, {240, 157, 148, 177}}, +#line 981 "src/html/html_unescape.gperf" + {"loplus", 3, {226, 168, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2064 "src/html/html_unescape.gperf" + {"Xfr", 4, {240, 157, 148, 155}}, + {(char*)0}, {(char*)0}, +#line 1539 "src/html/html_unescape.gperf" + {"real", 3, {226, 132, 156}}, +#line 1120 "src/html/html_unescape.gperf" + {"nfr", 4, {240, 157, 148, 171}}, + {(char*)0}, +#line 115 "src/html/html_unescape.gperf" + {"bfr", 4, {240, 157, 148, 159}}, + {(char*)0}, +#line 1185 "src/html/html_unescape.gperf" + {"NotHumpEqual", 3, {226, 137, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 789 "src/html/html_unescape.gperf" + {"Jfr", 4, {240, 157, 148, 141}}, + {(char*)0}, +#line 444 "src/html/html_unescape.gperf" + {"dscr", 4, {240, 157, 146, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2051 "src/html/html_unescape.gperf" + {"Wfr", 4, {240, 157, 148, 154}}, + {(char*)0}, +#line 130 "src/html/html_unescape.gperf" + {"blacklozenge", 3, {226, 167, 171}}, + {(char*)0}, +#line 2126 "src/html/html_unescape.gperf" + {"zopf", 4, {240, 157, 149, 171}}, +#line 1542 "src/html/html_unescape.gperf" + {"reals", 3, {226, 132, 157}}, + {(char*)0}, +#line 1171 "src/html/html_unescape.gperf" + {"NotCupCap", 3, {226, 137, 173}}, + {(char*)0}, {(char*)0}, +#line 1695 "src/html/html_unescape.gperf" + {"simplus", 3, {226, 168, 164}}, + {(char*)0}, +#line 566 "src/html/html_unescape.gperf" + {"ForAll", 3, {226, 136, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1402 "src/html/html_unescape.gperf" + {"pfr", 4, {240, 157, 148, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1343 "src/html/html_unescape.gperf" + {"omacr", 2, {197, 141}}, + {(char*)0}, +#line 2027 "src/html/html_unescape.gperf" + {"Vfr", 4, {240, 157, 148, 153}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 489 "src/html/html_unescape.gperf" + {"Emacr", 2, {196, 146}}, +#line 1617 "src/html/html_unescape.gperf" + {"Rscr", 3, {226, 132, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2059 "src/html/html_unescape.gperf" + {"wscr", 4, {240, 157, 147, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1680 "src/html/html_unescape.gperf" + {"ShortUpArrow", 3, {226, 134, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1665 "src/html/html_unescape.gperf" + {"setmn", 3, {226, 136, 150}}, + {(char*)0}, +#line 2028 "src/html/html_unescape.gperf" + {"vfr", 4, {240, 157, 148, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 807 "src/html/html_unescape.gperf" + {"Kfr", 4, {240, 157, 148, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1355 "src/html/html_unescape.gperf" + {"operp", 3, {226, 166, 185}}, + {(char*)0}, +#line 1048 "src/html/html_unescape.gperf" + {"Mfr", 4, {240, 157, 148, 144}}, +#line 1667 "src/html/html_unescape.gperf" + {"Sfr", 4, {240, 157, 148, 150}}, + {(char*)0}, {(char*)0}, +#line 1161 "src/html/html_unescape.gperf" + {"nltrie", 3, {226, 139, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 589 "src/html/html_unescape.gperf" + {"Fscr", 3, {226, 132, 177}}, + {(char*)0}, {(char*)0}, +#line 554 "src/html/html_unescape.gperf" + {"ffr", 4, {240, 157, 148, 163}}, +#line 1921 "src/html/html_unescape.gperf" + {"Ufr", 4, {240, 157, 148, 152}}, + {(char*)0}, +#line 1677 "src/html/html_unescape.gperf" + {"shortmid", 3, {226, 136, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1305 "src/html/html_unescape.gperf" + {"nvsim", 3, {226, 136, 188}}, +#line 368 "src/html/html_unescape.gperf" + {"Dfr", 4, {240, 157, 148, 135}}, +#line 921 "src/html/html_unescape.gperf" + {"lessdot", 3, {226, 139, 150}}, + {(char*)0}, {(char*)0}, +#line 1459 "src/html/html_unescape.gperf" + {"profline", 3, {226, 140, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1473 "src/html/html_unescape.gperf" + {"qfr", 4, {240, 157, 148, 174}}, +#line 346 "src/html/html_unescape.gperf" + {"dArr", 3, {226, 135, 147}}, + {(char*)0}, +#line 1248 "src/html/html_unescape.gperf" + {"nrtrie", 3, {226, 139, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1679 "src/html/html_unescape.gperf" + {"ShortRightArrow", 3, {226, 134, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1841 "src/html/html_unescape.gperf" + {"Therefore", 3, {226, 136, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 358 "src/html/html_unescape.gperf" + {"DD", 3, {226, 133, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1840 "src/html/html_unescape.gperf" + {"therefore", 3, {226, 136, 180}}, +#line 934 "src/html/html_unescape.gperf" + {"Lfr", 4, {240, 157, 148, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1825 "src/html/html_unescape.gperf" + {"target", 3, {226, 140, 150}}, + {(char*)0}, {(char*)0}, +#line 484 "src/html/html_unescape.gperf" + {"Element", 3, {226, 136, 136}}, +#line 2097 "src/html/html_unescape.gperf" + {"Yfr", 4, {240, 157, 148, 156}}, +#line 272 "src/html/html_unescape.gperf" + {"ClockwiseContourIntegral", 3, {226, 136, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1338 "src/html/html_unescape.gperf" + {"olcir", 3, {226, 166, 190}}, + {(char*)0}, +#line 246 "src/html/html_unescape.gperf" + {"Cfr", 3, {226, 132, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 549 "src/html/html_unescape.gperf" + {"female", 3, {226, 153, 128}}, +#line 1270 "src/html/html_unescape.gperf" + {"nsucceq", 3, {226, 170, 176}}, +#line 1313 "src/html/html_unescape.gperf" + {"oast", 3, {226, 138, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1396 "src/html/html_unescape.gperf" + {"percnt", 1, {37}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1363 "src/html/html_unescape.gperf" + {"ordf", 2, {194, 170}}, + {(char*)0}, +#line 1360 "src/html/html_unescape.gperf" + {"ord", 3, {226, 169, 157}}, +#line 1558 "src/html/html_unescape.gperf" + {"Rho", 2, {206, 161}}, + {(char*)0}, +#line 1068 "src/html/html_unescape.gperf" + {"mscr", 4, {240, 157, 147, 130}}, + {(char*)0}, +#line 1304 "src/html/html_unescape.gperf" + {"nvrtrie", 3, {226, 138, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 959 "src/html/html_unescape.gperf" + {"lnE", 3, {226, 137, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1134 "src/html/html_unescape.gperf" + {"nhArr", 3, {226, 135, 142}}, +#line 1358 "src/html/html_unescape.gperf" + {"Or", 3, {226, 169, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 388 "src/html/html_unescape.gperf" + {"divide", 2, {195, 183}}, + {(char*)0}, +#line 722 "src/html/html_unescape.gperf" + {"ifr", 4, {240, 157, 148, 166}}, +#line 485 "src/html/html_unescape.gperf" + {"elinters", 3, {226, 143, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 204 "src/html/html_unescape.gperf" + {"bsol", 1, {92}}, +#line 1299 "src/html/html_unescape.gperf" + {"nvlArr", 3, {226, 164, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 733 "src/html/html_unescape.gperf" + {"Imacr", 2, {196, 170}}, + {(char*)0}, +#line 90 "src/html/html_unescape.gperf" + {"backsimeq", 3, {226, 139, 141}}, +#line 1899 "src/html/html_unescape.gperf" + {"twixt", 3, {226, 137, 172}}, +#line 1339 "src/html/html_unescape.gperf" + {"olcross", 3, {226, 166, 187}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1509 "src/html/html_unescape.gperf" + {"rarrsim", 3, {226, 165, 180}}, +#line 410 "src/html/html_unescape.gperf" + {"DoubleDownArrow", 3, {226, 135, 147}}, +#line 841 "src/html/html_unescape.gperf" + {"larrsim", 3, {226, 165, 179}}, +#line 492 "src/html/html_unescape.gperf" + {"emptyset", 3, {226, 136, 133}}, +#line 1351 "src/html/html_unescape.gperf" + {"oopf", 4, {240, 157, 149, 160}}, + {(char*)0}, +#line 541 "src/html/html_unescape.gperf" + {"exist", 3, {226, 136, 131}}, + {(char*)0}, {(char*)0}, +#line 950 "src/html/html_unescape.gperf" + {"llhard", 3, {226, 165, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 540 "src/html/html_unescape.gperf" + {"excl", 1, {33}}, +#line 504 "src/html/html_unescape.gperf" + {"Eopf", 4, {240, 157, 148, 188}}, +#line 1143 "src/html/html_unescape.gperf" + {"nlArr", 3, {226, 135, 141}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1850 "src/html/html_unescape.gperf" + {"thinsp", 3, {226, 128, 137}}, +#line 1219 "src/html/html_unescape.gperf" + {"NotSubsetEqual", 3, {226, 138, 136}}, +#line 1404 "src/html/html_unescape.gperf" + {"phi", 2, {207, 134}}, +#line 411 "src/html/html_unescape.gperf" + {"DoubleLeftArrow", 3, {226, 135, 144}}, + {(char*)0}, +#line 1867 "src/html/html_unescape.gperf" + {"topcir", 3, {226, 171, 177}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 387 "src/html/html_unescape.gperf" + {"div", 2, {195, 183}}, + {(char*)0}, +#line 1119 "src/html/html_unescape.gperf" + {"Nfr", 4, {240, 157, 148, 145}}, +#line 1145 "src/html/html_unescape.gperf" + {"nlE", 3, {226, 137, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 2129 "src/html/html_unescape.gperf" + {"zscr", 4, {240, 157, 147, 143}}, +#line 995 "src/html/html_unescape.gperf" + {"lrhard", 3, {226, 165, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 951 "src/html/html_unescape.gperf" + {"lltri", 3, {226, 151, 186}}, + {(char*)0}, {(char*)0}, +#line 1243 "src/html/html_unescape.gperf" + {"nrArr", 3, {226, 135, 143}}, +#line 1225 "src/html/html_unescape.gperf" + {"NotSupersetEqual", 3, {226, 138, 137}}, + {(char*)0}, +#line 1820 "src/html/html_unescape.gperf" + {"swArr", 3, {226, 135, 153}}, +#line 1848 "src/html/html_unescape.gperf" + {"ThickSpace", 3, {226, 129, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1932 "src/html/html_unescape.gperf" + {"ultri", 3, {226, 151, 184}}, +#line 1205 "src/html/html_unescape.gperf" + {"notnivb", 3, {226, 139, 190}}, + {(char*)0}, +#line 1450 "src/html/html_unescape.gperf" + {"prime", 3, {226, 128, 178}}, + {(char*)0}, {(char*)0}, +#line 1452 "src/html/html_unescape.gperf" + {"primes", 3, {226, 132, 153}}, + {(char*)0}, +#line 1335 "src/html/html_unescape.gperf" + {"ohm", 2, {206, 169}}, + {(char*)0}, {(char*)0}, +#line 265 "src/html/html_unescape.gperf" + {"CircleTimes", 3, {226, 138, 151}}, +#line 1160 "src/html/html_unescape.gperf" + {"nltri", 3, {226, 139, 170}}, + {(char*)0}, {(char*)0}, +#line 1692 "src/html/html_unescape.gperf" + {"siml", 3, {226, 170, 157}}, +#line 1308 "src/html/html_unescape.gperf" + {"nwArr", 3, {226, 135, 150}}, + {(char*)0}, {(char*)0}, +#line 1990 "src/html/html_unescape.gperf" + {"varpi", 2, {207, 150}}, + {(char*)0}, {(char*)0}, +#line 1368 "src/html/html_unescape.gperf" + {"orv", 3, {226, 169, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1664 "src/html/html_unescape.gperf" + {"setminus", 3, {226, 136, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 997 "src/html/html_unescape.gperf" + {"lrtri", 3, {226, 138, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1398 "src/html/html_unescape.gperf" + {"permil", 3, {226, 128, 176}}, +#line 1054 "src/html/html_unescape.gperf" + {"mid", 3, {226, 136, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1973 "src/html/html_unescape.gperf" + {"urtri", 3, {226, 151, 185}}, + {(char*)0}, {(char*)0}, +#line 369 "src/html/html_unescape.gperf" + {"dfr", 4, {240, 157, 148, 161}}, +#line 1050 "src/html/html_unescape.gperf" + {"mho", 3, {226, 132, 167}}, +#line 1448 "src/html/html_unescape.gperf" + {"prE", 3, {226, 170, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2041 "src/html/html_unescape.gperf" + {"vsupne", 3, {226, 138, 139}}, + {(char*)0}, {(char*)0}, +#line 1247 "src/html/html_unescape.gperf" + {"nrtri", 3, {226, 139, 171}}, +#line 2039 "src/html/html_unescape.gperf" + {"vsubne", 3, {226, 138, 138}}, + {(char*)0}, +#line 473 "src/html/html_unescape.gperf" + {"eDot", 3, {226, 137, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 919 "src/html/html_unescape.gperf" + {"lesges", 3, {226, 170, 147}}, + {(char*)0}, {(char*)0}, +#line 87 "src/html/html_unescape.gperf" + {"backepsilon", 2, {207, 182}}, + {(char*)0}, +#line 1513 "src/html/html_unescape.gperf" + {"ratail", 3, {226, 164, 154}}, + {(char*)0}, +#line 843 "src/html/html_unescape.gperf" + {"latail", 3, {226, 164, 153}}, + {(char*)0}, {(char*)0}, +#line 1954 "src/html/html_unescape.gperf" + {"UpEquilibrium", 3, {226, 165, 174}}, + {(char*)0}, {(char*)0}, +#line 511 "src/html/html_unescape.gperf" + {"epsilon", 2, {206, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1964 "src/html/html_unescape.gperf" + {"upsilon", 2, {207, 133}}, + {(char*)0}, +#line 1052 "src/html/html_unescape.gperf" + {"midast", 1, {42}}, +#line 698 "src/html/html_unescape.gperf" + {"Hopf", 3, {226, 132, 141}}, +#line 2029 "src/html/html_unescape.gperf" + {"vltri", 3, {226, 138, 178}}, + {(char*)0}, +#line 1553 "src/html/html_unescape.gperf" + {"Rfr", 3, {226, 132, 156}}, + {(char*)0}, {(char*)0}, +#line 2048 "src/html/html_unescape.gperf" + {"Wedge", 3, {226, 139, 128}}, +#line 2052 "src/html/html_unescape.gperf" + {"wfr", 4, {240, 157, 148, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 94 "src/html/html_unescape.gperf" + {"barwed", 3, {226, 140, 133}}, + {(char*)0}, {(char*)0}, +#line 1031 "src/html/html_unescape.gperf" + {"malt", 3, {226, 156, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 251 "src/html/html_unescape.gperf" + {"Chi", 2, {206, 167}}, +#line 494 "src/html/html_unescape.gperf" + {"emptyv", 3, {226, 136, 133}}, +#line 1203 "src/html/html_unescape.gperf" + {"notni", 3, {226, 136, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 926 "src/html/html_unescape.gperf" + {"LessGreater", 3, {226, 137, 182}}, + {(char*)0}, +#line 378 "src/html/html_unescape.gperf" + {"diam", 3, {226, 139, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2035 "src/html/html_unescape.gperf" + {"vrtri", 3, {226, 138, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 263 "src/html/html_unescape.gperf" + {"CircleMinus", 3, {226, 138, 150}}, + {(char*)0}, +#line 1342 "src/html/html_unescape.gperf" + {"Omacr", 2, {197, 140}}, +#line 1659 "src/html/html_unescape.gperf" + {"seArr", 3, {226, 135, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 553 "src/html/html_unescape.gperf" + {"Ffr", 4, {240, 157, 148, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1445 "src/html/html_unescape.gperf" + {"precneqq", 3, {226, 170, 181}}, + {(char*)0}, +#line 380 "src/html/html_unescape.gperf" + {"Diamond", 3, {226, 139, 132}}, +#line 1364 "src/html/html_unescape.gperf" + {"ordm", 2, {194, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1103 "src/html/html_unescape.gperf" + {"neArr", 3, {226, 135, 151}}, +#line 764 "src/html/html_unescape.gperf" + {"Iopf", 4, {240, 157, 149, 128}}, +#line 260 "src/html/html_unescape.gperf" + {"CircleDot", 3, {226, 138, 153}}, + {(char*)0}, {(char*)0}, +#line 1453 "src/html/html_unescape.gperf" + {"prnap", 3, {226, 170, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 404 "src/html/html_unescape.gperf" + {"dotminus", 3, {226, 136, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1254 "src/html/html_unescape.gperf" + {"nshortmid", 3, {226, 136, 164}}, + {(char*)0}, +#line 148 "src/html/html_unescape.gperf" + {"bottom", 3, {226, 138, 165}}, + {(char*)0}, +#line 1428 "src/html/html_unescape.gperf" + {"pointint", 3, {226, 168, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1737 "src/html/html_unescape.gperf" + {"SquareUnion", 3, {226, 138, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 793 "src/html/html_unescape.gperf" + {"jopf", 4, {240, 157, 149, 155}}, + {(char*)0}, {(char*)0}, +#line 1963 "src/html/html_unescape.gperf" + {"Upsilon", 2, {206, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 279 "src/html/html_unescape.gperf" + {"Colone", 3, {226, 169, 180}}, + {(char*)0}, +#line 1301 "src/html/html_unescape.gperf" + {"nvlt", 1, {60}}, + {(char*)0}, {(char*)0}, +#line 1115 "src/html/html_unescape.gperf" + {"NestedLessLess", 3, {226, 137, 170}}, +#line 278 "src/html/html_unescape.gperf" + {"Colon", 3, {226, 136, 183}}, + {(char*)0}, {(char*)0}, +#line 205 "src/html/html_unescape.gperf" + {"bsolhsub", 3, {226, 159, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 412 "src/html/html_unescape.gperf" + {"DoubleLeftRightArrow", 3, {226, 135, 148}}, +#line 1424 "src/html/html_unescape.gperf" + {"plussim", 3, {226, 168, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 735 "src/html/html_unescape.gperf" + {"image", 3, {226, 132, 145}}, +#line 481 "src/html/html_unescape.gperf" + {"egs", 3, {226, 170, 150}}, + {(char*)0}, {(char*)0}, +#line 1371 "src/html/html_unescape.gperf" + {"oscr", 3, {226, 132, 180}}, +#line 1822 "src/html/html_unescape.gperf" + {"swnwar", 3, {226, 164, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2117 "src/html/html_unescape.gperf" + {"zeetrf", 3, {226, 132, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1032 "src/html/html_unescape.gperf" + {"maltese", 3, {226, 156, 160}}, + {(char*)0}, +#line 1049 "src/html/html_unescape.gperf" + {"mfr", 4, {240, 157, 148, 170}}, +#line 1505 "src/html/html_unescape.gperf" + {"rarrfs", 3, {226, 164, 158}}, +#line 529 "src/html/html_unescape.gperf" + {"Escr", 3, {226, 132, 176}}, +#line 837 "src/html/html_unescape.gperf" + {"larrfs", 3, {226, 164, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1063 "src/html/html_unescape.gperf" + {"mnplus", 3, {226, 136, 147}}, +#line 1130 "src/html/html_unescape.gperf" + {"ngt", 3, {226, 137, 175}}, +#line 1131 "src/html/html_unescape.gperf" + {"ngtr", 3, {226, 137, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 628 "src/html/html_unescape.gperf" + {"gl", 3, {226, 137, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 381 "src/html/html_unescape.gperf" + {"diamondsuit", 3, {226, 153, 166}}, +#line 656 "src/html/html_unescape.gperf" + {"GT", 1, {62}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 929 "src/html/html_unescape.gperf" + {"lesssim", 3, {226, 137, 178}}, +#line 447 "src/html/html_unescape.gperf" + {"dsol", 3, {226, 167, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1955 "src/html/html_unescape.gperf" + {"upharpoonleft", 3, {226, 134, 191}}, +#line 1732 "src/html/html_unescape.gperf" + {"SquareIntersection", 3, {226, 138, 147}}, +#line 1004 "src/html/html_unescape.gperf" + {"lsime", 3, {226, 170, 141}}, + {(char*)0}, +#line 1158 "src/html/html_unescape.gperf" + {"nLt", 3, {226, 137, 170}}, + {(char*)0}, +#line 1195 "src/html/html_unescape.gperf" + {"NotLess", 3, {226, 137, 174}}, + {(char*)0}, +#line 631 "src/html/html_unescape.gperf" + {"gnap", 3, {226, 170, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1635 "src/html/html_unescape.gperf" + {"scap", 3, {226, 170, 184}}, + {(char*)0}, {(char*)0}, +#line 1037 "src/html/html_unescape.gperf" + {"mapstoleft", 3, {226, 134, 164}}, +#line 1198 "src/html/html_unescape.gperf" + {"NotLessLess", 3, {226, 137, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1551 "src/html/html_unescape.gperf" + {"rfloor", 3, {226, 140, 139}}, + {(char*)0}, +#line 933 "src/html/html_unescape.gperf" + {"lfloor", 3, {226, 140, 138}}, + {(char*)0}, {(char*)0}, +#line 1257 "src/html/html_unescape.gperf" + {"nsime", 3, {226, 137, 132}}, + {(char*)0}, +#line 202 "src/html/html_unescape.gperf" + {"bsime", 3, {226, 139, 141}}, +#line 1196 "src/html/html_unescape.gperf" + {"NotLessEqual", 3, {226, 137, 176}}, +#line 1200 "src/html/html_unescape.gperf" + {"NotLessTilde", 3, {226, 137, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1090 "src/html/html_unescape.gperf" + {"ncap", 3, {226, 169, 131}}, + {(char*)0}, {(char*)0}, +#line 1197 "src/html/html_unescape.gperf" + {"NotLessGreater", 3, {226, 137, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1449 "src/html/html_unescape.gperf" + {"precsim", 3, {226, 137, 190}}, + {(char*)0}, +#line 977 "src/html/html_unescape.gperf" + {"looparrowright", 3, {226, 134, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1433 "src/html/html_unescape.gperf" + {"Pr", 3, {226, 170, 187}}, +#line 1531 "src/html/html_unescape.gperf" + {"rcub", 1, {125}}, +#line 1038 "src/html/html_unescape.gperf" + {"mapstoup", 3, {226, 134, 165}}, +#line 861 "src/html/html_unescape.gperf" + {"lcub", 1, {123}}, + {(char*)0}, +#line 2121 "src/html/html_unescape.gperf" + {"zfr", 4, {240, 157, 148, 183}}, + {(char*)0}, {(char*)0}, +#line 1947 "src/html/html_unescape.gperf" + {"uparrow", 3, {226, 134, 145}}, + {(char*)0}, +#line 633 "src/html/html_unescape.gperf" + {"gne", 3, {226, 170, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1641 "src/html/html_unescape.gperf" + {"sce", 3, {226, 170, 176}}, +#line 740 "src/html/html_unescape.gperf" + {"Im", 3, {226, 132, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1527 "src/html/html_unescape.gperf" + {"rcaron", 2, {197, 153}}, + {(char*)0}, +#line 857 "src/html/html_unescape.gperf" + {"lcaron", 2, {196, 190}}, +#line 1350 "src/html/html_unescape.gperf" + {"Oopf", 4, {240, 157, 149, 134}}, +#line 1637 "src/html/html_unescape.gperf" + {"scaron", 2, {197, 161}}, +#line 89 "src/html/html_unescape.gperf" + {"backsim", 3, {226, 136, 189}}, +#line 1829 "src/html/html_unescape.gperf" + {"Tcaron", 2, {197, 164}}, +#line 2111 "src/html/html_unescape.gperf" + {"Zcaron", 2, {197, 189}}, +#line 463 "src/html/html_unescape.gperf" + {"ecaron", 2, {196, 155}}, + {(char*)0}, +#line 109 "src/html/html_unescape.gperf" + {"Bernoullis", 3, {226, 132, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1122 "src/html/html_unescape.gperf" + {"nge", 3, {226, 137, 177}}, +#line 1830 "src/html/html_unescape.gperf" + {"tcaron", 2, {197, 165}}, + {(char*)0}, +#line 567 "src/html/html_unescape.gperf" + {"fork", 3, {226, 139, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 702 "src/html/html_unescape.gperf" + {"Hscr", 3, {226, 132, 139}}, + {(char*)0}, +#line 1092 "src/html/html_unescape.gperf" + {"ncaron", 2, {197, 136}}, +#line 488 "src/html/html_unescape.gperf" + {"elsdot", 3, {226, 170, 151}}, + {(char*)0}, +#line 1828 "src/html/html_unescape.gperf" + {"tbrk", 3, {226, 142, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1887 "src/html/html_unescape.gperf" + {"triplus", 3, {226, 168, 185}}, + {(char*)0}, {(char*)0}, +#line 379 "src/html/html_unescape.gperf" + {"diamond", 3, {226, 139, 132}}, + {(char*)0}, {(char*)0}, +#line 1097 "src/html/html_unescape.gperf" + {"ncup", 3, {226, 169, 130}}, + {(char*)0}, +#line 97 "src/html/html_unescape.gperf" + {"bbrk", 3, {226, 142, 181}}, + {(char*)0}, +#line 587 "src/html/html_unescape.gperf" + {"frown", 3, {226, 140, 162}}, +#line 129 "src/html/html_unescape.gperf" + {"bkarow", 3, {226, 164, 141}}, + {(char*)0}, +#line 1714 "src/html/html_unescape.gperf" + {"spades", 3, {226, 153, 160}}, + {(char*)0}, +#line 1470 "src/html/html_unescape.gperf" + {"psi", 2, {207, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 145 "src/html/html_unescape.gperf" + {"Bopf", 4, {240, 157, 148, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 395 "src/html/html_unescape.gperf" + {"dollar", 1, {36}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 386 "src/html/html_unescape.gperf" + {"disin", 3, {226, 139, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1715 "src/html/html_unescape.gperf" + {"spadesuit", 3, {226, 153, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1226 "src/html/html_unescape.gperf" + {"NotTilde", 3, {226, 137, 129}}, +#line 407 "src/html/html_unescape.gperf" + {"doublebarwedge", 3, {226, 140, 134}}, + {(char*)0}, +#line 595 "src/html/html_unescape.gperf" + {"gap", 3, {226, 170, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 98 "src/html/html_unescape.gperf" + {"bbrktbrk", 3, {226, 142, 182}}, + {(char*)0}, {(char*)0}, +#line 1821 "src/html/html_unescape.gperf" + {"swarrow", 3, {226, 134, 153}}, +#line 107 "src/html/html_unescape.gperf" + {"bepsi", 2, {207, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 771 "src/html/html_unescape.gperf" + {"Iscr", 3, {226, 132, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1228 "src/html/html_unescape.gperf" + {"NotTildeFullEqual", 3, {226, 137, 135}}, +#line 514 "src/html/html_unescape.gperf" + {"eqcolon", 3, {226, 137, 149}}, + {(char*)0}, {(char*)0}, +#line 1864 "src/html/html_unescape.gperf" + {"tint", 3, {226, 136, 173}}, + {(char*)0}, {(char*)0}, +#line 757 "src/html/html_unescape.gperf" + {"intprod", 3, {226, 168, 188}}, + {(char*)0}, +#line 1272 "src/html/html_unescape.gperf" + {"nsupE", 3, {226, 171, 134}}, + {(char*)0}, {(char*)0}, +#line 1309 "src/html/html_unescape.gperf" + {"nwarrow", 3, {226, 134, 150}}, +#line 1264 "src/html/html_unescape.gperf" + {"nsubE", 3, {226, 171, 133}}, + {(char*)0}, {(char*)0}, +#line 1126 "src/html/html_unescape.gperf" + {"nges", 3, {226, 169, 190}}, + {(char*)0}, +#line 1949 "src/html/html_unescape.gperf" + {"Uparrow", 3, {226, 135, 145}}, +#line 605 "src/html/html_unescape.gperf" + {"ge", 3, {226, 137, 165}}, +#line 1353 "src/html/html_unescape.gperf" + {"OpenCurlyDoubleQuote", 3, {226, 128, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1699 "src/html/html_unescape.gperf" + {"smallsetminus", 3, {226, 136, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1636 "src/html/html_unescape.gperf" + {"Scaron", 2, {197, 160}}, + {(char*)0}, +#line 1302 "src/html/html_unescape.gperf" + {"nvltrie", 3, {226, 138, 180}}, +#line 613 "src/html/html_unescape.gperf" + {"ges", 3, {226, 169, 190}}, +#line 136 "src/html/html_unescape.gperf" + {"blank", 3, {226, 144, 163}}, +#line 1485 "src/html/html_unescape.gperf" + {"QUOT", 1, {34}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 140 "src/html/html_unescape.gperf" + {"block", 3, {226, 150, 136}}, +#line 1874 "src/html/html_unescape.gperf" + {"trade", 3, {226, 132, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 795 "src/html/html_unescape.gperf" + {"jscr", 4, {240, 157, 146, 191}}, +#line 2047 "src/html/html_unescape.gperf" + {"wedge", 3, {226, 136, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 30 "src/html/html_unescape.gperf" + {"Amacr", 2, {196, 128}}, + {(char*)0}, +#line 518 "src/html/html_unescape.gperf" + {"Equal", 3, {226, 169, 181}}, + {(char*)0}, {(char*)0}, +#line 352 "src/html/html_unescape.gperf" + {"Dcaron", 2, {196, 142}}, + {(char*)0}, {(char*)0}, +#line 400 "src/html/html_unescape.gperf" + {"DotDot", 3, {226, 131, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 635 "src/html/html_unescape.gperf" + {"gneq", 3, {226, 170, 136}}, +#line 1991 "src/html/html_unescape.gperf" + {"varpropto", 3, {226, 136, 157}}, + {(char*)0}, +#line 636 "src/html/html_unescape.gperf" + {"gneqq", 3, {226, 137, 169}}, +#line 1462 "src/html/html_unescape.gperf" + {"Proportional", 3, {226, 136, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 775 "src/html/html_unescape.gperf" + {"isins", 3, {226, 139, 180}}, + {(char*)0}, +#line 470 "src/html/html_unescape.gperf" + {"eDDot", 3, {226, 169, 183}}, +#line 772 "src/html/html_unescape.gperf" + {"isin", 3, {226, 136, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1886 "src/html/html_unescape.gperf" + {"TripleDot", 3, {226, 131, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 569 "src/html/html_unescape.gperf" + {"Fouriertrf", 3, {226, 132, 177}}, +#line 1463 "src/html/html_unescape.gperf" + {"Proportion", 3, {226, 136, 183}}, + {(char*)0}, {(char*)0}, +#line 1123 "src/html/html_unescape.gperf" + {"ngeq", 3, {226, 137, 177}}, +#line 856 "src/html/html_unescape.gperf" + {"Lcaron", 2, {196, 189}}, + {(char*)0}, +#line 1124 "src/html/html_unescape.gperf" + {"ngeqq", 3, {226, 137, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 871 "src/html/html_unescape.gperf" + {"lE", 3, {226, 137, 166}}, +#line 228 "src/html/html_unescape.gperf" + {"Ccaron", 2, {196, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 200 "src/html/html_unescape.gperf" + {"bsemi", 3, {226, 129, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1464 "src/html/html_unescape.gperf" + {"propto", 3, {226, 136, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 915 "src/html/html_unescape.gperf" + {"lesdot", 3, {226, 169, 191}}, +#line 292 "src/html/html_unescape.gperf" + {"Conint", 3, {226, 136, 175}}, + {(char*)0}, +#line 36 "src/html/html_unescape.gperf" + {"And", 3, {226, 169, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1660 "src/html/html_unescape.gperf" + {"searrow", 3, {226, 134, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1367 "src/html/html_unescape.gperf" + {"orslope", 3, {226, 169, 151}}, +#line 677 "src/html/html_unescape.gperf" + {"harr", 3, {226, 134, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 846 "src/html/html_unescape.gperf" + {"late", 3, {226, 170, 173}}, + {(char*)0}, +#line 244 "src/html/html_unescape.gperf" + {"CenterDot", 2, {194, 183}}, + {(char*)0}, {(char*)0}, +#line 1329 "src/html/html_unescape.gperf" + {"ofr", 4, {240, 157, 148, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1104 "src/html/html_unescape.gperf" + {"nearrow", 3, {226, 134, 151}}, + {(char*)0}, +#line 1474 "src/html/html_unescape.gperf" + {"qint", 3, {226, 168, 140}}, + {(char*)0}, {(char*)0}, +#line 847 "src/html/html_unescape.gperf" + {"lates", 3, {226, 170, 173}}, +#line 802 "src/html/html_unescape.gperf" + {"kappav", 2, {207, 176}}, + {(char*)0}, {(char*)0}, +#line 699 "src/html/html_unescape.gperf" + {"horbar", 3, {226, 128, 149}}, +#line 476 "src/html/html_unescape.gperf" + {"Efr", 4, {240, 157, 148, 136}}, +#line 693 "src/html/html_unescape.gperf" + {"hoarr", 3, {226, 135, 191}}, +#line 1240 "src/html/html_unescape.gperf" + {"npre", 3, {226, 170, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 748 "src/html/html_unescape.gperf" + {"inodot", 2, {196, 177}}, + {(char*)0}, +#line 1916 "src/html/html_unescape.gperf" + {"udarr", 3, {226, 135, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 609 "src/html/html_unescape.gperf" + {"geq", 3, {226, 137, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1258 "src/html/html_unescape.gperf" + {"nsimeq", 3, {226, 137, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 610 "src/html/html_unescape.gperf" + {"geqq", 3, {226, 137, 167}}, + {(char*)0}, {(char*)0}, +#line 475 "src/html/html_unescape.gperf" + {"efDot", 3, {226, 137, 146}}, + {(char*)0}, {(char*)0}, +#line 1611 "src/html/html_unescape.gperf" + {"rpargt", 3, {226, 166, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1370 "src/html/html_unescape.gperf" + {"Oscr", 4, {240, 157, 146, 170}}, + {(char*)0}, {(char*)0}, +#line 1419 "src/html/html_unescape.gperf" + {"plusdo", 3, {226, 136, 148}}, + {(char*)0}, {(char*)0}, +#line 822 "src/html/html_unescape.gperf" + {"lagran", 3, {226, 132, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1847 "src/html/html_unescape.gperf" + {"thicksim", 3, {226, 136, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1446 "src/html/html_unescape.gperf" + {"precnsim", 3, {226, 139, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1091 "src/html/html_unescape.gperf" + {"Ncaron", 2, {197, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1080 "src/html/html_unescape.gperf" + {"napE", 3, {226, 169, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 728 "src/html/html_unescape.gperf" + {"iiint", 3, {226, 136, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 199 "src/html/html_unescape.gperf" + {"Bscr", 3, {226, 132, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1036 "src/html/html_unescape.gperf" + {"mapstodown", 3, {226, 134, 167}}, + {(char*)0}, {(char*)0}, +#line 1994 "src/html/html_unescape.gperf" + {"varrho", 2, {207, 177}}, + {(char*)0}, +#line 776 "src/html/html_unescape.gperf" + {"isinsv", 3, {226, 139, 179}}, + {(char*)0}, {(char*)0}, +#line 1297 "src/html/html_unescape.gperf" + {"nvHarr", 3, {226, 164, 132}}, + {(char*)0}, {(char*)0}, +#line 1192 "src/html/html_unescape.gperf" + {"NotLeftTriangleBar", 3, {226, 167, 143}}, + {(char*)0}, +#line 521 "src/html/html_unescape.gperf" + {"equest", 3, {226, 137, 159}}, + {(char*)0}, +#line 1194 "src/html/html_unescape.gperf" + {"NotLeftTriangleEqual", 3, {226, 139, 172}}, +#line 1193 "src/html/html_unescape.gperf" + {"NotLeftTriangle", 3, {226, 139, 170}}, + {(char*)0}, {(char*)0}, +#line 61 "src/html/html_unescape.gperf" + {"Aopf", 4, {240, 157, 148, 184}}, +#line 681 "src/html/html_unescape.gperf" + {"hbar", 3, {226, 132, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1985 "src/html/html_unescape.gperf" + {"vangrt", 3, {226, 166, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 689 "src/html/html_unescape.gperf" + {"Hfr", 3, {226, 132, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1495 "src/html/html_unescape.gperf" + {"range", 3, {226, 166, 165}}, +#line 1705 "src/html/html_unescape.gperf" + {"smte", 3, {226, 170, 172}}, +#line 1003 "src/html/html_unescape.gperf" + {"lsim", 3, {226, 137, 178}}, + {(char*)0}, +#line 1235 "src/html/html_unescape.gperf" + {"npolint", 3, {226, 168, 148}}, + {(char*)0}, +#line 353 "src/html/html_unescape.gperf" + {"dcaron", 2, {196, 143}}, + {(char*)0}, +#line 532 "src/html/html_unescape.gperf" + {"esim", 3, {226, 137, 130}}, + {(char*)0}, +#line 1940 "src/html/html_unescape.gperf" + {"Union", 3, {226, 139, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1706 "src/html/html_unescape.gperf" + {"smtes", 3, {226, 170, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 815 "src/html/html_unescape.gperf" + {"kopf", 4, {240, 157, 149, 156}}, +#line 639 "src/html/html_unescape.gperf" + {"gopf", 4, {240, 157, 149, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1256 "src/html/html_unescape.gperf" + {"nsim", 3, {226, 137, 129}}, + {(char*)0}, +#line 201 "src/html/html_unescape.gperf" + {"bsim", 3, {226, 136, 189}}, + {(char*)0}, +#line 1698 "src/html/html_unescape.gperf" + {"SmallCircle", 3, {226, 136, 152}}, + {(char*)0}, +#line 1172 "src/html/html_unescape.gperf" + {"NotDoubleVerticalBar", 3, {226, 136, 166}}, +#line 1201 "src/html/html_unescape.gperf" + {"NotNestedGreaterGreater", 3, {226, 170, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 520 "src/html/html_unescape.gperf" + {"EqualTilde", 3, {226, 137, 130}}, + {(char*)0}, {(char*)0}, +#line 1187 "src/html/html_unescape.gperf" + {"notindot", 3, {226, 139, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1526 "src/html/html_unescape.gperf" + {"Rcaron", 2, {197, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1430 "src/html/html_unescape.gperf" + {"Popf", 3, {226, 132, 153}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 638 "src/html/html_unescape.gperf" + {"Gopf", 4, {240, 157, 148, 190}}, + {(char*)0}, {(char*)0}, +#line 723 "src/html/html_unescape.gperf" + {"Ifr", 3, {226, 132, 145}}, + {(char*)0}, {(char*)0}, +#line 2049 "src/html/html_unescape.gperf" + {"wedgeq", 3, {226, 137, 153}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1456 "src/html/html_unescape.gperf" + {"prod", 3, {226, 136, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1374 "src/html/html_unescape.gperf" + {"osol", 3, {226, 138, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 419 "src/html/html_unescape.gperf" + {"DoubleUpArrow", 3, {226, 135, 145}}, + {(char*)0}, {(char*)0}, +#line 290 "src/html/html_unescape.gperf" + {"Congruent", 3, {226, 137, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 637 "src/html/html_unescape.gperf" + {"gnsim", 3, {226, 139, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1651 "src/html/html_unescape.gperf" + {"scsim", 3, {226, 137, 191}}, + {(char*)0}, +#line 790 "src/html/html_unescape.gperf" + {"jfr", 4, {240, 157, 148, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1962 "src/html/html_unescape.gperf" + {"upsih", 2, {207, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1156 "src/html/html_unescape.gperf" + {"nLl", 3, {226, 139, 152}}, + {(char*)0}, {(char*)0}, +#line 420 "src/html/html_unescape.gperf" + {"DoubleUpDownArrow", 3, {226, 135, 149}}, + {(char*)0}, +#line 1128 "src/html/html_unescape.gperf" + {"ngsim", 3, {226, 137, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 684 "src/html/html_unescape.gperf" + {"hearts", 3, {226, 153, 165}}, + {(char*)0}, +#line 922 "src/html/html_unescape.gperf" + {"lesseqgtr", 3, {226, 139, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1112 "src/html/html_unescape.gperf" + {"nesear", 3, {226, 164, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 542 "src/html/html_unescape.gperf" + {"Exists", 3, {226, 136, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1703 "src/html/html_unescape.gperf" + {"smile", 3, {226, 140, 163}}, + {(char*)0}, +#line 1984 "src/html/html_unescape.gperf" + {"uwangle", 3, {226, 166, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 685 "src/html/html_unescape.gperf" + {"heartsuit", 3, {226, 153, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 700 "src/html/html_unescape.gperf" + {"HorizontalLine", 3, {226, 148, 128}}, + {(char*)0}, {(char*)0}, +#line 645 "src/html/html_unescape.gperf" + {"GreaterLess", 3, {226, 137, 183}}, + {(char*)0}, +#line 1615 "src/html/html_unescape.gperf" + {"rsaquo", 3, {226, 128, 186}}, + {(char*)0}, +#line 998 "src/html/html_unescape.gperf" + {"lsaquo", 3, {226, 128, 185}}, + {(char*)0}, +#line 1540 "src/html/html_unescape.gperf" + {"realine", 3, {226, 132, 155}}, +#line 348 "src/html/html_unescape.gperf" + {"Dashv", 3, {226, 171, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1687 "src/html/html_unescape.gperf" + {"simdot", 3, {226, 169, 170}}, +#line 641 "src/html/html_unescape.gperf" + {"GreaterEqual", 3, {226, 137, 165}}, +#line 647 "src/html/html_unescape.gperf" + {"GreaterTilde", 3, {226, 137, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 642 "src/html/html_unescape.gperf" + {"GreaterEqualLess", 3, {226, 139, 155}}, + {(char*)0}, +#line 644 "src/html/html_unescape.gperf" + {"GreaterGreater", 3, {226, 170, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1530 "src/html/html_unescape.gperf" + {"rceil", 3, {226, 140, 137}}, + {(char*)0}, +#line 860 "src/html/html_unescape.gperf" + {"lceil", 3, {226, 140, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 927 "src/html/html_unescape.gperf" + {"lessgtr", 3, {226, 137, 182}}, + {(char*)0}, {(char*)0}, +#line 1340 "src/html/html_unescape.gperf" + {"oline", 3, {226, 128, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1852 "src/html/html_unescape.gperf" + {"thksim", 3, {226, 136, 188}}, + {(char*)0}, +#line 759 "src/html/html_unescape.gperf" + {"InvisibleTimes", 3, {226, 129, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1487 "src/html/html_unescape.gperf" + {"race", 3, {226, 136, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 769 "src/html/html_unescape.gperf" + {"iquest", 2, {194, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 737 "src/html/html_unescape.gperf" + {"imagline", 3, {226, 132, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1966 "src/html/html_unescape.gperf" + {"UpTee", 3, {226, 138, 165}}, + {(char*)0}, +#line 1053 "src/html/html_unescape.gperf" + {"midcir", 3, {226, 171, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1327 "src/html/html_unescape.gperf" + {"ofcir", 3, {226, 166, 191}}, + {(char*)0}, {(char*)0}, +#line 357 "src/html/html_unescape.gperf" + {"ddarr", 3, {226, 135, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1494 "src/html/html_unescape.gperf" + {"rangd", 3, {226, 166, 146}}, + {(char*)0}, +#line 827 "src/html/html_unescape.gperf" + {"langd", 3, {226, 166, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 522 "src/html/html_unescape.gperf" + {"Equilibrium", 3, {226, 135, 140}}, +#line 1390 "src/html/html_unescape.gperf" + {"parsim", 3, {226, 171, 179}}, +#line 2012 "src/html/html_unescape.gperf" + {"Vdashl", 3, {226, 171, 166}}, +#line 1328 "src/html/html_unescape.gperf" + {"Ofr", 4, {240, 157, 148, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 105 "src/html/html_unescape.gperf" + {"Because", 3, {226, 136, 181}}, + {(char*)0}, +#line 1514 "src/html/html_unescape.gperf" + {"rAtail", 3, {226, 164, 156}}, + {(char*)0}, +#line 844 "src/html/html_unescape.gperf" + {"lAtail", 3, {226, 164, 155}}, +#line 1349 "src/html/html_unescape.gperf" + {"ominus", 3, {226, 138, 150}}, +#line 74 "src/html/html_unescape.gperf" + {"Ascr", 4, {240, 157, 146, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 510 "src/html/html_unescape.gperf" + {"Epsilon", 2, {206, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1676 "src/html/html_unescape.gperf" + {"ShortLeftArrow", 3, {226, 134, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 777 "src/html/html_unescape.gperf" + {"isinv", 3, {226, 136, 136}}, + {(char*)0}, +#line 1051 "src/html/html_unescape.gperf" + {"micro", 2, {194, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2112 "src/html/html_unescape.gperf" + {"zcaron", 2, {197, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 817 "src/html/html_unescape.gperf" + {"kscr", 4, {240, 157, 147, 128}}, +#line 649 "src/html/html_unescape.gperf" + {"gscr", 3, {226, 132, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 114 "src/html/html_unescape.gperf" + {"Bfr", 4, {240, 157, 148, 133}}, +#line 608 "src/html/html_unescape.gperf" + {"gel", 3, {226, 139, 155}}, +#line 687 "src/html/html_unescape.gperf" + {"hercon", 3, {226, 138, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1885 "src/html/html_unescape.gperf" + {"triminus", 3, {226, 168, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 480 "src/html/html_unescape.gperf" + {"egrave", 2, {195, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1655 "src/html/html_unescape.gperf" + {"sdot", 3, {226, 139, 133}}, +#line 1924 "src/html/html_unescape.gperf" + {"ugrave", 2, {195, 185}}, + {(char*)0}, +#line 2115 "src/html/html_unescape.gperf" + {"Zdot", 2, {197, 187}}, +#line 472 "src/html/html_unescape.gperf" + {"edot", 2, {196, 151}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1229 "src/html/html_unescape.gperf" + {"NotTildeTilde", 3, {226, 137, 137}}, + {(char*)0}, +#line 1835 "src/html/html_unescape.gperf" + {"tdot", 3, {226, 131, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1467 "src/html/html_unescape.gperf" + {"Pscr", 4, {240, 157, 146, 171}}, +#line 1408 "src/html/html_unescape.gperf" + {"Pi", 2, {206, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 648 "src/html/html_unescape.gperf" + {"Gscr", 4, {240, 157, 146, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1425 "src/html/html_unescape.gperf" + {"plustwo", 3, {226, 168, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1173 "src/html/html_unescape.gperf" + {"NotElement", 3, {226, 136, 137}}, + {(char*)0}, +#line 1422 "src/html/html_unescape.gperf" + {"PlusMinus", 2, {194, 177}}, + {(char*)0}, {(char*)0}, +#line 697 "src/html/html_unescape.gperf" + {"hopf", 4, {240, 157, 149, 153}}, +#line 594 "src/html/html_unescape.gperf" + {"gammad", 2, {207, 157}}, + {(char*)0}, +#line 1044 "src/html/html_unescape.gperf" + {"mDDot", 3, {226, 136, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 389 "src/html/html_unescape.gperf" + {"divideontimes", 3, {226, 139, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 401 "src/html/html_unescape.gperf" + {"doteq", 3, {226, 137, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1986 "src/html/html_unescape.gperf" + {"varepsilon", 2, {207, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1439 "src/html/html_unescape.gperf" + {"Precedes", 3, {226, 137, 186}}, + {(char*)0}, {(char*)0}, +#line 593 "src/html/html_unescape.gperf" + {"Gammad", 2, {207, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 349 "src/html/html_unescape.gperf" + {"dashv", 3, {226, 138, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1170 "src/html/html_unescape.gperf" + {"NotCongruent", 3, {226, 137, 162}}, + {(char*)0}, {(char*)0}, +#line 1911 "src/html/html_unescape.gperf" + {"ubreve", 2, {197, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1333 "src/html/html_unescape.gperf" + {"ogt", 3, {226, 167, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1609 "src/html/html_unescape.gperf" + {"RoundImplies", 3, {226, 165, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1441 "src/html/html_unescape.gperf" + {"PrecedesSlantEqual", 3, {226, 137, 188}}, + {(char*)0}, {(char*)0}, +#line 1688 "src/html/html_unescape.gperf" + {"sime", 3, {226, 137, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1923 "src/html/html_unescape.gperf" + {"Ugrave", 2, {195, 153}}, + {(char*)0}, +#line 350 "src/html/html_unescape.gperf" + {"dbkarow", 3, {226, 164, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1656 "src/html/html_unescape.gperf" + {"sdote", 3, {226, 169, 166}}, + {(char*)0}, +#line 2016 "src/html/html_unescape.gperf" + {"veeeq", 3, {226, 137, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1035 "src/html/html_unescape.gperf" + {"mapsto", 3, {226, 134, 166}}, + {(char*)0}, {(char*)0}, +#line 1862 "src/html/html_unescape.gperf" + {"times", 2, {195, 151}}, + {(char*)0}, {(char*)0}, +#line 1496 "src/html/html_unescape.gperf" + {"rangle", 3, {226, 159, 169}}, + {(char*)0}, +#line 828 "src/html/html_unescape.gperf" + {"langle", 3, {226, 159, 168}}, + {(char*)0}, {(char*)0}, +#line 878 "src/html/html_unescape.gperf" + {"leftarrowtail", 3, {226, 134, 162}}, +#line 673 "src/html/html_unescape.gperf" + {"hamilt", 3, {226, 132, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1919 "src/html/html_unescape.gperf" + {"udhar", 3, {226, 165, 174}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1138 "src/html/html_unescape.gperf" + {"nisd", 3, {226, 139, 186}}, + {(char*)0}, +#line 1550 "src/html/html_unescape.gperf" + {"rfisht", 3, {226, 165, 189}}, + {(char*)0}, +#line 932 "src/html/html_unescape.gperf" + {"lfisht", 3, {226, 165, 188}}, +#line 676 "src/html/html_unescape.gperf" + {"harrcir", 3, {226, 165, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1354 "src/html/html_unescape.gperf" + {"OpenCurlyQuote", 3, {226, 128, 152}}, + {(char*)0}, +#line 1920 "src/html/html_unescape.gperf" + {"ufisht", 3, {226, 165, 190}}, +#line 1184 "src/html/html_unescape.gperf" + {"NotHumpDownHump", 3, {226, 137, 142}}, + {(char*)0}, {(char*)0}, +#line 896 "src/html/html_unescape.gperf" + {"LeftTee", 3, {226, 138, 163}}, + {(char*)0}, +#line 1618 "src/html/html_unescape.gperf" + {"rsh", 3, {226, 134, 177}}, + {(char*)0}, +#line 1001 "src/html/html_unescape.gperf" + {"lsh", 3, {226, 134, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 668 "src/html/html_unescape.gperf" + {"gvertneqq", 3, {226, 137, 169}}, + {(char*)0}, {(char*)0}, +#line 1861 "src/html/html_unescape.gperf" + {"timesb", 3, {226, 138, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1650 "src/html/html_unescape.gperf" + {"scpolint", 3, {226, 168, 147}}, + {(char*)0}, {(char*)0}, +#line 237 "src/html/html_unescape.gperf" + {"Cdot", 2, {196, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 455 "src/html/html_unescape.gperf" + {"dwangle", 3, {226, 166, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1910 "src/html/html_unescape.gperf" + {"Ubreve", 2, {197, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 905 "src/html/html_unescape.gperf" + {"LeftUpVector", 3, {226, 134, 191}}, + {(char*)0}, {(char*)0}, +#line 904 "src/html/html_unescape.gperf" + {"LeftUpVectorBar", 3, {226, 165, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 462 "src/html/html_unescape.gperf" + {"Ecaron", 2, {196, 154}}, + {(char*)0}, {(char*)0}, +#line 694 "src/html/html_unescape.gperf" + {"homtht", 3, {226, 136, 187}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 725 "src/html/html_unescape.gperf" + {"igrave", 2, {195, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1239 "src/html/html_unescape.gperf" + {"npreceq", 3, {226, 170, 175}}, +#line 467 "src/html/html_unescape.gperf" + {"ecolon", 3, {226, 137, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 359 "src/html/html_unescape.gperf" + {"dd", 3, {226, 133, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1689 "src/html/html_unescape.gperf" + {"simeq", 3, {226, 137, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1188 "src/html/html_unescape.gperf" + {"notinE", 3, {226, 139, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 120 "src/html/html_unescape.gperf" + {"bigoplus", 3, {226, 168, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 22 "src/html/html_unescape.gperf" + {"Afr", 4, {240, 157, 148, 132}}, +#line 874 "src/html/html_unescape.gperf" + {"leftarrow", 3, {226, 134, 144}}, +#line 1336 "src/html/html_unescape.gperf" + {"oint", 3, {226, 136, 174}}, + {(char*)0}, +#line 1824 "src/html/html_unescape.gperf" + {"Tab", 1, {9}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1330 "src/html/html_unescape.gperf" + {"ogon", 2, {203, 155}}, + {(char*)0}, {(char*)0}, +#line 1013 "src/html/html_unescape.gperf" + {"lt", 1, {60}}, +#line 1150 "src/html/html_unescape.gperf" + {"nLeftrightarrow", 3, {226, 135, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1499 "src/html/html_unescape.gperf" + {"rarrb", 3, {226, 135, 165}}, + {(char*)0}, +#line 832 "src/html/html_unescape.gperf" + {"larrb", 3, {226, 135, 164}}, + {(char*)0}, +#line 701 "src/html/html_unescape.gperf" + {"hscr", 4, {240, 157, 146, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 902 "src/html/html_unescape.gperf" + {"LeftUpDownVector", 3, {226, 165, 145}}, + {(char*)0}, +#line 808 "src/html/html_unescape.gperf" + {"kfr", 4, {240, 157, 148, 168}}, +#line 620 "src/html/html_unescape.gperf" + {"gfr", 4, {240, 157, 148, 164}}, +#line 1946 "src/html/html_unescape.gperf" + {"UpArrowBar", 3, {226, 164, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1251 "src/html/html_unescape.gperf" + {"nsce", 3, {226, 170, 176}}, +#line 1016 "src/html/html_unescape.gperf" + {"ltdot", 3, {226, 139, 150}}, +#line 617 "src/html/html_unescape.gperf" + {"gesl", 3, {226, 139, 155}}, +#line 2074 "src/html/html_unescape.gperf" + {"xodot", 3, {226, 168, 128}}, +#line 1748 "src/html/html_unescape.gperf" + {"star", 3, {226, 152, 134}}, + {(char*)0}, {(char*)0}, +#line 984 "src/html/html_unescape.gperf" + {"lowbar", 1, {95}}, + {(char*)0}, +#line 2066 "src/html/html_unescape.gperf" + {"xharr", 3, {226, 159, 183}}, +#line 466 "src/html/html_unescape.gperf" + {"ecir", 3, {226, 137, 150}}, + {(char*)0}, +#line 1976 "src/html/html_unescape.gperf" + {"utdot", 3, {226, 139, 176}}, +#line 1086 "src/html/html_unescape.gperf" + {"natur", 3, {226, 153, 174}}, +#line 1002 "src/html/html_unescape.gperf" + {"Lsh", 3, {226, 134, 176}}, +#line 746 "src/html/html_unescape.gperf" + {"infin", 3, {226, 136, 158}}, + {(char*)0}, +#line 284 "src/html/html_unescape.gperf" + {"comp", 3, {226, 136, 129}}, + {(char*)0}, +#line 1685 "src/html/html_unescape.gperf" + {"sigmav", 2, {207, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 2078 "src/html/html_unescape.gperf" + {"xotime", 3, {226, 168, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1401 "src/html/html_unescape.gperf" + {"Pfr", 4, {240, 157, 148, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 619 "src/html/html_unescape.gperf" + {"Gfr", 4, {240, 157, 148, 138}}, + {(char*)0}, {(char*)0}, +#line 116 "src/html/html_unescape.gperf" + {"bigcap", 3, {226, 139, 130}}, + {(char*)0}, +#line 1693 "src/html/html_unescape.gperf" + {"simlE", 3, {226, 170, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 727 "src/html/html_unescape.gperf" + {"iiiint", 3, {226, 168, 140}}, +#line 96 "src/html/html_unescape.gperf" + {"barwedge", 3, {226, 140, 133}}, +#line 95 "src/html/html_unescape.gperf" + {"Barwed", 3, {226, 140, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2070 "src/html/html_unescape.gperf" + {"xlarr", 3, {226, 159, 181}}, +#line 924 "src/html/html_unescape.gperf" + {"LessEqualGreater", 3, {226, 139, 154}}, + {(char*)0}, +#line 302 "src/html/html_unescape.gperf" + {"crarr", 3, {226, 134, 181}}, +#line 773 "src/html/html_unescape.gperf" + {"isindot", 3, {226, 139, 181}}, + {(char*)0}, +#line 283 "src/html/html_unescape.gperf" + {"commat", 1, {64}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1055 "src/html/html_unescape.gperf" + {"middot", 2, {194, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 917 "src/html/html_unescape.gperf" + {"lesdotor", 3, {226, 170, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1684 "src/html/html_unescape.gperf" + {"sigmaf", 2, {207, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1500 "src/html/html_unescape.gperf" + {"rarrbfs", 3, {226, 164, 160}}, + {(char*)0}, +#line 833 "src/html/html_unescape.gperf" + {"larrbfs", 3, {226, 164, 159}}, + {(char*)0}, {(char*)0}, +#line 2079 "src/html/html_unescape.gperf" + {"xrarr", 3, {226, 159, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 118 "src/html/html_unescape.gperf" + {"bigcup", 3, {226, 139, 131}}, + {(char*)0}, +#line 275 "src/html/html_unescape.gperf" + {"clubs", 3, {226, 153, 163}}, +#line 678 "src/html/html_unescape.gperf" + {"hArr", 3, {226, 135, 148}}, +#line 1626 "src/html/html_unescape.gperf" + {"rtrie", 3, {226, 138, 181}}, + {(char*)0}, +#line 1022 "src/html/html_unescape.gperf" + {"ltrie", 3, {226, 138, 180}}, +#line 742 "src/html/html_unescape.gperf" + {"imped", 2, {198, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 503 "src/html/html_unescape.gperf" + {"eogon", 2, {196, 153}}, +#line 1631 "src/html/html_unescape.gperf" + {"rx", 3, {226, 132, 158}}, +#line 1024 "src/html/html_unescape.gperf" + {"ltrPar", 3, {226, 166, 150}}, +#line 1747 "src/html/html_unescape.gperf" + {"Star", 3, {226, 139, 134}}, + {(char*)0}, +#line 1943 "src/html/html_unescape.gperf" + {"uogon", 2, {197, 179}}, + {(char*)0}, {(char*)0}, +#line 1856 "src/html/html_unescape.gperf" + {"Tilde", 3, {226, 136, 188}}, + {(char*)0}, +#line 672 "src/html/html_unescape.gperf" + {"half", 2, {194, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1855 "src/html/html_unescape.gperf" + {"tilde", 2, {203, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 876 "src/html/html_unescape.gperf" + {"Leftarrow", 3, {226, 135, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 618 "src/html/html_unescape.gperf" + {"gesles", 3, {226, 170, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 218 "src/html/html_unescape.gperf" + {"cap", 3, {226, 136, 169}}, +#line 1752 "src/html/html_unescape.gperf" + {"strns", 2, {194, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1015 "src/html/html_unescape.gperf" + {"Lt", 3, {226, 137, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1454 "src/html/html_unescape.gperf" + {"prnE", 3, {226, 170, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1727 "src/html/html_unescape.gperf" + {"sqsupe", 3, {226, 138, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1728 "src/html/html_unescape.gperf" + {"sqsupset", 3, {226, 138, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1883 "src/html/html_unescape.gperf" + {"tridot", 3, {226, 151, 172}}, +#line 1361 "src/html/html_unescape.gperf" + {"order", 3, {226, 132, 180}}, + {(char*)0}, {(char*)0}, +#line 223 "src/html/html_unescape.gperf" + {"caps", 3, {226, 136, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 303 "src/html/html_unescape.gperf" + {"cross", 3, {226, 156, 151}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 367 "src/html/html_unescape.gperf" + {"dfisht", 3, {226, 165, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2072 "src/html/html_unescape.gperf" + {"xmap", 3, {226, 159, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1726 "src/html/html_unescape.gperf" + {"sqsup", 3, {226, 138, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1625 "src/html/html_unescape.gperf" + {"rtri", 3, {226, 150, 185}}, + {(char*)0}, +#line 1021 "src/html/html_unescape.gperf" + {"ltri", 3, {226, 151, 131}}, +#line 778 "src/html/html_unescape.gperf" + {"it", 3, {226, 129, 162}}, +#line 1599 "src/html/html_unescape.gperf" + {"rmoust", 3, {226, 142, 177}}, + {(char*)0}, +#line 955 "src/html/html_unescape.gperf" + {"lmoust", 3, {226, 142, 176}}, +#line 634 "src/html/html_unescape.gperf" + {"gnE", 3, {226, 137, 169}}, +#line 937 "src/html/html_unescape.gperf" + {"lgE", 3, {226, 170, 145}}, + {(char*)0}, {(char*)0}, +#line 1642 "src/html/html_unescape.gperf" + {"scE", 3, {226, 170, 180}}, + {(char*)0}, +#line 1979 "src/html/html_unescape.gperf" + {"utri", 3, {226, 150, 181}}, + {(char*)0}, +#line 2017 "src/html/html_unescape.gperf" + {"vellip", 3, {226, 139, 174}}, + {(char*)0}, +#line 535 "src/html/html_unescape.gperf" + {"ETH", 2, {195, 144}}, + {(char*)0}, {(char*)0}, +#line 953 "src/html/html_unescape.gperf" + {"lmidot", 2, {197, 128}}, + {(char*)0}, +#line 1942 "src/html/html_unescape.gperf" + {"Uogon", 2, {197, 178}}, +#line 301 "src/html/html_unescape.gperf" + {"CounterClockwiseContourIntegral", 3, {226, 136, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1121 "src/html/html_unescape.gperf" + {"ngE", 3, {226, 137, 167}}, +#line 1310 "src/html/html_unescape.gperf" + {"nwnear", 3, {226, 164, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 918 "src/html/html_unescape.gperf" + {"lesg", 3, {226, 139, 154}}, + {(char*)0}, {(char*)0}, +#line 1416 "src/html/html_unescape.gperf" + {"plusb", 3, {226, 138, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1619 "src/html/html_unescape.gperf" + {"Rsh", 3, {226, 134, 177}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 300 "src/html/html_unescape.gperf" + {"copysr", 3, {226, 132, 151}}, + {(char*)0}, +#line 747 "src/html/html_unescape.gperf" + {"infintie", 3, {226, 167, 157}}, + {(char*)0}, +#line 739 "src/html/html_unescape.gperf" + {"imath", 2, {196, 177}}, +#line 531 "src/html/html_unescape.gperf" + {"Esim", 3, {226, 169, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1403 "src/html/html_unescape.gperf" + {"Phi", 2, {206, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 629 "src/html/html_unescape.gperf" + {"glE", 3, {226, 170, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 2031 "src/html/html_unescape.gperf" + {"vnsup", 3, {226, 138, 131}}, + {(char*)0}, {(char*)0}, +#line 1691 "src/html/html_unescape.gperf" + {"simgE", 3, {226, 170, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 414 "src/html/html_unescape.gperf" + {"DoubleLongLeftArrow", 3, {226, 159, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 415 "src/html/html_unescape.gperf" + {"DoubleLongLeftRightArrow", 3, {226, 159, 186}}, + {(char*)0}, {(char*)0}, +#line 1296 "src/html/html_unescape.gperf" + {"nvgt", 1, {62}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1047 "src/html/html_unescape.gperf" + {"Mellintrf", 3, {226, 132, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1451 "src/html/html_unescape.gperf" + {"Prime", 3, {226, 128, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 729 "src/html/html_unescape.gperf" + {"iinfin", 3, {226, 167, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1547 "src/html/html_unescape.gperf" + {"ReverseElement", 3, {226, 136, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 493 "src/html/html_unescape.gperf" + {"EmptySmallSquare", 3, {226, 151, 187}}, +#line 1490 "src/html/html_unescape.gperf" + {"radic", 3, {226, 136, 154}}, + {(char*)0}, {(char*)0}, +#line 688 "src/html/html_unescape.gperf" + {"hfr", 4, {240, 157, 148, 165}}, +#line 2116 "src/html/html_unescape.gperf" + {"zdot", 2, {197, 188}}, +#line 1030 "src/html/html_unescape.gperf" + {"male", 3, {226, 153, 130}}, + {(char*)0}, +#line 1501 "src/html/html_unescape.gperf" + {"rarrc", 3, {226, 164, 179}}, +#line 1437 "src/html/html_unescape.gperf" + {"prec", 3, {226, 137, 186}}, +#line 1647 "src/html/html_unescape.gperf" + {"scnap", 3, {226, 170, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 384 "src/html/html_unescape.gperf" + {"DifferentialD", 3, {226, 133, 134}}, + {(char*)0}, +#line 1064 "src/html/html_unescape.gperf" + {"models", 3, {226, 138, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1012 "src/html/html_unescape.gperf" + {"ltcir", 3, {226, 169, 185}}, +#line 763 "src/html/html_unescape.gperf" + {"iogon", 2, {196, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 217 "src/html/html_unescape.gperf" + {"capcap", 3, {226, 169, 139}}, + {(char*)0}, +#line 721 "src/html/html_unescape.gperf" + {"iff", 3, {226, 135, 148}}, + {(char*)0}, +#line 361 "src/html/html_unescape.gperf" + {"ddotseq", 3, {226, 169, 183}}, + {(char*)0}, +#line 264 "src/html/html_unescape.gperf" + {"CirclePlus", 3, {226, 138, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1623 "src/html/html_unescape.gperf" + {"rthree", 3, {226, 139, 140}}, + {(char*)0}, +#line 1017 "src/html/html_unescape.gperf" + {"lthree", 3, {226, 139, 139}}, + {(char*)0}, {(char*)0}, +#line 1442 "src/html/html_unescape.gperf" + {"PrecedesTilde", 3, {226, 137, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 450 "src/html/html_unescape.gperf" + {"dtdot", 3, {226, 139, 177}}, + {(char*)0}, +#line 276 "src/html/html_unescape.gperf" + {"clubsuit", 3, {226, 153, 163}}, + {(char*)0}, +#line 1489 "src/html/html_unescape.gperf" + {"racute", 2, {197, 149}}, + {(char*)0}, +#line 820 "src/html/html_unescape.gperf" + {"lacute", 2, {196, 186}}, +#line 1890 "src/html/html_unescape.gperf" + {"trpezium", 3, {226, 143, 162}}, +#line 1633 "src/html/html_unescape.gperf" + {"sacute", 2, {197, 155}}, + {(char*)0}, {(char*)0}, +#line 2109 "src/html/html_unescape.gperf" + {"Zacute", 2, {197, 185}}, +#line 460 "src/html/html_unescape.gperf" + {"eacute", 2, {195, 169}}, + {(char*)0}, +#line 1859 "src/html/html_unescape.gperf" + {"TildeTilde", 3, {226, 137, 136}}, + {(char*)0}, +#line 1907 "src/html/html_unescape.gperf" + {"Uarrocir", 3, {226, 165, 137}}, +#line 1903 "src/html/html_unescape.gperf" + {"uacute", 2, {195, 186}}, +#line 983 "src/html/html_unescape.gperf" + {"lowast", 3, {226, 136, 151}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1077 "src/html/html_unescape.gperf" + {"nacute", 2, {197, 132}}, + {(char*)0}, +#line 1207 "src/html/html_unescape.gperf" + {"NotPrecedes", 3, {226, 138, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 952 "src/html/html_unescape.gperf" + {"Lmidot", 2, {196, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1948 "src/html/html_unescape.gperf" + {"UpArrow", 3, {226, 134, 145}}, + {(char*)0}, +#line 1512 "src/html/html_unescape.gperf" + {"rarrw", 3, {226, 134, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 439 "src/html/html_unescape.gperf" + {"DownTee", 3, {226, 138, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 556 "src/html/html_unescape.gperf" + {"FilledSmallSquare", 3, {226, 151, 188}}, +#line 220 "src/html/html_unescape.gperf" + {"capcup", 3, {226, 169, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 643 "src/html/html_unescape.gperf" + {"GreaterFullEqual", 3, {226, 137, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1300 "src/html/html_unescape.gperf" + {"nvle", 3, {226, 137, 164}}, + {(char*)0}, +#line 1884 "src/html/html_unescape.gperf" + {"trie", 3, {226, 137, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1347 "src/html/html_unescape.gperf" + {"omicron", 2, {206, 191}}, + {(char*)0}, +#line 418 "src/html/html_unescape.gperf" + {"DoubleRightTee", 3, {226, 138, 168}}, +#line 234 "src/html/html_unescape.gperf" + {"Cconint", 3, {226, 136, 176}}, +#line 1622 "src/html/html_unescape.gperf" + {"rsquor", 3, {226, 128, 153}}, + {(char*)0}, +#line 1008 "src/html/html_unescape.gperf" + {"lsquor", 3, {226, 128, 154}}, + {(char*)0}, +#line 2125 "src/html/html_unescape.gperf" + {"zigrarr", 3, {226, 135, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 294 "src/html/html_unescape.gperf" + {"copf", 4, {240, 157, 149, 148}}, + {(char*)0}, +#line 293 "src/html/html_unescape.gperf" + {"ContourIntegral", 3, {226, 136, 174}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 671 "src/html/html_unescape.gperf" + {"hairsp", 3, {226, 128, 138}}, +#line 1729 "src/html/html_unescape.gperf" + {"sqsupseteq", 3, {226, 138, 146}}, +#line 307 "src/html/html_unescape.gperf" + {"csub", 3, {226, 171, 143}}, +#line 1956 "src/html/html_unescape.gperf" + {"upharpoonright", 3, {226, 134, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 427 "src/html/html_unescape.gperf" + {"DownBreve", 2, {204, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1675 "src/html/html_unescape.gperf" + {"ShortDownArrow", 3, {226, 134, 147}}, + {(char*)0}, +#line 2076 "src/html/html_unescape.gperf" + {"xopf", 4, {240, 157, 149, 169}}, + {(char*)0}, +#line 1632 "src/html/html_unescape.gperf" + {"Sacute", 2, {197, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2040 "src/html/html_unescape.gperf" + {"vsupnE", 3, {226, 171, 140}}, +#line 266 "src/html/html_unescape.gperf" + {"cir", 3, {226, 151, 139}}, +#line 1415 "src/html/html_unescape.gperf" + {"plusacir", 3, {226, 168, 163}}, +#line 309 "src/html/html_unescape.gperf" + {"csup", 3, {226, 171, 144}}, +#line 2038 "src/html/html_unescape.gperf" + {"vsubnE", 3, {226, 171, 139}}, +#line 1902 "src/html/html_unescape.gperf" + {"Uacute", 2, {195, 154}}, + {(char*)0}, +#line 774 "src/html/html_unescape.gperf" + {"isinE", 3, {226, 139, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 607 "src/html/html_unescape.gperf" + {"gEl", 3, {226, 170, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1720 "src/html/html_unescape.gperf" + {"sqcups", 3, {226, 138, 148}}, + {(char*)0}, +#line 1702 "src/html/html_unescape.gperf" + {"smid", 3, {226, 136, 163}}, + {(char*)0}, +#line 936 "src/html/html_unescape.gperf" + {"lg", 3, {226, 137, 182}}, + {(char*)0}, +#line 416 "src/html/html_unescape.gperf" + {"DoubleLongRightArrow", 3, {226, 159, 185}}, +#line 1209 "src/html/html_unescape.gperf" + {"NotPrecedesSlantEqual", 3, {226, 139, 160}}, + {(char*)0}, {(char*)0}, +#line 478 "src/html/html_unescape.gperf" + {"eg", 3, {226, 170, 154}}, + {(char*)0}, {(char*)0}, +#line 34 "src/html/html_unescape.gperf" + {"AMP", 1, {38}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1163 "src/html/html_unescape.gperf" + {"nmid", 3, {226, 136, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1863 "src/html/html_unescape.gperf" + {"timesd", 3, {226, 168, 176}}, + {(char*)0}, {(char*)0}, +#line 434 "src/html/html_unescape.gperf" + {"DownLeftVector", 3, {226, 134, 189}}, +#line 2131 "src/html/html_unescape.gperf" + {"zwnj", 3, {226, 128, 140}}, +#line 819 "src/html/html_unescape.gperf" + {"Lacute", 2, {196, 185}}, +#line 433 "src/html/html_unescape.gperf" + {"DownLeftVectorBar", 3, {226, 165, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1332 "src/html/html_unescape.gperf" + {"ograve", 2, {195, 178}}, +#line 2088 "src/html/html_unescape.gperf" + {"Yacute", 2, {195, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1719 "src/html/html_unescape.gperf" + {"sqcup", 3, {226, 138, 148}}, + {(char*)0}, {(char*)0}, +#line 1323 "src/html/html_unescape.gperf" + {"odot", 3, {226, 138, 153}}, +#line 213 "src/html/html_unescape.gperf" + {"Cacute", 2, {196, 134}}, + {(char*)0}, +#line 1286 "src/html/html_unescape.gperf" + {"nu", 2, {206, 189}}, +#line 1889 "src/html/html_unescape.gperf" + {"tritime", 3, {226, 168, 187}}, + {(char*)0}, +#line 479 "src/html/html_unescape.gperf" + {"Egrave", 2, {195, 136}}, +#line 508 "src/html/html_unescape.gperf" + {"eplus", 3, {226, 169, 177}}, + {(char*)0}, +#line 86 "src/html/html_unescape.gperf" + {"backcong", 3, {226, 137, 140}}, + {(char*)0}, {(char*)0}, +#line 1957 "src/html/html_unescape.gperf" + {"uplus", 3, {226, 138, 142}}, + {(char*)0}, +#line 471 "src/html/html_unescape.gperf" + {"Edot", 2, {196, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 310 "src/html/html_unescape.gperf" + {"csupe", 3, {226, 171, 146}}, + {(char*)0}, +#line 1690 "src/html/html_unescape.gperf" + {"simg", 3, {226, 170, 158}}, +#line 1959 "src/html/html_unescape.gperf" + {"UpperRightArrow", 3, {226, 134, 151}}, +#line 308 "src/html/html_unescape.gperf" + {"csube", 3, {226, 171, 145}}, + {(char*)0}, +#line 451 "src/html/html_unescape.gperf" + {"dtri", 3, {226, 150, 191}}, +#line 1455 "src/html/html_unescape.gperf" + {"prnsim", 3, {226, 139, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 178 "src/html/html_unescape.gperf" + {"boxUr", 3, {226, 149, 153}}, +#line 1981 "src/html/html_unescape.gperf" + {"uuarr", 3, {226, 135, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 432 "src/html/html_unescape.gperf" + {"DownLeftTeeVector", 3, {226, 165, 158}}, +#line 651 "src/html/html_unescape.gperf" + {"gsime", 3, {226, 170, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 121 "src/html/html_unescape.gperf" + {"bigotimes", 3, {226, 168, 130}}, +#line 342 "src/html/html_unescape.gperf" + {"Dagger", 3, {226, 128, 161}}, + {(char*)0}, {(char*)0}, +#line 755 "src/html/html_unescape.gperf" + {"Intersection", 3, {226, 139, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 711 "src/html/html_unescape.gperf" + {"iacute", 2, {195, 173}}, + {(char*)0}, +#line 1435 "src/html/html_unescape.gperf" + {"prcue", 3, {226, 137, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 482 "src/html/html_unescape.gperf" + {"egsdot", 3, {226, 170, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 743 "src/html/html_unescape.gperf" + {"Implies", 3, {226, 135, 146}}, +#line 2011 "src/html/html_unescape.gperf" + {"VDash", 3, {226, 138, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 208 "src/html/html_unescape.gperf" + {"bump", 3, {226, 137, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1071 "src/html/html_unescape.gperf" + {"Mu", 2, {206, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 2009 "src/html/html_unescape.gperf" + {"vDash", 3, {226, 138, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1028 "src/html/html_unescape.gperf" + {"lvnE", 3, {226, 137, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 895 "src/html/html_unescape.gperf" + {"LeftTeeArrow", 3, {226, 134, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1076 "src/html/html_unescape.gperf" + {"Nacute", 2, {197, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1937 "src/html/html_unescape.gperf" + {"UnderBrace", 3, {226, 143, 159}}, +#line 1469 "src/html/html_unescape.gperf" + {"Psi", 2, {206, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1560 "src/html/html_unescape.gperf" + {"rhov", 2, {207, 177}}, + {(char*)0}, +#line 913 "src/html/html_unescape.gperf" + {"lescc", 3, {226, 170, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1790 "src/html/html_unescape.gperf" + {"sup1", 2, {194, 185}}, + {(char*)0}, {(char*)0}, +#line 1791 "src/html/html_unescape.gperf" + {"sup2", 2, {194, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1792 "src/html/html_unescape.gperf" + {"sup3", 2, {194, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 119 "src/html/html_unescape.gperf" + {"bigodot", 3, {226, 168, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 425 "src/html/html_unescape.gperf" + {"Downarrow", 3, {226, 135, 147}}, + {(char*)0}, +#line 2083 "src/html/html_unescape.gperf" + {"xsqcup", 3, {226, 168, 134}}, + {(char*)0}, +#line 93 "src/html/html_unescape.gperf" + {"barvee", 3, {226, 138, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1107 "src/html/html_unescape.gperf" + {"NegativeMediumSpace", 3, {226, 128, 139}}, +#line 210 "src/html/html_unescape.gperf" + {"bumpe", 3, {226, 137, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 306 "src/html/html_unescape.gperf" + {"cscr", 4, {240, 157, 146, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1249 "src/html/html_unescape.gperf" + {"nsc", 3, {226, 138, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1793 "src/html/html_unescape.gperf" + {"sup", 3, {226, 138, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 239 "src/html/html_unescape.gperf" + {"cedil", 2, {194, 184}}, + {(char*)0}, {(char*)0}, +#line 192 "src/html/html_unescape.gperf" + {"boxVr", 3, {226, 149, 159}}, + {(char*)0}, +#line 1365 "src/html/html_unescape.gperf" + {"origof", 3, {226, 138, 182}}, +#line 2130 "src/html/html_unescape.gperf" + {"zwj", 3, {226, 128, 141}}, +#line 724 "src/html/html_unescape.gperf" + {"Igrave", 2, {195, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 717 "src/html/html_unescape.gperf" + {"Idot", 2, {196, 176}}, + {(char*)0}, +#line 2082 "src/html/html_unescape.gperf" + {"xscr", 4, {240, 157, 147, 141}}, +#line 2069 "src/html/html_unescape.gperf" + {"xi", 2, {206, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1132 "src/html/html_unescape.gperf" + {"nGtv", 3, {226, 137, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 166 "src/html/html_unescape.gperf" + {"boxHu", 3, {226, 149, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1853 "src/html/html_unescape.gperf" + {"THORN", 2, {195, 158}}, + {(char*)0}, +#line 1488 "src/html/html_unescape.gperf" + {"Racute", 2, {197, 148}}, + {(char*)0}, +#line 1506 "src/html/html_unescape.gperf" + {"rarrhk", 3, {226, 134, 170}}, + {(char*)0}, +#line 838 "src/html/html_unescape.gperf" + {"larrhk", 3, {226, 134, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1628 "src/html/html_unescape.gperf" + {"rtriltri", 3, {226, 167, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 181 "src/html/html_unescape.gperf" + {"boxV", 3, {226, 149, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 341 "src/html/html_unescape.gperf" + {"dagger", 3, {226, 128, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1346 "src/html/html_unescape.gperf" + {"Omicron", 2, {206, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 421 "src/html/html_unescape.gperf" + {"DoubleVerticalBar", 3, {226, 136, 165}}, + {(char*)0}, {(char*)0}, +#line 1118 "src/html/html_unescape.gperf" + {"nexists", 3, {226, 136, 132}}, + {(char*)0}, {(char*)0}, +#line 1285 "src/html/html_unescape.gperf" + {"Nu", 2, {206, 157}}, +#line 1117 "src/html/html_unescape.gperf" + {"nexist", 3, {226, 136, 132}}, +#line 606 "src/html/html_unescape.gperf" + {"gE", 3, {226, 137, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 64 "src/html/html_unescape.gperf" + {"ap", 3, {226, 137, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1794 "src/html/html_unescape.gperf" + {"Sup", 3, {226, 139, 145}}, +#line 402 "src/html/html_unescape.gperf" + {"doteqdot", 3, {226, 137, 145}}, + {(char*)0}, {(char*)0}, +#line 500 "src/html/html_unescape.gperf" + {"eng", 2, {197, 139}}, + {(char*)0}, +#line 225 "src/html/html_unescape.gperf" + {"caron", 2, {203, 135}}, + {(char*)0}, +#line 168 "src/html/html_unescape.gperf" + {"boxHU", 3, {226, 149, 169}}, +#line 614 "src/html/html_unescape.gperf" + {"gesdot", 3, {226, 170, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1548 "src/html/html_unescape.gperf" + {"ReverseEquilibrium", 3, {226, 135, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 175 "src/html/html_unescape.gperf" + {"boxUL", 3, {226, 149, 157}}, + {(char*)0}, +#line 1805 "src/html/html_unescape.gperf" + {"supmult", 3, {226, 171, 130}}, + {(char*)0}, {(char*)0}, +#line 1410 "src/html/html_unescape.gperf" + {"pitchfork", 3, {226, 139, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1289 "src/html/html_unescape.gperf" + {"numsp", 3, {226, 128, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1492 "src/html/html_unescape.gperf" + {"rang", 3, {226, 159, 169}}, + {(char*)0}, +#line 825 "src/html/html_unescape.gperf" + {"lang", 3, {226, 159, 168}}, + {(char*)0}, {(char*)0}, +#line 1316 "src/html/html_unescape.gperf" + {"ocir", 3, {226, 138, 154}}, + {(char*)0}, +#line 1516 "src/html/html_unescape.gperf" + {"rationals", 3, {226, 132, 154}}, + {(char*)0}, +#line 296 "src/html/html_unescape.gperf" + {"coprod", 3, {226, 136, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1019 "src/html/html_unescape.gperf" + {"ltlarr", 3, {226, 165, 182}}, +#line 195 "src/html/html_unescape.gperf" + {"breve", 2, {203, 152}}, + {(char*)0}, +#line 1078 "src/html/html_unescape.gperf" + {"nang", 3, {226, 136, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1818 "src/html/html_unescape.gperf" + {"swarhk", 3, {226, 164, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1497 "src/html/html_unescape.gperf" + {"raquo", 2, {194, 187}}, + {(char*)0}, +#line 831 "src/html/html_unescape.gperf" + {"laquo", 2, {194, 171}}, +#line 1816 "src/html/html_unescape.gperf" + {"supsub", 3, {226, 171, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 322 "src/html/html_unescape.gperf" + {"Cup", 3, {226, 139, 147}}, +#line 66 "src/html/html_unescape.gperf" + {"ape", 3, {226, 137, 138}}, +#line 1482 "src/html/html_unescape.gperf" + {"quest", 1, {63}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1306 "src/html/html_unescape.gperf" + {"nwarhk", 3, {226, 164, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1809 "src/html/html_unescape.gperf" + {"supset", 3, {226, 138, 131}}, + {(char*)0}, +#line 423 "src/html/html_unescape.gperf" + {"downarrow", 3, {226, 134, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 453 "src/html/html_unescape.gperf" + {"duarr", 3, {226, 135, 181}}, + {(char*)0}, +#line 68 "src/html/html_unescape.gperf" + {"apos", 1, {39}}, +#line 1331 "src/html/html_unescape.gperf" + {"Ograve", 2, {195, 146}}, +#line 1678 "src/html/html_unescape.gperf" + {"shortparallel", 3, {226, 136, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1269 "src/html/html_unescape.gperf" + {"nsucc", 3, {226, 138, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 967 "src/html/html_unescape.gperf" + {"LongLeftArrow", 3, {226, 159, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 916 "src/html/html_unescape.gperf" + {"lesdoto", 3, {226, 170, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1807 "src/html/html_unescape.gperf" + {"supne", 3, {226, 138, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1127 "src/html/html_unescape.gperf" + {"nGg", 3, {226, 139, 153}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1491 "src/html/html_unescape.gperf" + {"raemptyv", 3, {226, 166, 179}}, +#line 1817 "src/html/html_unescape.gperf" + {"supsup", 3, {226, 171, 150}}, +#line 821 "src/html/html_unescape.gperf" + {"laemptyv", 3, {226, 166, 180}}, + {(char*)0}, {(char*)0}, +#line 1871 "src/html/html_unescape.gperf" + {"topfork", 3, {226, 171, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 502 "src/html/html_unescape.gperf" + {"Eogon", 2, {196, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1594 "src/html/html_unescape.gperf" + {"risingdotseq", 3, {226, 137, 147}}, + {(char*)0}, +#line 212 "src/html/html_unescape.gperf" + {"bumpeq", 3, {226, 137, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1010 "src/html/html_unescape.gperf" + {"lstrok", 2, {197, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1897 "src/html/html_unescape.gperf" + {"Tstrok", 2, {197, 166}}, +#line 650 "src/html/html_unescape.gperf" + {"gsim", 3, {226, 137, 179}}, + {(char*)0}, {(char*)0}, +#line 106 "src/html/html_unescape.gperf" + {"bemptyv", 3, {226, 166, 176}}, +#line 2110 "src/html/html_unescape.gperf" + {"zacute", 2, {197, 186}}, +#line 652 "src/html/html_unescape.gperf" + {"gsiml", 3, {226, 170, 144}}, + {(char*)0}, {(char*)0}, +#line 1898 "src/html/html_unescape.gperf" + {"tstrok", 2, {197, 167}}, + {(char*)0}, +#line 1601 "src/html/html_unescape.gperf" + {"roang", 3, {226, 159, 173}}, +#line 189 "src/html/html_unescape.gperf" + {"boxVL", 3, {226, 149, 163}}, +#line 963 "src/html/html_unescape.gperf" + {"loang", 3, {226, 159, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1153 "src/html/html_unescape.gperf" + {"nleqslant", 3, {226, 169, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1634 "src/html/html_unescape.gperf" + {"sbquo", 3, {226, 128, 154}}, + {(char*)0}, +#line 1657 "src/html/html_unescape.gperf" + {"searhk", 3, {226, 164, 165}}, +#line 957 "src/html/html_unescape.gperf" + {"lnapprox", 3, {226, 170, 137}}, + {(char*)0}, {(char*)0}, +#line 1810 "src/html/html_unescape.gperf" + {"Supset", 3, {226, 139, 145}}, + {(char*)0}, +#line 162 "src/html/html_unescape.gperf" + {"boxHd", 3, {226, 149, 164}}, +#line 1987 "src/html/html_unescape.gperf" + {"varkappa", 2, {207, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 254 "src/html/html_unescape.gperf" + {"circeq", 3, {226, 137, 151}}, + {(char*)0}, +#line 2102 "src/html/html_unescape.gperf" + {"yopf", 4, {240, 157, 149, 170}}, + {(char*)0}, +#line 1941 "src/html/html_unescape.gperf" + {"UnionPlus", 3, {226, 138, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 826 "src/html/html_unescape.gperf" + {"Lang", 3, {226, 159, 170}}, +#line 1101 "src/html/html_unescape.gperf" + {"nearhk", 3, {226, 164, 164}}, +#line 1674 "src/html/html_unescape.gperf" + {"shcy", 2, {209, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 245 "src/html/html_unescape.gperf" + {"cfr", 4, {240, 157, 148, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 800 "src/html/html_unescape.gperf" + {"Kappa", 2, {206, 154}}, +#line 944 "src/html/html_unescape.gperf" + {"ljcy", 2, {209, 153}}, +#line 1046 "src/html/html_unescape.gperf" + {"MediumSpace", 3, {226, 129, 159}}, + {(char*)0}, {(char*)0}, +#line 1811 "src/html/html_unescape.gperf" + {"supseteq", 3, {226, 138, 135}}, +#line 1812 "src/html/html_unescape.gperf" + {"supseteqq", 3, {226, 171, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1545 "src/html/html_unescape.gperf" + {"reg", 2, {194, 174}}, +#line 31 "src/html/html_unescape.gperf" + {"amacr", 2, {196, 129}}, +#line 909 "src/html/html_unescape.gperf" + {"leg", 3, {226, 139, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2050 "src/html/html_unescape.gperf" + {"weierp", 3, {226, 132, 152}}, +#line 1893 "src/html/html_unescape.gperf" + {"TScy", 2, {208, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1813 "src/html/html_unescape.gperf" + {"supsetneq", 3, {226, 138, 139}}, +#line 1141 "src/html/html_unescape.gperf" + {"njcy", 2, {209, 154}}, +#line 2065 "src/html/html_unescape.gperf" + {"xfr", 4, {240, 157, 148, 181}}, + {(char*)0}, +#line 1072 "src/html/html_unescape.gperf" + {"mu", 2, {206, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1298 "src/html/html_unescape.gperf" + {"nvinfin", 3, {226, 167, 158}}, +#line 179 "src/html/html_unescape.gperf" + {"boxUR", 3, {226, 149, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2077 "src/html/html_unescape.gperf" + {"xoplus", 3, {226, 168, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 887 "src/html/html_unescape.gperf" + {"leftleftarrows", 3, {226, 135, 135}}, +#line 1787 "src/html/html_unescape.gperf" + {"sum", 3, {226, 136, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 112 "src/html/html_unescape.gperf" + {"beth", 3, {226, 132, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 286 "src/html/html_unescape.gperf" + {"complement", 3, {226, 136, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1287 "src/html/html_unescape.gperf" + {"num", 1, {35}}, +#line 33 "src/html/html_unescape.gperf" + {"amp", 1, {38}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 174 "src/html/html_unescape.gperf" + {"boxUl", 3, {226, 149, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1177 "src/html/html_unescape.gperf" + {"NotGreater", 3, {226, 137, 175}}, +#line 170 "src/html/html_unescape.gperf" + {"boxplus", 3, {226, 138, 158}}, +#line 791 "src/html/html_unescape.gperf" + {"jmath", 2, {200, 183}}, + {(char*)0}, +#line 1669 "src/html/html_unescape.gperf" + {"sfrown", 3, {226, 140, 162}}, + {(char*)0}, +#line 448 "src/html/html_unescape.gperf" + {"Dstrok", 2, {196, 144}}, + {(char*)0}, +#line 37 "src/html/html_unescape.gperf" + {"and", 3, {226, 136, 167}}, +#line 1180 "src/html/html_unescape.gperf" + {"NotGreaterGreater", 3, {226, 137, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1182 "src/html/html_unescape.gperf" + {"NotGreaterSlantEqual", 3, {226, 169, 190}}, + {(char*)0}, +#line 1181 "src/html/html_unescape.gperf" + {"NotGreaterLess", 3, {226, 137, 185}}, +#line 1484 "src/html/html_unescape.gperf" + {"quot", 1, {34}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1179 "src/html/html_unescape.gperf" + {"NotGreaterFullEqual", 3, {226, 137, 167}}, +#line 709 "src/html/html_unescape.gperf" + {"hyphen", 3, {226, 128, 144}}, +#line 1412 "src/html/html_unescape.gperf" + {"planck", 3, {226, 132, 143}}, + {(char*)0}, +#line 1857 "src/html/html_unescape.gperf" + {"TildeEqual", 3, {226, 137, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1872 "src/html/html_unescape.gperf" + {"tosa", 3, {226, 164, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1009 "src/html/html_unescape.gperf" + {"Lstrok", 2, {197, 129}}, + {(char*)0}, {(char*)0}, +#line 1681 "src/html/html_unescape.gperf" + {"shy", 2, {194, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2073 "src/html/html_unescape.gperf" + {"xnis", 3, {226, 139, 187}}, +#line 762 "src/html/html_unescape.gperf" + {"Iogon", 2, {196, 174}}, + {(char*)0}, {(char*)0}, +#line 456 "src/html/html_unescape.gperf" + {"DZcy", 2, {208, 143}}, + {(char*)0}, +#line 1334 "src/html/html_unescape.gperf" + {"ohbar", 3, {226, 166, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 271 "src/html/html_unescape.gperf" + {"cirscir", 3, {226, 167, 130}}, + {(char*)0}, +#line 1666 "src/html/html_unescape.gperf" + {"sext", 3, {226, 156, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1387 "src/html/html_unescape.gperf" + {"para", 2, {194, 182}}, + {(char*)0}, {(char*)0}, +#line 77 "src/html/html_unescape.gperf" + {"ast", 1, {42}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1483 "src/html/html_unescape.gperf" + {"questeq", 3, {226, 137, 159}}, + {(char*)0}, +#line 1788 "src/html/html_unescape.gperf" + {"Sum", 3, {226, 136, 145}}, + {(char*)0}, +#line 445 "src/html/html_unescape.gperf" + {"DScy", 2, {208, 133}}, + {(char*)0}, +#line 499 "src/html/html_unescape.gperf" + {"ENG", 2, {197, 138}}, + {(char*)0}, +#line 2123 "src/html/html_unescape.gperf" + {"ZHcy", 2, {208, 150}}, + {(char*)0}, {(char*)0}, +#line 966 "src/html/html_unescape.gperf" + {"longleftarrow", 3, {226, 159, 181}}, + {(char*)0}, +#line 347 "src/html/html_unescape.gperf" + {"dash", 3, {226, 128, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 438 "src/html/html_unescape.gperf" + {"DownTeeArrow", 3, {226, 134, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1814 "src/html/html_unescape.gperf" + {"supsetneqq", 3, {226, 171, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1458 "src/html/html_unescape.gperf" + {"profalar", 3, {226, 140, 174}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1312 "src/html/html_unescape.gperf" + {"oacute", 2, {195, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 193 "src/html/html_unescape.gperf" + {"boxVR", 3, {226, 149, 160}}, + {(char*)0}, {(char*)0}, +#line 459 "src/html/html_unescape.gperf" + {"Eacute", 2, {195, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1808 "src/html/html_unescape.gperf" + {"supplus", 3, {226, 171, 128}}, + {(char*)0}, +#line 695 "src/html/html_unescape.gperf" + {"hookleftarrow", 3, {226, 134, 169}}, + {(char*)0}, {(char*)0}, +#line 274 "src/html/html_unescape.gperf" + {"CloseCurlyQuote", 3, {226, 128, 153}}, + {(char*)0}, {(char*)0}, +#line 1888 "src/html/html_unescape.gperf" + {"trisb", 3, {226, 167, 141}}, +#line 406 "src/html/html_unescape.gperf" + {"dotsquare", 3, {226, 138, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1624 "src/html/html_unescape.gperf" + {"rtimes", 3, {226, 139, 138}}, + {(char*)0}, +#line 1018 "src/html/html_unescape.gperf" + {"ltimes", 3, {226, 139, 137}}, + {(char*)0}, {(char*)0}, +#line 1865 "src/html/html_unescape.gperf" + {"toea", 3, {226, 164, 168}}, +#line 24 "src/html/html_unescape.gperf" + {"Agrave", 2, {195, 128}}, + {(char*)0}, {(char*)0}, +#line 76 "src/html/html_unescape.gperf" + {"Assign", 3, {226, 137, 148}}, +#line 1493 "src/html/html_unescape.gperf" + {"Rang", 3, {226, 159, 171}}, +#line 761 "src/html/html_unescape.gperf" + {"iocy", 2, {209, 145}}, + {(char*)0}, +#line 1208 "src/html/html_unescape.gperf" + {"NotPrecedesEqual", 3, {226, 170, 175}}, + {(char*)0}, +#line 62 "src/html/html_unescape.gperf" + {"aopf", 4, {240, 157, 149, 146}}, + {(char*)0}, +#line 252 "src/html/html_unescape.gperf" + {"chi", 2, {207, 135}}, + {(char*)0}, {(char*)0}, +#line 1480 "src/html/html_unescape.gperf" + {"quaternions", 3, {226, 132, 141}}, +#line 188 "src/html/html_unescape.gperf" + {"boxVl", 3, {226, 149, 162}}, +#line 1178 "src/html/html_unescape.gperf" + {"NotGreaterEqual", 3, {226, 137, 177}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2067 "src/html/html_unescape.gperf" + {"xhArr", 3, {226, 159, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1362 "src/html/html_unescape.gperf" + {"orderof", 3, {226, 132, 180}}, + {(char*)0}, {(char*)0}, +#line 1621 "src/html/html_unescape.gperf" + {"rsquo", 3, {226, 128, 153}}, + {(char*)0}, +#line 1007 "src/html/html_unescape.gperf" + {"lsquo", 3, {226, 128, 152}}, +#line 2104 "src/html/html_unescape.gperf" + {"yscr", 4, {240, 157, 147, 142}}, + {(char*)0}, {(char*)0}, +#line 604 "src/html/html_unescape.gperf" + {"gdot", 2, {196, 161}}, + {(char*)0}, +#line 1215 "src/html/html_unescape.gperf" + {"NotSquareSubsetEqual", 3, {226, 139, 162}}, +#line 810 "src/html/html_unescape.gperf" + {"KHcy", 2, {208, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 203 "src/html/html_unescape.gperf" + {"bsolb", 3, {226, 167, 133}}, +#line 1214 "src/html/html_unescape.gperf" + {"NotSquareSubset", 3, {226, 138, 143}}, +#line 1673 "src/html/html_unescape.gperf" + {"SHcy", 2, {208, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 2099 "src/html/html_unescape.gperf" + {"YIcy", 2, {208, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 339 "src/html/html_unescape.gperf" + {"cwint", 3, {226, 136, 177}}, + {(char*)0}, {(char*)0}, +#line 1842 "src/html/html_unescape.gperf" + {"Theta", 2, {206, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1843 "src/html/html_unescape.gperf" + {"theta", 2, {206, 184}}, +#line 2071 "src/html/html_unescape.gperf" + {"xlArr", 3, {226, 159, 184}}, + {(char*)0}, +#line 1217 "src/html/html_unescape.gperf" + {"NotSquareSupersetEqual", 3, {226, 139, 163}}, + {(char*)0}, {(char*)0}, +#line 366 "src/html/html_unescape.gperf" + {"demptyv", 3, {226, 166, 177}}, +#line 1876 "src/html/html_unescape.gperf" + {"triangle", 3, {226, 150, 181}}, + {(char*)0}, +#line 603 "src/html/html_unescape.gperf" + {"Gdot", 2, {196, 160}}, + {(char*)0}, +#line 1216 "src/html/html_unescape.gperf" + {"NotSquareSuperset", 3, {226, 138, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 9 "src/html/html_unescape.gperf" + {"Abreve", 2, {196, 130}}, + {(char*)0}, {(char*)0}, +#line 449 "src/html/html_unescape.gperf" + {"dstrok", 2, {196, 145}}, +#line 1400 "src/html/html_unescape.gperf" + {"pertenk", 3, {226, 128, 177}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1522 "src/html/html_unescape.gperf" + {"rbrack", 1, {93}}, + {(char*)0}, +#line 852 "src/html/html_unescape.gperf" + {"lbrack", 1, {91}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1324 "src/html/html_unescape.gperf" + {"odsold", 3, {226, 166, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1348 "src/html/html_unescape.gperf" + {"omid", 3, {226, 166, 182}}, + {(char*)0}, +#line 2080 "src/html/html_unescape.gperf" + {"xrArr", 3, {226, 159, 185}}, + {(char*)0}, +#line 1878 "src/html/html_unescape.gperf" + {"triangleleft", 3, {226, 151, 131}}, +#line 1183 "src/html/html_unescape.gperf" + {"NotGreaterTilde", 3, {226, 137, 181}}, +#line 280 "src/html/html_unescape.gperf" + {"colone", 3, {226, 137, 148}}, + {(char*)0}, +#line 968 "src/html/html_unescape.gperf" + {"Longleftarrow", 3, {226, 159, 184}}, + {(char*)0}, +#line 767 "src/html/html_unescape.gperf" + {"iota", 2, {206, 185}}, + {(char*)0}, +#line 277 "src/html/html_unescape.gperf" + {"colon", 1, {58}}, +#line 2119 "src/html/html_unescape.gperf" + {"Zeta", 2, {206, 150}}, +#line 597 "src/html/html_unescape.gperf" + {"gbreve", 2, {196, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 247 "src/html/html_unescape.gperf" + {"CHcy", 2, {208, 167}}, + {(char*)0}, {(char*)0}, +#line 2105 "src/html/html_unescape.gperf" + {"YUcy", 2, {208, 174}}, +#line 1546 "src/html/html_unescape.gperf" + {"REG", 2, {194, 174}}, +#line 1823 "src/html/html_unescape.gperf" + {"szlig", 2, {195, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 457 "src/html/html_unescape.gperf" + {"dzcy", 2, {209, 159}}, + {(char*)0}, +#line 111 "src/html/html_unescape.gperf" + {"beta", 2, {206, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 539 "src/html/html_unescape.gperf" + {"euro", 3, {226, 130, 172}}, + {(char*)0}, {(char*)0}, +#line 875 "src/html/html_unescape.gperf" + {"LeftArrow", 3, {226, 134, 144}}, + {(char*)0}, {(char*)0}, +#line 222 "src/html/html_unescape.gperf" + {"CapitalDifferentialD", 3, {226, 133, 133}}, + {(char*)0}, +#line 1593 "src/html/html_unescape.gperf" + {"ring", 2, {203, 154}}, +#line 830 "src/html/html_unescape.gperf" + {"Laplacetrf", 3, {226, 132, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 392 "src/html/html_unescape.gperf" + {"djcy", 2, {209, 146}}, + {(char*)0}, +#line 1356 "src/html/html_unescape.gperf" + {"oplus", 3, {226, 138, 149}}, + {(char*)0}, {(char*)0}, +#line 752 "src/html/html_unescape.gperf" + {"integers", 3, {226, 132, 164}}, +#line 596 "src/html/html_unescape.gperf" + {"Gbreve", 2, {196, 158}}, + {(char*)0}, +#line 1909 "src/html/html_unescape.gperf" + {"ubrcy", 2, {209, 158}}, +#line 538 "src/html/html_unescape.gperf" + {"euml", 2, {195, 171}}, + {(char*)0}, {(char*)0}, +#line 362 "src/html/html_unescape.gperf" + {"deg", 2, {194, 176}}, + {(char*)0}, +#line 1983 "src/html/html_unescape.gperf" + {"uuml", 2, {195, 188}}, + {(char*)0}, {(char*)0}, +#line 710 "src/html/html_unescape.gperf" + {"Iacute", 2, {195, 141}}, +#line 1781 "src/html/html_unescape.gperf" + {"succeq", 3, {226, 170, 176}}, + {(char*)0}, +#line 812 "src/html/html_unescape.gperf" + {"KJcy", 2, {208, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 320 "src/html/html_unescape.gperf" + {"CupCap", 3, {226, 137, 141}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1894 "src/html/html_unescape.gperf" + {"tscy", 2, {209, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 242 "src/html/html_unescape.gperf" + {"cent", 2, {194, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 391 "src/html/html_unescape.gperf" + {"DJcy", 2, {208, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1858 "src/html/html_unescape.gperf" + {"TildeFullEqual", 3, {226, 137, 133}}, + {(char*)0}, +#line 1880 "src/html/html_unescape.gperf" + {"triangleq", 3, {226, 137, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 454 "src/html/html_unescape.gperf" + {"duhar", 3, {226, 165, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 880 "src/html/html_unescape.gperf" + {"LeftDoubleBracket", 3, {226, 159, 166}}, + {(char*)0}, +#line 943 "src/html/html_unescape.gperf" + {"LJcy", 2, {208, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 719 "src/html/html_unescape.gperf" + {"iecy", 2, {208, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1879 "src/html/html_unescape.gperf" + {"trianglelefteq", 3, {226, 138, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1111 "src/html/html_unescape.gperf" + {"nequiv", 3, {226, 137, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1255 "src/html/html_unescape.gperf" + {"nshortparallel", 3, {226, 136, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1100 "src/html/html_unescape.gperf" + {"ndash", 3, {226, 128, 147}}, +#line 149 "src/html/html_unescape.gperf" + {"bowtie", 3, {226, 139, 136}}, + {(char*)0}, +#line 558 "src/html/html_unescape.gperf" + {"fjlig", 1, {102}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1908 "src/html/html_unescape.gperf" + {"Ubrcy", 2, {208, 142}}, + {(char*)0}, +#line 2000 "src/html/html_unescape.gperf" + {"vartheta", 2, {207, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1982 "src/html/html_unescape.gperf" + {"Uuml", 2, {195, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 2002 "src/html/html_unescape.gperf" + {"vartriangleright", 3, {226, 138, 179}}, +#line 2001 "src/html/html_unescape.gperf" + {"vartriangleleft", 3, {226, 138, 178}}, +#line 75 "src/html/html_unescape.gperf" + {"ascr", 4, {240, 157, 146, 182}}, + {(char*)0}, {(char*)0}, +#line 1776 "src/html/html_unescape.gperf" + {"succcurlyeq", 3, {226, 137, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 338 "src/html/html_unescape.gperf" + {"cwconint", 3, {226, 136, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1639 "src/html/html_unescape.gperf" + {"sc", 3, {226, 137, 187}}, + {(char*)0}, +#line 560 "src/html/html_unescape.gperf" + {"fllig", 3, {239, 172, 130}}, + {(char*)0}, +#line 257 "src/html/html_unescape.gperf" + {"circledast", 3, {226, 138, 155}}, + {(char*)0}, {(char*)0}, +#line 2010 "src/html/html_unescape.gperf" + {"Vdash", 3, {226, 138, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1293 "src/html/html_unescape.gperf" + {"nVdash", 3, {226, 138, 174}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1804 "src/html/html_unescape.gperf" + {"suplarr", 3, {226, 165, 187}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1603 "src/html/html_unescape.gperf" + {"robrk", 3, {226, 159, 167}}, + {(char*)0}, +#line 965 "src/html/html_unescape.gperf" + {"lobrk", 3, {226, 159, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2008 "src/html/html_unescape.gperf" + {"vdash", 3, {226, 138, 162}}, +#line 2108 "src/html/html_unescape.gperf" + {"Yuml", 2, {197, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 655 "src/html/html_unescape.gperf" + {"gt", 1, {62}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 227 "src/html/html_unescape.gperf" + {"ccaps", 3, {226, 169, 141}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1777 "src/html/html_unescape.gperf" + {"Succeeds", 3, {226, 137, 187}}, +#line 1311 "src/html/html_unescape.gperf" + {"Oacute", 2, {195, 147}}, +#line 1875 "src/html/html_unescape.gperf" + {"TRADE", 3, {226, 132, 162}}, +#line 1140 "src/html/html_unescape.gperf" + {"NJcy", 2, {208, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 658 "src/html/html_unescape.gperf" + {"gtdot", 3, {226, 139, 151}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2098 "src/html/html_unescape.gperf" + {"yfr", 4, {240, 157, 148, 182}}, + {(char*)0}, {(char*)0}, +#line 285 "src/html/html_unescape.gperf" + {"compfn", 3, {226, 136, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 657 "src/html/html_unescape.gperf" + {"Gt", 3, {226, 137, 171}}, +#line 1648 "src/html/html_unescape.gperf" + {"scnE", 3, {226, 170, 182}}, +#line 732 "src/html/html_unescape.gperf" + {"ijlig", 2, {196, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 262 "src/html/html_unescape.gperf" + {"circledS", 3, {226, 147, 136}}, + {(char*)0}, {(char*)0}, +#line 2096 "src/html/html_unescape.gperf" + {"yen", 2, {194, 165}}, + {(char*)0}, +#line 1844 "src/html/html_unescape.gperf" + {"thetasym", 2, {207, 145}}, + {(char*)0}, {(char*)0}, +#line 784 "src/html/html_unescape.gperf" + {"iuml", 2, {195, 175}}, +#line 1779 "src/html/html_unescape.gperf" + {"SucceedsSlantEqual", 3, {226, 137, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 160 "src/html/html_unescape.gperf" + {"boxH", 3, {226, 149, 144}}, +#line 1074 "src/html/html_unescape.gperf" + {"mumap", 3, {226, 138, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1578 "src/html/html_unescape.gperf" + {"rightrightarrows", 3, {226, 135, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 281 "src/html/html_unescape.gperf" + {"coloneq", 3, {226, 137, 148}}, + {(char*)0}, +#line 1638 "src/html/html_unescape.gperf" + {"Sc", 3, {226, 170, 188}}, +#line 630 "src/html/html_unescape.gperf" + {"glj", 3, {226, 170, 164}}, +#line 720 "src/html/html_unescape.gperf" + {"iexcl", 2, {194, 161}}, + {(char*)0}, {(char*)0}, +#line 235 "src/html/html_unescape.gperf" + {"ccups", 3, {226, 169, 140}}, + {(char*)0}, +#line 2060 "src/html/html_unescape.gperf" + {"xcap", 3, {226, 139, 130}}, +#line 2124 "src/html/html_unescape.gperf" + {"zhcy", 2, {208, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 164 "src/html/html_unescape.gperf" + {"boxHD", 3, {226, 149, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 912 "src/html/html_unescape.gperf" + {"leqslant", 3, {226, 169, 189}}, + {(char*)0}, +#line 1958 "src/html/html_unescape.gperf" + {"UpperLeftArrow", 3, {226, 134, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 351 "src/html/html_unescape.gperf" + {"dblac", 2, {203, 157}}, + {(char*)0}, {(char*)0}, +#line 1471 "src/html/html_unescape.gperf" + {"puncsp", 3, {226, 128, 136}}, + {(char*)0}, +#line 229 "src/html/html_unescape.gperf" + {"ccaron", 2, {196, 141}}, + {(char*)0}, +#line 1520 "src/html/html_unescape.gperf" + {"rbbrk", 3, {226, 157, 179}}, + {(char*)0}, +#line 850 "src/html/html_unescape.gperf" + {"lbbrk", 3, {226, 157, 178}}, + {(char*)0}, +#line 59 "src/html/html_unescape.gperf" + {"Aogon", 2, {196, 132}}, +#line 899 "src/html/html_unescape.gperf" + {"LeftTriangleBar", 3, {226, 167, 143}}, + {(char*)0}, {(char*)0}, +#line 616 "src/html/html_unescape.gperf" + {"gesdotol", 3, {226, 170, 132}}, +#line 901 "src/html/html_unescape.gperf" + {"LeftTriangleEqual", 3, {226, 138, 180}}, +#line 900 "src/html/html_unescape.gperf" + {"LeftTriangle", 3, {226, 138, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 291 "src/html/html_unescape.gperf" + {"conint", 3, {226, 136, 174}}, + {(char*)0}, {(char*)0}, +#line 440 "src/html/html_unescape.gperf" + {"drbkarow", 3, {226, 164, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1627 "src/html/html_unescape.gperf" + {"rtrif", 3, {226, 150, 184}}, + {(char*)0}, +#line 1023 "src/html/html_unescape.gperf" + {"ltrif", 3, {226, 151, 130}}, + {(char*)0}, {(char*)0}, +#line 1549 "src/html/html_unescape.gperf" + {"ReverseUpEquilibrium", 3, {226, 165, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 879 "src/html/html_unescape.gperf" + {"LeftCeiling", 3, {226, 140, 136}}, + {(char*)0}, +#line 1980 "src/html/html_unescape.gperf" + {"utrif", 3, {226, 150, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 2062 "src/html/html_unescape.gperf" + {"xcup", 3, {226, 139, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 546 "src/html/html_unescape.gperf" + {"fallingdotseq", 3, {226, 137, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1529 "src/html/html_unescape.gperf" + {"rcedil", 2, {197, 151}}, + {(char*)0}, +#line 859 "src/html/html_unescape.gperf" + {"lcedil", 2, {196, 188}}, + {(char*)0}, +#line 1644 "src/html/html_unescape.gperf" + {"scedil", 2, {197, 159}}, + {(char*)0}, +#line 1831 "src/html/html_unescape.gperf" + {"Tcedil", 2, {197, 162}}, + {(char*)0}, +#line 1749 "src/html/html_unescape.gperf" + {"starf", 3, {226, 152, 133}}, +#line 169 "src/html/html_unescape.gperf" + {"boxminus", 3, {226, 138, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1832 "src/html/html_unescape.gperf" + {"tcedil", 2, {197, 163}}, +#line 2118 "src/html/html_unescape.gperf" + {"ZeroWidthSpace", 3, {226, 128, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1094 "src/html/html_unescape.gperf" + {"ncedil", 2, {197, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1405 "src/html/html_unescape.gperf" + {"phiv", 2, {207, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 712 "src/html/html_unescape.gperf" + {"ic", 3, {226, 129, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 221 "src/html/html_unescape.gperf" + {"capdot", 3, {226, 169, 128}}, + {(char*)0}, {(char*)0}, +#line 446 "src/html/html_unescape.gperf" + {"dscy", 2, {209, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 249 "src/html/html_unescape.gperf" + {"check", 3, {226, 156, 147}}, +#line 1382 "src/html/html_unescape.gperf" + {"ovbar", 3, {226, 140, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1281 "src/html/html_unescape.gperf" + {"ntriangleleft", 3, {226, 139, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1581 "src/html/html_unescape.gperf" + {"RightTee", 3, {226, 138, 162}}, +#line 1295 "src/html/html_unescape.gperf" + {"nvge", 3, {226, 137, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 893 "src/html/html_unescape.gperf" + {"leftrightsquigarrow", 3, {226, 134, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 988 "src/html/html_unescape.gperf" + {"lozenge", 3, {226, 151, 138}}, + {(char*)0}, {(char*)0}, +#line 1584 "src/html/html_unescape.gperf" + {"RightTriangleBar", 3, {226, 167, 144}}, + {(char*)0}, +#line 1582 "src/html/html_unescape.gperf" + {"RightTeeVector", 3, {226, 165, 155}}, + {(char*)0}, +#line 1586 "src/html/html_unescape.gperf" + {"RightTriangleEqual", 3, {226, 138, 181}}, +#line 1585 "src/html/html_unescape.gperf" + {"RightTriangle", 3, {226, 138, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 803 "src/html/html_unescape.gperf" + {"Kcedil", 2, {196, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1643 "src/html/html_unescape.gperf" + {"Scedil", 2, {197, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 269 "src/html/html_unescape.gperf" + {"cirfnint", 3, {226, 168, 144}}, + {(char*)0}, {(char*)0}, +#line 491 "src/html/html_unescape.gperf" + {"empty", 3, {226, 136, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 23 "src/html/html_unescape.gperf" + {"afr", 4, {240, 157, 148, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 377 "src/html/html_unescape.gperf" + {"DiacriticalTilde", 2, {203, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 883 "src/html/html_unescape.gperf" + {"LeftDownVector", 3, {226, 135, 131}}, + {(char*)0}, {(char*)0}, +#line 882 "src/html/html_unescape.gperf" + {"LeftDownVectorBar", 3, {226, 165, 153}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 908 "src/html/html_unescape.gperf" + {"lEg", 3, {226, 170, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 69 "src/html/html_unescape.gperf" + {"ApplyFunction", 3, {226, 129, 161}}, + {(char*)0}, {(char*)0}, +#line 209 "src/html/html_unescape.gperf" + {"bumpE", 3, {226, 170, 174}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 858 "src/html/html_unescape.gperf" + {"Lcedil", 2, {196, 187}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 224 "src/html/html_unescape.gperf" + {"caret", 3, {226, 129, 129}}, + {(char*)0}, +#line 92 "src/html/html_unescape.gperf" + {"Barv", 3, {226, 171, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 230 "src/html/html_unescape.gperf" + {"Ccedil", 2, {195, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 261 "src/html/html_unescape.gperf" + {"circledR", 2, {194, 174}}, +#line 881 "src/html/html_unescape.gperf" + {"LeftDownTeeVector", 3, {226, 165, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1896 "src/html/html_unescape.gperf" + {"tshcy", 2, {209, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 403 "src/html/html_unescape.gperf" + {"DotEqual", 3, {226, 137, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 243 "src/html/html_unescape.gperf" + {"centerdot", 2, {194, 183}}, + {(char*)0}, +#line 1282 "src/html/html_unescape.gperf" + {"ntrianglelefteq", 3, {226, 139, 172}}, + {(char*)0}, +#line 1057 "src/html/html_unescape.gperf" + {"minus", 3, {226, 136, 146}}, + {(char*)0}, +#line 624 "src/html/html_unescape.gperf" + {"gimel", 3, {226, 132, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 7 "src/html/html_unescape.gperf" + {"Aacute", 2, {195, 129}}, +#line 654 "src/html/html_unescape.gperf" + {"gtcir", 3, {226, 169, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 662 "src/html/html_unescape.gperf" + {"gtrarr", 3, {226, 165, 184}}, +#line 206 "src/html/html_unescape.gperf" + {"bull", 3, {226, 128, 162}}, + {(char*)0}, {(char*)0}, +#line 424 "src/html/html_unescape.gperf" + {"DownArrow", 3, {226, 134, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1537 "src/html/html_unescape.gperf" + {"rdquor", 3, {226, 128, 157}}, + {(char*)0}, +#line 866 "src/html/html_unescape.gperf" + {"ldquor", 3, {226, 128, 158}}, + {(char*)0}, {(char*)0}, +#line 756 "src/html/html_unescape.gperf" + {"intlarhk", 3, {226, 168, 151}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1978 "src/html/html_unescape.gperf" + {"utilde", 2, {197, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 590 "src/html/html_unescape.gperf" + {"gacute", 2, {199, 181}}, + {(char*)0}, +#line 1279 "src/html/html_unescape.gperf" + {"ntilde", 2, {195, 177}}, +#line 21 "src/html/html_unescape.gperf" + {"af", 3, {226, 129, 161}}, + {(char*)0}, {(char*)0}, +#line 704 "src/html/html_unescape.gperf" + {"Hstrok", 2, {196, 166}}, + {(char*)0}, +#line 544 "src/html/html_unescape.gperf" + {"exponentiale", 3, {226, 133, 135}}, +#line 1056 "src/html/html_unescape.gperf" + {"minusb", 3, {226, 138, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1588 "src/html/html_unescape.gperf" + {"RightUpTeeVector", 3, {226, 165, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1965 "src/html/html_unescape.gperf" + {"UpTeeArrow", 3, {226, 134, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2120 "src/html/html_unescape.gperf" + {"zeta", 2, {206, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 374 "src/html/html_unescape.gperf" + {"DiacriticalDot", 2, {203, 153}}, +#line 375 "src/html/html_unescape.gperf" + {"DiacriticalDoubleAcute", 2, {203, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1147 "src/html/html_unescape.gperf" + {"nleftarrow", 3, {226, 134, 154}}, +#line 692 "src/html/html_unescape.gperf" + {"hkswarow", 3, {226, 164, 166}}, + {(char*)0}, +#line 730 "src/html/html_unescape.gperf" + {"iiota", 3, {226, 132, 169}}, + {(char*)0}, {(char*)0}, +#line 63 "src/html/html_unescape.gperf" + {"apacir", 3, {226, 169, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1093 "src/html/html_unescape.gperf" + {"Ncedil", 2, {197, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 215 "src/html/html_unescape.gperf" + {"capand", 3, {226, 169, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1043 "src/html/html_unescape.gperf" + {"mdash", 3, {226, 128, 148}}, + {(char*)0}, {(char*)0}, +#line 555 "src/html/html_unescape.gperf" + {"filig", 3, {239, 172, 129}}, +#line 1649 "src/html/html_unescape.gperf" + {"scnsim", 3, {226, 139, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1541 "src/html/html_unescape.gperf" + {"realpart", 3, {226, 132, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 898 "src/html/html_unescape.gperf" + {"leftthreetimes", 3, {226, 139, 139}}, +#line 78 "src/html/html_unescape.gperf" + {"asymp", 3, {226, 137, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 686 "src/html/html_unescape.gperf" + {"hellip", 3, {226, 128, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 452 "src/html/html_unescape.gperf" + {"dtrif", 3, {226, 150, 190}}, + {(char*)0}, +#line 1176 "src/html/html_unescape.gperf" + {"NotExists", 3, {226, 136, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1640 "src/html/html_unescape.gperf" + {"sccue", 3, {226, 137, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2090 "src/html/html_unescape.gperf" + {"YAcy", 2, {208, 175}}, +#line 1977 "src/html/html_unescape.gperf" + {"Utilde", 2, {197, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1174 "src/html/html_unescape.gperf" + {"NotEqual", 3, {226, 137, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1849 "src/html/html_unescape.gperf" + {"ThinSpace", 3, {226, 128, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 65 "src/html/html_unescape.gperf" + {"apE", 3, {226, 169, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 207 "src/html/html_unescape.gperf" + {"bullet", 3, {226, 128, 162}}, + {(char*)0}, {(char*)0}, +#line 273 "src/html/html_unescape.gperf" + {"CloseCurlyDoubleQuote", 3, {226, 128, 157}}, +#line 364 "src/html/html_unescape.gperf" + {"Delta", 2, {206, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 621 "src/html/html_unescape.gperf" + {"gg", 3, {226, 137, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1379 "src/html/html_unescape.gperf" + {"otimes", 3, {226, 138, 151}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 2057 "src/html/html_unescape.gperf" + {"wreath", 3, {226, 137, 128}}, + {(char*)0}, +#line 1528 "src/html/html_unescape.gperf" + {"Rcedil", 2, {197, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 536 "src/html/html_unescape.gperf" + {"eth", 2, {195, 176}}, +#line 1806 "src/html/html_unescape.gperf" + {"supnE", 3, {226, 171, 140}}, + {(char*)0}, {(char*)0}, +#line 85 "src/html/html_unescape.gperf" + {"awint", 3, {226, 168, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 196 "src/html/html_unescape.gperf" + {"Breve", 2, {203, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 622 "src/html/html_unescape.gperf" + {"Gg", 3, {226, 139, 153}}, + {(char*)0}, +#line 707 "src/html/html_unescape.gperf" + {"HumpEqual", 3, {226, 137, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 949 "src/html/html_unescape.gperf" + {"Lleftarrow", 3, {226, 135, 154}}, +#line 155 "src/html/html_unescape.gperf" + {"boxdr", 3, {226, 148, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1783 "src/html/html_unescape.gperf" + {"succneqq", 3, {226, 170, 182}}, +#line 1972 "src/html/html_unescape.gperf" + {"uring", 2, {197, 175}}, +#line 930 "src/html/html_unescape.gperf" + {"LessSlantEqual", 3, {226, 169, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1291 "src/html/html_unescape.gperf" + {"nvdash", 3, {226, 138, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 670 "src/html/html_unescape.gperf" + {"Hacek", 2, {203, 135}}, +#line 780 "src/html/html_unescape.gperf" + {"itilde", 2, {196, 169}}, + {(char*)0}, {(char*)0}, +#line 766 "src/html/html_unescape.gperf" + {"Iota", 2, {206, 153}}, + {(char*)0}, +#line 760 "src/html/html_unescape.gperf" + {"IOcy", 2, {208, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 157 "src/html/html_unescape.gperf" + {"boxDr", 3, {226, 149, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1780 "src/html/html_unescape.gperf" + {"SucceedsTilde", 3, {226, 137, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 884 "src/html/html_unescape.gperf" + {"LeftFloor", 3, {226, 140, 138}}, +#line 2042 "src/html/html_unescape.gperf" + {"Vvdash", 3, {226, 138, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1877 "src/html/html_unescape.gperf" + {"triangledown", 3, {226, 150, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 970 "src/html/html_unescape.gperf" + {"LongLeftRightArrow", 3, {226, 159, 183}}, +#line 1573 "src/html/html_unescape.gperf" + {"RightFloor", 3, {226, 140, 139}}, + {(char*)0}, {(char*)0}, +#line 435 "src/html/html_unescape.gperf" + {"DownRightTeeVector", 3, {226, 165, 159}}, + {(char*)0}, +#line 1481 "src/html/html_unescape.gperf" + {"quatint", 3, {226, 168, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1278 "src/html/html_unescape.gperf" + {"Ntilde", 2, {195, 145}}, + {(char*)0}, {(char*)0}, +#line 211 "src/html/html_unescape.gperf" + {"Bumpeq", 3, {226, 137, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 669 "src/html/html_unescape.gperf" + {"gvnE", 3, {226, 137, 169}}, + {(char*)0}, +#line 165 "src/html/html_unescape.gperf" + {"boxhu", 3, {226, 148, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 659 "src/html/html_unescape.gperf" + {"gtlPar", 3, {226, 166, 149}}, + {(char*)0}, {(char*)0}, +#line 1238 "src/html/html_unescape.gperf" + {"nprec", 3, {226, 138, 128}}, + {(char*)0}, {(char*)0}, +#line 1381 "src/html/html_unescape.gperf" + {"ouml", 2, {195, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 612 "src/html/html_unescape.gperf" + {"gescc", 3, {226, 170, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 537 "src/html/html_unescape.gperf" + {"Euml", 2, {195, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1971 "src/html/html_unescape.gperf" + {"Uring", 2, {197, 174}}, + {(char*)0}, +#line 1938 "src/html/html_unescape.gperf" + {"UnderBracket", 3, {226, 142, 181}}, +#line 1162 "src/html/html_unescape.gperf" + {"nLtv", 3, {226, 137, 170}}, +#line 873 "src/html/html_unescape.gperf" + {"LeftArrowBar", 3, {226, 135, 164}}, +#line 1096 "src/html/html_unescape.gperf" + {"ncongdot", 3, {226, 169, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 79 "src/html/html_unescape.gperf" + {"asympeq", 3, {226, 137, 141}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1059 "src/html/html_unescape.gperf" + {"minusdu", 3, {226, 168, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 365 "src/html/html_unescape.gperf" + {"delta", 2, {206, 180}}, + {(char*)0}, +#line 679 "src/html/html_unescape.gperf" + {"harrw", 3, {226, 134, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 39 "src/html/html_unescape.gperf" + {"andslope", 3, {226, 169, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 238 "src/html/html_unescape.gperf" + {"cdot", 2, {196, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 226 "src/html/html_unescape.gperf" + {"Cayleys", 3, {226, 132, 173}}, +#line 167 "src/html/html_unescape.gperf" + {"boxhU", 3, {226, 149, 168}}, + {(char*)0}, {(char*)0}, +#line 1785 "src/html/html_unescape.gperf" + {"succsim", 3, {226, 137, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 267 "src/html/html_unescape.gperf" + {"cirE", 3, {226, 167, 131}}, +#line 1654 "src/html/html_unescape.gperf" + {"sdotb", 3, {226, 138, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1319 "src/html/html_unescape.gperf" + {"odash", 3, {226, 138, 157}}, +#line 270 "src/html/html_unescape.gperf" + {"cirmid", 3, {226, 171, 175}}, +#line 1803 "src/html/html_unescape.gperf" + {"suphsub", 3, {226, 171, 151}}, +#line 1796 "src/html/html_unescape.gperf" + {"supdsub", 3, {226, 171, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1795 "src/html/html_unescape.gperf" + {"supdot", 3, {226, 170, 190}}, + {(char*)0}, +#line 84 "src/html/html_unescape.gperf" + {"awconint", 3, {226, 136, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1895 "src/html/html_unescape.gperf" + {"TSHcy", 2, {208, 139}}, + {(char*)0}, {(char*)0}, +#line 640 "src/html/html_unescape.gperf" + {"grave", 1, {96}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1005 "src/html/html_unescape.gperf" + {"lsimg", 3, {226, 170, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1950 "src/html/html_unescape.gperf" + {"UpArrowDownArrow", 3, {226, 135, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 907 "src/html/html_unescape.gperf" + {"LeftVector", 3, {226, 134, 188}}, +#line 417 "src/html/html_unescape.gperf" + {"DoubleRightArrow", 3, {226, 135, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1109 "src/html/html_unescape.gperf" + {"NegativeThinSpace", 3, {226, 128, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 942 "src/html/html_unescape.gperf" + {"lhblk", 3, {226, 150, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 268 "src/html/html_unescape.gperf" + {"cire", 3, {226, 137, 151}}, +#line 1294 "src/html/html_unescape.gperf" + {"nVDash", 3, {226, 138, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1928 "src/html/html_unescape.gperf" + {"uhblk", 3, {226, 150, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 738 "src/html/html_unescape.gperf" + {"imagpart", 3, {226, 132, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1587 "src/html/html_unescape.gperf" + {"RightUpDownVector", 3, {226, 165, 143}}, + {(char*)0}, {(char*)0}, +#line 152 "src/html/html_unescape.gperf" + {"boxdL", 3, {226, 149, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 627 "src/html/html_unescape.gperf" + {"gla", 3, {226, 170, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 783 "src/html/html_unescape.gperf" + {"Iuml", 2, {195, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1326 "src/html/html_unescape.gperf" + {"oelig", 2, {197, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1199 "src/html/html_unescape.gperf" + {"NotLessSlantEqual", 3, {226, 169, 189}}, + {(char*)0}, +#line 154 "src/html/html_unescape.gperf" + {"boxDL", 3, {226, 149, 151}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 592 "src/html/html_unescape.gperf" + {"gamma", 2, {206, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1378 "src/html/html_unescape.gperf" + {"Otimes", 3, {226, 168, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 969 "src/html/html_unescape.gperf" + {"longleftrightarrow", 3, {226, 159, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 591 "src/html/html_unescape.gperf" + {"Gamma", 2, {206, 147}}, +#line 128 "src/html/html_unescape.gperf" + {"bigwedge", 3, {226, 139, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 161 "src/html/html_unescape.gperf" + {"boxhd", 3, {226, 148, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1797 "src/html/html_unescape.gperf" + {"supE", 3, {226, 171, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 903 "src/html/html_unescape.gperf" + {"LeftUpTeeVector", 3, {226, 165, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 615 "src/html/html_unescape.gperf" + {"gesdoto", 3, {226, 170, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 801 "src/html/html_unescape.gperf" + {"kappa", 2, {206, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1125 "src/html/html_unescape.gperf" + {"ngeqslant", 3, {226, 169, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 666 "src/html/html_unescape.gperf" + {"gtrless", 3, {226, 137, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 551 "src/html/html_unescape.gperf" + {"fflig", 3, {239, 172, 128}}, +#line 122 "src/html/html_unescape.gperf" + {"bigsqcup", 3, {226, 168, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 809 "src/html/html_unescape.gperf" + {"kgreen", 2, {196, 184}}, +#line 1798 "src/html/html_unescape.gperf" + {"supe", 3, {226, 138, 135}}, + {(char*)0}, +#line 171 "src/html/html_unescape.gperf" + {"boxtimes", 3, {226, 138, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 632 "src/html/html_unescape.gperf" + {"gnapprox", 3, {226, 170, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 428 "src/html/html_unescape.gperf" + {"downdownarrows", 3, {226, 135, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 126 "src/html/html_unescape.gperf" + {"biguplus", 3, {226, 168, 132}}, +#line 811 "src/html/html_unescape.gperf" + {"khcy", 2, {209, 133}}, + {(char*)0}, +#line 356 "src/html/html_unescape.gperf" + {"ddagger", 3, {226, 128, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1380 "src/html/html_unescape.gperf" + {"Ouml", 2, {195, 150}}, + {(char*)0}, +#line 110 "src/html/html_unescape.gperf" + {"Beta", 2, {206, 146}}, +#line 1058 "src/html/html_unescape.gperf" + {"minusd", 3, {226, 136, 184}}, +#line 1784 "src/html/html_unescape.gperf" + {"succnsim", 3, {226, 139, 169}}, + {(char*)0}, +#line 311 "src/html/html_unescape.gperf" + {"ctdot", 3, {226, 139, 175}}, + {(char*)0}, {(char*)0}, +#line 813 "src/html/html_unescape.gperf" + {"kjcy", 2, {209, 156}}, +#line 626 "src/html/html_unescape.gperf" + {"gjcy", 2, {209, 147}}, + {(char*)0}, +#line 1095 "src/html/html_unescape.gperf" + {"ncong", 3, {226, 137, 135}}, +#line 2086 "src/html/html_unescape.gperf" + {"xvee", 3, {226, 139, 129}}, +#line 99 "src/html/html_unescape.gperf" + {"bcong", 3, {226, 137, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1723 "src/html/html_unescape.gperf" + {"sqsube", 3, {226, 138, 145}}, + {(char*)0}, {(char*)0}, +#line 156 "src/html/html_unescape.gperf" + {"boxdR", 3, {226, 149, 146}}, + {(char*)0}, {(char*)0}, +#line 971 "src/html/html_unescape.gperf" + {"Longleftrightarrow", 3, {226, 159, 186}}, + {(char*)0}, +#line 1722 "src/html/html_unescape.gperf" + {"sqsub", 3, {226, 138, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 431 "src/html/html_unescape.gperf" + {"DownLeftRightVector", 3, {226, 165, 144}}, + {(char*)0}, {(char*)0}, +#line 1724 "src/html/html_unescape.gperf" + {"sqsubset", 3, {226, 138, 143}}, + {(char*)0}, +#line 1230 "src/html/html_unescape.gperf" + {"NotVerticalBar", 3, {226, 136, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1175 "src/html/html_unescape.gperf" + {"NotEqualTilde", 3, {226, 137, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 151 "src/html/html_unescape.gperf" + {"boxdl", 3, {226, 148, 144}}, + {(char*)0}, {(char*)0}, +#line 158 "src/html/html_unescape.gperf" + {"boxDR", 3, {226, 149, 148}}, + {(char*)0}, +#line 35 "src/html/html_unescape.gperf" + {"andand", 3, {226, 169, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1592 "src/html/html_unescape.gperf" + {"RightVector", 3, {226, 135, 128}}, + {(char*)0}, +#line 731 "src/html/html_unescape.gperf" + {"IJlig", 2, {196, 178}}, +#line 1227 "src/html/html_unescape.gperf" + {"NotTildeEqual", 3, {226, 137, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 58 "src/html/html_unescape.gperf" + {"angzarr", 3, {226, 141, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 53 "src/html/html_unescape.gperf" + {"angrt", 3, {226, 136, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 12 "src/html/html_unescape.gperf" + {"acd", 3, {226, 136, 191}}, + {(char*)0}, {(char*)0}, +#line 38 "src/html/html_unescape.gperf" + {"andd", 3, {226, 169, 156}}, + {(char*)0}, +#line 1241 "src/html/html_unescape.gperf" + {"nrarrc", 3, {226, 164, 179}}, +#line 2026 "src/html/html_unescape.gperf" + {"VeryThinSpace", 3, {226, 128, 138}}, + {(char*)0}, +#line 1800 "src/html/html_unescape.gperf" + {"Superset", 3, {226, 138, 131}}, + {(char*)0}, +#line 153 "src/html/html_unescape.gperf" + {"boxDl", 3, {226, 149, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2030 "src/html/html_unescape.gperf" + {"vnsub", 3, {226, 138, 130}}, + {(char*)0}, {(char*)0}, +#line 236 "src/html/html_unescape.gperf" + {"ccupssm", 3, {226, 169, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1988 "src/html/html_unescape.gperf" + {"varnothing", 3, {226, 136, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1533 "src/html/html_unescape.gperf" + {"rcy", 2, {209, 128}}, + {(char*)0}, +#line 863 "src/html/html_unescape.gperf" + {"lcy", 2, {208, 187}}, + {(char*)0}, +#line 1653 "src/html/html_unescape.gperf" + {"scy", 2, {209, 129}}, + {(char*)0}, +#line 1833 "src/html/html_unescape.gperf" + {"Tcy", 2, {208, 162}}, +#line 2113 "src/html/html_unescape.gperf" + {"Zcy", 2, {208, 151}}, +#line 469 "src/html/html_unescape.gperf" + {"ecy", 2, {209, 141}}, +#line 1538 "src/html/html_unescape.gperf" + {"rdsh", 3, {226, 134, 179}}, + {(char*)0}, +#line 869 "src/html/html_unescape.gperf" + {"ldsh", 3, {226, 134, 178}}, + {(char*)0}, +#line 1915 "src/html/html_unescape.gperf" + {"ucy", 2, {209, 131}}, +#line 185 "src/html/html_unescape.gperf" + {"boxVH", 3, {226, 149, 172}}, +#line 1834 "src/html/html_unescape.gperf" + {"tcy", 2, {209, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1099 "src/html/html_unescape.gperf" + {"ncy", 2, {208, 189}}, + {(char*)0}, +#line 101 "src/html/html_unescape.gperf" + {"bcy", 2, {208, 177}}, +#line 1277 "src/html/html_unescape.gperf" + {"ntgl", 3, {226, 137, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 787 "src/html/html_unescape.gperf" + {"Jcy", 2, {208, 153}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 289 "src/html/html_unescape.gperf" + {"congdot", 3, {226, 169, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 57 "src/html/html_unescape.gperf" + {"angst", 2, {195, 133}}, + {(char*)0}, +#line 1570 "src/html/html_unescape.gperf" + {"RightDownTeeVector", 3, {226, 165, 157}}, + {(char*)0}, {(char*)0}, +#line 1386 "src/html/html_unescape.gperf" + {"OverParenthesis", 3, {226, 143, 156}}, +#line 1020 "src/html/html_unescape.gperf" + {"ltquest", 3, {226, 169, 187}}, + {(char*)0}, +#line 1395 "src/html/html_unescape.gperf" + {"pcy", 2, {208, 191}}, + {(char*)0}, {(char*)0}, +#line 1376 "src/html/html_unescape.gperf" + {"otilde", 2, {195, 181}}, +#line 1536 "src/html/html_unescape.gperf" + {"rdquo", 3, {226, 128, 157}}, + {(char*)0}, +#line 865 "src/html/html_unescape.gperf" + {"ldquo", 3, {226, 128, 156}}, + {(char*)0}, +#line 2006 "src/html/html_unescape.gperf" + {"Vcy", 2, {208, 146}}, + {(char*)0}, {(char*)0}, +#line 216 "src/html/html_unescape.gperf" + {"capbrcup", 3, {226, 169, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 102 "src/html/html_unescape.gperf" + {"bdquo", 3, {226, 128, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 422 "src/html/html_unescape.gperf" + {"DownArrowBar", 3, {226, 164, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 2007 "src/html/html_unescape.gperf" + {"vcy", 2, {208, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 54 "src/html/html_unescape.gperf" + {"angrtvb", 3, {226, 138, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 805 "src/html/html_unescape.gperf" + {"Kcy", 2, {208, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1041 "src/html/html_unescape.gperf" + {"Mcy", 2, {208, 156}}, +#line 1652 "src/html/html_unescape.gperf" + {"Scy", 2, {208, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1116 "src/html/html_unescape.gperf" + {"NewLine", 1, {10}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 548 "src/html/html_unescape.gperf" + {"fcy", 2, {209, 132}}, +#line 1914 "src/html/html_unescape.gperf" + {"Ucy", 2, {208, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 184 "src/html/html_unescape.gperf" + {"boxVh", 3, {226, 149, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 354 "src/html/html_unescape.gperf" + {"Dcy", 2, {208, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 705 "src/html/html_unescape.gperf" + {"hstrok", 2, {196, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 862 "src/html/html_unescape.gperf" + {"Lcy", 2, {208, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 2094 "src/html/html_unescape.gperf" + {"Ycy", 2, {208, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1815 "src/html/html_unescape.gperf" + {"supsim", 3, {226, 171, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1165 "src/html/html_unescape.gperf" + {"NonBreakingSpace", 2, {194, 160}}, +#line 1383 "src/html/html_unescape.gperf" + {"OverBar", 3, {226, 128, 190}}, +#line 1725 "src/html/html_unescape.gperf" + {"sqsubseteq", 3, {226, 138, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 625 "src/html/html_unescape.gperf" + {"GJcy", 2, {208, 131}}, + {(char*)0}, {(char*)0}, +#line 1384 "src/html/html_unescape.gperf" + {"OverBrace", 3, {226, 143, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 513 "src/html/html_unescape.gperf" + {"eqcirc", 3, {226, 137, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1385 "src/html/html_unescape.gperf" + {"OverBracket", 3, {226, 142, 180}}, + {(char*)0}, +#line 82 "src/html/html_unescape.gperf" + {"Auml", 2, {195, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 16 "src/html/html_unescape.gperf" + {"acute", 2, {194, 180}}, +#line 716 "src/html/html_unescape.gperf" + {"icy", 2, {208, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 779 "src/html/html_unescape.gperf" + {"Itilde", 2, {196, 168}}, +#line 690 "src/html/html_unescape.gperf" + {"HilbertSpace", 3, {226, 132, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1345 "src/html/html_unescape.gperf" + {"omega", 2, {207, 137}}, +#line 214 "src/html/html_unescape.gperf" + {"cacute", 2, {196, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1646 "src/html/html_unescape.gperf" + {"scirc", 2, {197, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 465 "src/html/html_unescape.gperf" + {"ecirc", 2, {195, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1913 "src/html/html_unescape.gperf" + {"ucirc", 2, {195, 187}}, + {(char*)0}, +#line 646 "src/html/html_unescape.gperf" + {"GreaterSlantEqual", 3, {226, 169, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 785 "src/html/html_unescape.gperf" + {"Jcirc", 2, {196, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1292 "src/html/html_unescape.gperf" + {"nvDash", 3, {226, 138, 173}}, +#line 2044 "src/html/html_unescape.gperf" + {"Wcirc", 2, {197, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1098 "src/html/html_unescape.gperf" + {"Ncy", 2, {208, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1580 "src/html/html_unescape.gperf" + {"RightTeeArrow", 3, {226, 134, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 925 "src/html/html_unescape.gperf" + {"LessFullEqual", 3, {226, 137, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1011 "src/html/html_unescape.gperf" + {"ltcc", 3, {226, 170, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 27 "src/html/html_unescape.gperf" + {"aleph", 3, {226, 132, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 355 "src/html/html_unescape.gperf" + {"dcy", 2, {208, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1645 "src/html/html_unescape.gperf" + {"Scirc", 2, {197, 156}}, + {(char*)0}, +#line 920 "src/html/html_unescape.gperf" + {"lessapprox", 3, {226, 170, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 718 "src/html/html_unescape.gperf" + {"IEcy", 2, {208, 149}}, +#line 986 "src/html/html_unescape.gperf" + {"LowerRightArrow", 3, {226, 134, 152}}, +#line 1912 "src/html/html_unescape.gperf" + {"Ucirc", 2, {195, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 25 "src/html/html_unescape.gperf" + {"agrave", 2, {195, 160}}, + {(char*)0}, +#line 1060 "src/html/html_unescape.gperf" + {"MinusPlus", 3, {226, 136, 147}}, +#line 127 "src/html/html_unescape.gperf" + {"bigvee", 3, {226, 139, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1532 "src/html/html_unescape.gperf" + {"Rcy", 2, {208, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1802 "src/html/html_unescape.gperf" + {"suphsol", 3, {226, 159, 137}}, + {(char*)0}, {(char*)0}, +#line 495 "src/html/html_unescape.gperf" + {"EmptyVerySmallSquare", 3, {226, 150, 171}}, + {(char*)0}, +#line 163 "src/html/html_unescape.gperf" + {"boxhD", 3, {226, 149, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1436 "src/html/html_unescape.gperf" + {"precapprox", 3, {226, 170, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 55 "src/html/html_unescape.gperf" + {"angrtvbd", 3, {226, 166, 157}}, +#line 2092 "src/html/html_unescape.gperf" + {"Ycirc", 2, {197, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1753 "src/html/html_unescape.gperf" + {"sub", 3, {226, 138, 130}}, + {(char*)0}, {(char*)0}, +#line 1375 "src/html/html_unescape.gperf" + {"Otilde", 2, {195, 149}}, +#line 232 "src/html/html_unescape.gperf" + {"Ccirc", 2, {196, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 547 "src/html/html_unescape.gperf" + {"Fcy", 2, {208, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 287 "src/html/html_unescape.gperf" + {"complexes", 3, {226, 132, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1763 "src/html/html_unescape.gperf" + {"subrarr", 3, {226, 165, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 758 "src/html/html_unescape.gperf" + {"InvisibleComma", 3, {226, 129, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 176 "src/html/html_unescape.gperf" + {"boxur", 3, {226, 148, 148}}, +#line 10 "src/html/html_unescape.gperf" + {"abreve", 2, {196, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1280 "src/html/html_unescape.gperf" + {"ntlg", 3, {226, 137, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 714 "src/html/html_unescape.gperf" + {"icirc", 2, {195, 174}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 2063 "src/html/html_unescape.gperf" + {"xdtri", 3, {226, 150, 189}}, +#line 253 "src/html/html_unescape.gperf" + {"circ", 2, {203, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 663 "src/html/html_unescape.gperf" + {"gtrdot", 3, {226, 139, 151}}, + {(char*)0}, {(char*)0}, +#line 611 "src/html/html_unescape.gperf" + {"geqslant", 3, {226, 169, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1283 "src/html/html_unescape.gperf" + {"ntriangleright", 3, {226, 139, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 314 "src/html/html_unescape.gperf" + {"cuepr", 3, {226, 139, 158}}, +#line 1754 "src/html/html_unescape.gperf" + {"Sub", 3, {226, 139, 144}}, + {(char*)0}, +#line 1042 "src/html/html_unescape.gperf" + {"mcy", 2, {208, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1860 "src/html/html_unescape.gperf" + {"timesbar", 3, {226, 168, 177}}, + {(char*)0}, +#line 691 "src/html/html_unescape.gperf" + {"hksearow", 3, {226, 164, 165}}, + {(char*)0}, {(char*)0}, +#line 1683 "src/html/html_unescape.gperf" + {"sigma", 2, {207, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 325 "src/html/html_unescape.gperf" + {"cupor", 3, {226, 169, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1373 "src/html/html_unescape.gperf" + {"oslash", 2, {195, 184}}, +#line 458 "src/html/html_unescape.gperf" + {"dzigrarr", 3, {226, 159, 191}}, + {(char*)0}, {(char*)0}, +#line 892 "src/html/html_unescape.gperf" + {"leftrightharpoons", 3, {226, 135, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1577 "src/html/html_unescape.gperf" + {"rightleftharpoons", 3, {226, 135, 140}}, + {(char*)0}, +#line 804 "src/html/html_unescape.gperf" + {"kcedil", 2, {196, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1759 "src/html/html_unescape.gperf" + {"submult", 3, {226, 171, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 333 "src/html/html_unescape.gperf" + {"curren", 2, {194, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 897 "src/html/html_unescape.gperf" + {"LeftTeeVector", 3, {226, 165, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 123 "src/html/html_unescape.gperf" + {"bigstar", 3, {226, 152, 133}}, + {(char*)0}, {(char*)0}, +#line 321 "src/html/html_unescape.gperf" + {"cup", 3, {226, 136, 170}}, +#line 974 "src/html/html_unescape.gperf" + {"LongRightArrow", 3, {226, 159, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 598 "src/html/html_unescape.gperf" + {"Gcedil", 2, {196, 162}}, + {(char*)0}, +#line 1440 "src/html/html_unescape.gperf" + {"PrecedesEqual", 3, {226, 170, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 2114 "src/html/html_unescape.gperf" + {"zcy", 2, {208, 183}}, + {(char*)0}, +#line 1413 "src/html/html_unescape.gperf" + {"planckh", 3, {226, 132, 142}}, +#line 1344 "src/html/html_unescape.gperf" + {"Omega", 2, {206, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1772 "src/html/html_unescape.gperf" + {"subsub", 3, {226, 171, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1534 "src/html/html_unescape.gperf" + {"rdca", 3, {226, 164, 183}}, +#line 326 "src/html/html_unescape.gperf" + {"cups", 3, {226, 136, 170}}, +#line 864 "src/html/html_unescape.gperf" + {"ldca", 3, {226, 164, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1764 "src/html/html_unescape.gperf" + {"subset", 3, {226, 138, 130}}, +#line 1220 "src/html/html_unescape.gperf" + {"NotSucceeds", 3, {226, 138, 129}}, +#line 877 "src/html/html_unescape.gperf" + {"LeftArrowRightArrow", 3, {226, 135, 134}}, + {(char*)0}, {(char*)0}, +#line 2045 "src/html/html_unescape.gperf" + {"wcirc", 2, {197, 181}}, +#line 1561 "src/html/html_unescape.gperf" + {"RightAngleBracket", 3, {226, 159, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1284 "src/html/html_unescape.gperf" + {"ntrianglerighteq", 3, {226, 139, 173}}, +#line 1682 "src/html/html_unescape.gperf" + {"Sigma", 2, {206, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1223 "src/html/html_unescape.gperf" + {"NotSucceedsTilde", 3, {226, 137, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 373 "src/html/html_unescape.gperf" + {"DiacriticalAcute", 2, {194, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1761 "src/html/html_unescape.gperf" + {"subne", 3, {226, 138, 138}}, + {(char*)0}, +#line 1457 "src/html/html_unescape.gperf" + {"Product", 3, {226, 136, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 259 "src/html/html_unescape.gperf" + {"circleddash", 3, {226, 138, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1773 "src/html/html_unescape.gperf" + {"subsup", 3, {226, 171, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 298 "src/html/html_unescape.gperf" + {"copy", 2, {194, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 534 "src/html/html_unescape.gperf" + {"eta", 2, {206, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 52 "src/html/html_unescape.gperf" + {"angmsd", 3, {226, 136, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1084 "src/html/html_unescape.gperf" + {"natural", 3, {226, 153, 174}}, + {(char*)0}, +#line 1799 "src/html/html_unescape.gperf" + {"supedot", 3, {226, 171, 132}}, +#line 1085 "src/html/html_unescape.gperf" + {"naturals", 3, {226, 132, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1881 "src/html/html_unescape.gperf" + {"triangleright", 3, {226, 150, 185}}, + {(char*)0}, +#line 376 "src/html/html_unescape.gperf" + {"DiacriticalGrave", 1, {96}}, +#line 173 "src/html/html_unescape.gperf" + {"boxuL", 3, {226, 149, 155}}, +#line 288 "src/html/html_unescape.gperf" + {"cong", 3, {226, 137, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1836 "src/html/html_unescape.gperf" + {"telrec", 3, {226, 140, 149}}, + {(char*)0}, {(char*)0}, +#line 282 "src/html/html_unescape.gperf" + {"comma", 1, {44}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1765 "src/html/html_unescape.gperf" + {"Subset", 3, {226, 139, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1222 "src/html/html_unescape.gperf" + {"NotSucceedsSlantEqual", 3, {226, 139, 161}}, +#line 664 "src/html/html_unescape.gperf" + {"gtreqless", 3, {226, 139, 155}}, +#line 80 "src/html/html_unescape.gperf" + {"Atilde", 2, {195, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 327 "src/html/html_unescape.gperf" + {"curarr", 3, {226, 134, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 313 "src/html/html_unescape.gperf" + {"cudarrr", 3, {226, 164, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 312 "src/html/html_unescape.gperf" + {"cudarrl", 3, {226, 164, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1766 "src/html/html_unescape.gperf" + {"subseteq", 3, {226, 138, 134}}, +#line 1767 "src/html/html_unescape.gperf" + {"subseteqq", 3, {226, 171, 133}}, +#line 1579 "src/html/html_unescape.gperf" + {"rightsquigarrow", 3, {226, 134, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 319 "src/html/html_unescape.gperf" + {"cupcap", 3, {226, 169, 134}}, +#line 1769 "src/html/html_unescape.gperf" + {"subsetneq", 3, {226, 138, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 60 "src/html/html_unescape.gperf" + {"aogon", 2, {196, 133}}, +#line 1191 "src/html/html_unescape.gperf" + {"notinvc", 3, {226, 139, 182}}, +#line 1583 "src/html/html_unescape.gperf" + {"rightthreetimes", 3, {226, 139, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 2089 "src/html/html_unescape.gperf" + {"yacute", 2, {195, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1148 "src/html/html_unescape.gperf" + {"nLeftarrow", 3, {226, 135, 141}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1318 "src/html/html_unescape.gperf" + {"ocy", 2, {208, 190}}, +#line 241 "src/html/html_unescape.gperf" + {"cemptyv", 3, {226, 166, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 468 "src/html/html_unescape.gperf" + {"Ecy", 2, {208, 173}}, + {(char*)0}, {(char*)0}, +#line 323 "src/html/html_unescape.gperf" + {"cupcup", 3, {226, 169, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1882 "src/html/html_unescape.gperf" + {"trianglerighteq", 3, {226, 138, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 889 "src/html/html_unescape.gperf" + {"LeftRightArrow", 3, {226, 134, 148}}, + {(char*)0}, {(char*)0}, +#line 1775 "src/html/html_unescape.gperf" + {"succ", 3, {226, 137, 187}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 426 "src/html/html_unescape.gperf" + {"DownArrowUpArrow", 3, {226, 135, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1325 "src/html/html_unescape.gperf" + {"OElig", 2, {197, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 248 "src/html/html_unescape.gperf" + {"chcy", 2, {209, 135}}, +#line 665 "src/html/html_unescape.gperf" + {"gtreqqless", 3, {226, 170, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 43 "src/html/html_unescape.gperf" + {"angle", 3, {226, 136, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 13 "src/html/html_unescape.gperf" + {"acE", 3, {226, 136, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1598 "src/html/html_unescape.gperf" + {"rmoustache", 3, {226, 142, 177}}, + {(char*)0}, +#line 954 "src/html/html_unescape.gperf" + {"lmoustache", 3, {226, 142, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1110 "src/html/html_unescape.gperf" + {"NegativeVeryThinSpace", 3, {226, 128, 139}}, + {(char*)0}, {(char*)0}, +#line 1083 "src/html/html_unescape.gperf" + {"napprox", 3, {226, 137, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1372 "src/html/html_unescape.gperf" + {"Oslash", 2, {195, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1770 "src/html/html_unescape.gperf" + {"subsetneqq", 3, {226, 171, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 72 "src/html/html_unescape.gperf" + {"Aring", 2, {195, 133}}, +#line 177 "src/html/html_unescape.gperf" + {"boxuR", 3, {226, 149, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1762 "src/html/html_unescape.gperf" + {"subplus", 3, {226, 170, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2087 "src/html/html_unescape.gperf" + {"xwedge", 3, {226, 139, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 172 "src/html/html_unescape.gperf" + {"boxul", 3, {226, 148, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 190 "src/html/html_unescape.gperf" + {"boxvr", 3, {226, 148, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 706 "src/html/html_unescape.gperf" + {"HumpDownHump", 3, {226, 137, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 715 "src/html/html_unescape.gperf" + {"Icy", 2, {208, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 71 "src/html/html_unescape.gperf" + {"approxeq", 3, {226, 137, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 8 "src/html/html_unescape.gperf" + {"aacute", 2, {195, 161}}, +#line 67 "src/html/html_unescape.gperf" + {"apid", 3, {226, 137, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1952 "src/html/html_unescape.gperf" + {"UpDownArrow", 3, {226, 134, 149}}, + {(char*)0}, +#line 1114 "src/html/html_unescape.gperf" + {"NestedGreaterGreater", 3, {226, 137, 171}}, + {(char*)0}, +#line 788 "src/html/html_unescape.gperf" + {"jcy", 2, {208, 185}}, + {(char*)0}, {(char*)0}, +#line 667 "src/html/html_unescape.gperf" + {"gtrsim", 3, {226, 137, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 180 "src/html/html_unescape.gperf" + {"boxv", 3, {226, 148, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1315 "src/html/html_unescape.gperf" + {"ocirc", 2, {195, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 464 "src/html/html_unescape.gperf" + {"Ecirc", 2, {195, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1206 "src/html/html_unescape.gperf" + {"notnivc", 3, {226, 139, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 125 "src/html/html_unescape.gperf" + {"bigtriangleup", 3, {226, 150, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 343 "src/html/html_unescape.gperf" + {"daleth", 3, {226, 132, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1317 "src/html/html_unescape.gperf" + {"Ocy", 2, {208, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 682 "src/html/html_unescape.gperf" + {"Hcirc", 2, {196, 164}}, +#line 1591 "src/html/html_unescape.gperf" + {"RightVectorBar", 3, {226, 165, 147}}, +#line 19 "src/html/html_unescape.gperf" + {"AElig", 2, {195, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 557 "src/html/html_unescape.gperf" + {"FilledVerySmallSquare", 3, {226, 150, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 623 "src/html/html_unescape.gperf" + {"ggg", 3, {226, 139, 153}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 100 "src/html/html_unescape.gperf" + {"Bcy", 2, {208, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1427 "src/html/html_unescape.gperf" + {"Poincareplane", 3, {226, 132, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 187 "src/html/html_unescape.gperf" + {"boxvL", 3, {226, 149, 161}}, + {(char*)0}, {(char*)0}, +#line 1393 "src/html/html_unescape.gperf" + {"PartialD", 3, {226, 136, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 713 "src/html/html_unescape.gperf" + {"Icirc", 2, {195, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 316 "src/html/html_unescape.gperf" + {"cularr", 3, {226, 134, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 159 "src/html/html_unescape.gperf" + {"boxh", 3, {226, 148, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 40 "src/html/html_unescape.gperf" + {"andv", 3, {226, 169, 154}}, + {(char*)0}, +#line 1789 "src/html/html_unescape.gperf" + {"sung", 3, {226, 153, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1569 "src/html/html_unescape.gperf" + {"RightDoubleBracket", 3, {226, 159, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 786 "src/html/html_unescape.gperf" + {"jcirc", 2, {196, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1936 "src/html/html_unescape.gperf" + {"UnderBar", 1, {95}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1564 "src/html/html_unescape.gperf" + {"RightArrow", 3, {226, 134, 146}}, +#line 258 "src/html/html_unescape.gperf" + {"circledcirc", 3, {226, 138, 154}}, +#line 28 "src/html/html_unescape.gperf" + {"Alpha", 2, {206, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 886 "src/html/html_unescape.gperf" + {"leftharpoonup", 3, {226, 134, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 317 "src/html/html_unescape.gperf" + {"cularrp", 3, {226, 164, 189}}, + {(char*)0}, +#line 1566 "src/html/html_unescape.gperf" + {"RightArrowLeftArrow", 3, {226, 135, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1995 "src/html/html_unescape.gperf" + {"varsigma", 2, {207, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1288 "src/html/html_unescape.gperf" + {"numero", 3, {226, 132, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 552 "src/html/html_unescape.gperf" + {"ffllig", 3, {239, 172, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 985 "src/html/html_unescape.gperf" + {"LowerLeftArrow", 3, {226, 134, 153}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 543 "src/html/html_unescape.gperf" + {"expectation", 3, {226, 132, 176}}, + {(char*)0}, +#line 1314 "src/html/html_unescape.gperf" + {"Ocirc", 2, {195, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2091 "src/html/html_unescape.gperf" + {"yacy", 2, {209, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 824 "src/html/html_unescape.gperf" + {"lambda", 2, {206, 187}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1221 "src/html/html_unescape.gperf" + {"NotSucceedsEqual", 3, {226, 170, 176}}, +#line 191 "src/html/html_unescape.gperf" + {"boxvR", 3, {226, 149, 158}}, + {(char*)0}, +#line 124 "src/html/html_unescape.gperf" + {"bigtriangledown", 3, {226, 150, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 41 "src/html/html_unescape.gperf" + {"ang", 3, {226, 136, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2084 "src/html/html_unescape.gperf" + {"xuplus", 3, {226, 168, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1075 "src/html/html_unescape.gperf" + {"nabla", 3, {226, 136, 135}}, +#line 186 "src/html/html_unescape.gperf" + {"boxvl", 3, {226, 148, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 533 "src/html/html_unescape.gperf" + {"Eta", 2, {206, 151}}, + {(char*)0}, +#line 17 "src/html/html_unescape.gperf" + {"Acy", 2, {208, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 806 "src/html/html_unescape.gperf" + {"kcy", 2, {208, 186}}, +#line 602 "src/html/html_unescape.gperf" + {"gcy", 2, {208, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 894 "src/html/html_unescape.gperf" + {"LeftRightVector", 3, {226, 165, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 231 "src/html/html_unescape.gperf" + {"ccedil", 2, {195, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 91 "src/html/html_unescape.gperf" + {"Backslash", 3, {226, 136, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 703 "src/html/html_unescape.gperf" + {"hslash", 3, {226, 132, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1394 "src/html/html_unescape.gperf" + {"Pcy", 2, {208, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 601 "src/html/html_unescape.gperf" + {"Gcy", 2, {208, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 660 "src/html/html_unescape.gperf" + {"gtquest", 3, {226, 169, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 823 "src/html/html_unescape.gperf" + {"Lambda", 2, {206, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1322 "src/html/html_unescape.gperf" + {"odiv", 3, {226, 168, 184}}, + {(char*)0}, +#line 885 "src/html/html_unescape.gperf" + {"leftharpoondown", 3, {226, 134, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 972 "src/html/html_unescape.gperf" + {"longmapsto", 3, {226, 159, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 798 "src/html/html_unescape.gperf" + {"Jukcy", 2, {208, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 867 "src/html/html_unescape.gperf" + {"ldrdhar", 3, {226, 165, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2085 "src/html/html_unescape.gperf" + {"xutri", 3, {226, 150, 179}}, +#line 1246 "src/html/html_unescape.gperf" + {"nRightarrow", 3, {226, 135, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 545 "src/html/html_unescape.gperf" + {"ExponentialE", 3, {226, 133, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1245 "src/html/html_unescape.gperf" + {"nrightarrow", 3, {226, 134, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 14 "src/html/html_unescape.gperf" + {"Acirc", 2, {195, 130}}, +#line 1164 "src/html/html_unescape.gperf" + {"NoBreak", 3, {226, 129, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 600 "src/html/html_unescape.gperf" + {"gcirc", 2, {196, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 42 "src/html/html_unescape.gperf" + {"ange", 3, {226, 166, 164}}, +#line 328 "src/html/html_unescape.gperf" + {"curarrm", 3, {226, 164, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1671 "src/html/html_unescape.gperf" + {"SHCHcy", 2, {208, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2107 "src/html/html_unescape.gperf" + {"yuml", 2, {195, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1760 "src/html/html_unescape.gperf" + {"subnE", 3, {226, 171, 139}}, + {(char*)0}, {(char*)0}, +#line 360 "src/html/html_unescape.gperf" + {"DDotrahd", 3, {226, 164, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1629 "src/html/html_unescape.gperf" + {"RuleDelayed", 3, {226, 167, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 599 "src/html/html_unescape.gperf" + {"Gcirc", 2, {196, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 796 "src/html/html_unescape.gperf" + {"Jsercy", 2, {208, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 653 "src/html/html_unescape.gperf" + {"gtcc", 3, {226, 170, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 782 "src/html/html_unescape.gperf" + {"iukcy", 2, {209, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1951 "src/html/html_unescape.gperf" + {"updownarrow", 3, {226, 134, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 331 "src/html/html_unescape.gperf" + {"curlyvee", 3, {226, 139, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 550 "src/html/html_unescape.gperf" + {"ffilig", 3, {239, 172, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2100 "src/html/html_unescape.gperf" + {"yicy", 2, {209, 151}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 390 "src/html/html_unescape.gperf" + {"divonx", 3, {226, 139, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 661 "src/html/html_unescape.gperf" + {"gtrapprox", 3, {226, 170, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1755 "src/html/html_unescape.gperf" + {"subdot", 3, {226, 170, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 891 "src/html/html_unescape.gperf" + {"leftrightarrows", 3, {226, 135, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 83 "src/html/html_unescape.gperf" + {"auml", 2, {195, 164}}, + {(char*)0}, {(char*)0}, +#line 1953 "src/html/html_unescape.gperf" + {"Updownarrow", 3, {226, 135, 149}}, + {(char*)0}, +#line 1576 "src/html/html_unescape.gperf" + {"rightleftarrows", 3, {226, 135, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 437 "src/html/html_unescape.gperf" + {"DownRightVector", 3, {226, 135, 129}}, + {(char*)0}, {(char*)0}, +#line 436 "src/html/html_unescape.gperf" + {"DownRightVectorBar", 3, {226, 165, 151}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 683 "src/html/html_unescape.gperf" + {"hcirc", 2, {196, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1614 "src/html/html_unescape.gperf" + {"Rrightarrow", 3, {226, 135, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 973 "src/html/html_unescape.gperf" + {"longrightarrow", 3, {226, 159, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 324 "src/html/html_unescape.gperf" + {"cupdot", 3, {226, 138, 141}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 11 "src/html/html_unescape.gperf" + {"ac", 3, {226, 136, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 696 "src/html/html_unescape.gperf" + {"hookrightarrow", 3, {226, 134, 170}}, + {(char*)0}, {(char*)0}, +#line 1108 "src/html/html_unescape.gperf" + {"NegativeThickSpace", 3, {226, 128, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1756 "src/html/html_unescape.gperf" + {"subE", 3, {226, 171, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1901 "src/html/html_unescape.gperf" + {"twoheadrightarrow", 3, {226, 134, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 430 "src/html/html_unescape.gperf" + {"downharpoonright", 3, {226, 135, 130}}, +#line 429 "src/html/html_unescape.gperf" + {"downharpoonleft", 3, {226, 135, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 20 "src/html/html_unescape.gperf" + {"aelig", 2, {195, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1535 "src/html/html_unescape.gperf" + {"rdldhar", 3, {226, 165, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 332 "src/html/html_unescape.gperf" + {"curlywedge", 3, {226, 139, 143}}, + {(char*)0}, +#line 708 "src/html/html_unescape.gperf" + {"hybull", 3, {226, 129, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1757 "src/html/html_unescape.gperf" + {"sube", 3, {226, 138, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 975 "src/html/html_unescape.gperf" + {"Longrightarrow", 3, {226, 159, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 240 "src/html/html_unescape.gperf" + {"Cedilla", 2, {194, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1189 "src/html/html_unescape.gperf" + {"notinva", 3, {226, 136, 137}}, +#line 1778 "src/html/html_unescape.gperf" + {"SucceedsEqual", 3, {226, 170, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 888 "src/html/html_unescape.gperf" + {"leftrightarrow", 3, {226, 134, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1750 "src/html/html_unescape.gperf" + {"straightepsilon", 2, {207, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 32 "src/html/html_unescape.gperf" + {"amalg", 3, {226, 168, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 81 "src/html/html_unescape.gperf" + {"atilde", 2, {195, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1568 "src/html/html_unescape.gperf" + {"RightCeiling", 3, {226, 140, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 890 "src/html/html_unescape.gperf" + {"Leftrightarrow", 3, {226, 135, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1771 "src/html/html_unescape.gperf" + {"subsim", 3, {226, 171, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2023 "src/html/html_unescape.gperf" + {"VerticalLine", 1, {124}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1590 "src/html/html_unescape.gperf" + {"RightUpVector", 3, {226, 134, 190}}, + {(char*)0}, {(char*)0}, +#line 1589 "src/html/html_unescape.gperf" + {"RightUpVectorBar", 3, {226, 165, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1572 "src/html/html_unescape.gperf" + {"RightDownVector", 3, {226, 135, 130}}, + {(char*)0}, {(char*)0}, +#line 1571 "src/html/html_unescape.gperf" + {"RightDownVectorBar", 3, {226, 165, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 26 "src/html/html_unescape.gperf" + {"alefsym", 3, {226, 132, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 256 "src/html/html_unescape.gperf" + {"circlearrowright", 3, {226, 134, 187}}, +#line 255 "src/html/html_unescape.gperf" + {"circlearrowleft", 3, {226, 134, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 781 "src/html/html_unescape.gperf" + {"Iukcy", 2, {208, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1377 "src/html/html_unescape.gperf" + {"otimesas", 3, {226, 168, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 754 "src/html/html_unescape.gperf" + {"intercal", 3, {226, 138, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1846 "src/html/html_unescape.gperf" + {"thickapprox", 3, {226, 137, 136}}, + {(char*)0}, {(char*)0}, +#line 799 "src/html/html_unescape.gperf" + {"jukcy", 2, {209, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1204 "src/html/html_unescape.gperf" + {"notniva", 3, {226, 136, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1444 "src/html/html_unescape.gperf" + {"precnapprox", 3, {226, 170, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 336 "src/html/html_unescape.gperf" + {"cuvee", 3, {226, 139, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 73 "src/html/html_unescape.gperf" + {"aring", 2, {195, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 233 "src/html/html_unescape.gperf" + {"ccirc", 2, {196, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1563 "src/html/html_unescape.gperf" + {"rightarrow", 3, {226, 134, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 753 "src/html/html_unescape.gperf" + {"Integral", 3, {226, 136, 171}}, +#line 2061 "src/html/html_unescape.gperf" + {"xcirc", 3, {226, 151, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 797 "src/html/html_unescape.gperf" + {"jsercy", 2, {209, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 250 "src/html/html_unescape.gperf" + {"checkmark", 3, {226, 156, 147}}, + {(char*)0}, +#line 2025 "src/html/html_unescape.gperf" + {"VerticalTilde", 3, {226, 137, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 183 "src/html/html_unescape.gperf" + {"boxvH", 3, {226, 149, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1211 "src/html/html_unescape.gperf" + {"NotRightTriangleBar", 3, {226, 167, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1213 "src/html/html_unescape.gperf" + {"NotRightTriangleEqual", 3, {226, 139, 173}}, +#line 1212 "src/html/html_unescape.gperf" + {"NotRightTriangle", 3, {226, 139, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 906 "src/html/html_unescape.gperf" + {"LeftVectorBar", 3, {226, 165, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 182 "src/html/html_unescape.gperf" + {"boxvh", 3, {226, 148, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 150 "src/html/html_unescape.gperf" + {"boxbox", 3, {226, 167, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2095 "src/html/html_unescape.gperf" + {"ycy", 2, {209, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1758 "src/html/html_unescape.gperf" + {"subedot", 3, {226, 171, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1707 "src/html/html_unescape.gperf" + {"SOFTcy", 2, {208, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1565 "src/html/html_unescape.gperf" + {"Rightarrow", 3, {226, 135, 146}}, + {(char*)0}, +#line 29 "src/html/html_unescape.gperf" + {"alpha", 2, {206, 177}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1672 "src/html/html_unescape.gperf" + {"shchcy", 2, {209, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1708 "src/html/html_unescape.gperf" + {"softcy", 2, {209, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 18 "src/html/html_unescape.gperf" + {"acy", 2, {208, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2093 "src/html/html_unescape.gperf" + {"ycirc", 2, {197, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 117 "src/html/html_unescape.gperf" + {"bigcirc", 3, {226, 151, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 736 "src/html/html_unescape.gperf" + {"ImaginaryI", 3, {226, 133, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 70 "src/html/html_unescape.gperf" + {"approx", 3, {226, 137, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1801 "src/html/html_unescape.gperf" + {"SupersetEqual", 3, {226, 138, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2043 "src/html/html_unescape.gperf" + {"vzigzag", 3, {226, 166, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 315 "src/html/html_unescape.gperf" + {"cuesc", 3, {226, 139, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1939 "src/html/html_unescape.gperf" + {"UnderParenthesis", 3, {226, 143, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 15 "src/html/html_unescape.gperf" + {"acirc", 2, {195, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1774 "src/html/html_unescape.gperf" + {"succapprox", 3, {226, 170, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1040 "src/html/html_unescape.gperf" + {"mcomma", 3, {226, 168, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 48 "src/html/html_unescape.gperf" + {"angmsdae", 3, {226, 166, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 45 "src/html/html_unescape.gperf" + {"angmsdab", 3, {226, 166, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 49 "src/html/html_unescape.gperf" + {"angmsdaf", 3, {226, 166, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 56 "src/html/html_unescape.gperf" + {"angsph", 3, {226, 136, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1026 "src/html/html_unescape.gperf" + {"luruhar", 3, {226, 165, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 47 "src/html/html_unescape.gperf" + {"angmsdad", 3, {226, 166, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1900 "src/html/html_unescape.gperf" + {"twoheadleftarrow", 3, {226, 134, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 340 "src/html/html_unescape.gperf" + {"cylcty", 3, {226, 140, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1751 "src/html/html_unescape.gperf" + {"straightphi", 2, {207, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1073 "src/html/html_unescape.gperf" + {"multimap", 3, {226, 138, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1562 "src/html/html_unescape.gperf" + {"RightArrowBar", 3, {226, 135, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 868 "src/html/html_unescape.gperf" + {"ldrushar", 3, {226, 165, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 872 "src/html/html_unescape.gperf" + {"LeftAngleBracket", 3, {226, 159, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1630 "src/html/html_unescape.gperf" + {"ruluhar", 3, {226, 165, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 329 "src/html/html_unescape.gperf" + {"curlyeqprec", 3, {226, 139, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2106 "src/html/html_unescape.gperf" + {"yucy", 2, {209, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1025 "src/html/html_unescape.gperf" + {"lurdshar", 3, {226, 165, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 675 "src/html/html_unescape.gperf" + {"hardcy", 2, {209, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1574 "src/html/html_unescape.gperf" + {"rightharpoondown", 3, {226, 135, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1575 "src/html/html_unescape.gperf" + {"rightharpoonup", 3, {226, 135, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 674 "src/html/html_unescape.gperf" + {"HARDcy", 2, {208, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1768 "src/html/html_unescape.gperf" + {"SubsetEqual", 3, {226, 138, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 385 "src/html/html_unescape.gperf" + {"digamma", 2, {207, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1918 "src/html/html_unescape.gperf" + {"udblac", 2, {197, 177}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1786 "src/html/html_unescape.gperf" + {"SuchThat", 3, {226, 136, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 337 "src/html/html_unescape.gperf" + {"cuwed", 3, {226, 139, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1917 "src/html/html_unescape.gperf" + {"Udblac", 2, {197, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 50 "src/html/html_unescape.gperf" + {"angmsdag", 3, {226, 166, 174}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 51 "src/html/html_unescape.gperf" + {"angmsdah", 3, {226, 166, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2022 "src/html/html_unescape.gperf" + {"VerticalBar", 3, {226, 136, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2024 "src/html/html_unescape.gperf" + {"VerticalSeparator", 3, {226, 157, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1567 "src/html/html_unescape.gperf" + {"rightarrowtail", 3, {226, 134, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1321 "src/html/html_unescape.gperf" + {"odblac", 2, {197, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1782 "src/html/html_unescape.gperf" + {"succnapprox", 3, {226, 170, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 46 "src/html/html_unescape.gperf" + {"angmsdac", 3, {226, 166, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1320 "src/html/html_unescape.gperf" + {"Odblac", 2, {197, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 318 "src/html/html_unescape.gperf" + {"cupbrcap", 3, {226, 169, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 44 "src/html/html_unescape.gperf" + {"angmsdaa", 3, {226, 166, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 330 "src/html/html_unescape.gperf" + {"curlyeqsucc", 3, {226, 139, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 334 "src/html/html_unescape.gperf" + {"curvearrowleft", 3, {226, 134, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 335 "src/html/html_unescape.gperf" + {"curvearrowright", 3, {226, 134, 183}} + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = hash_entity (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + if (len == lengthtable[key]) + { + register const char *s = wordlist[key].entity; + + if (s && *str == *s && !memcmp (str + 1, s + 1, len - 1)) + return &wordlist[key]; + } + } + return 0; +} diff --git a/src/inlines.c b/src/inlines.c index f75c846..71d75e9 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -1,251 +1,216 @@ #include <stdlib.h> +#include <string.h> #include <stdio.h> #include <stdbool.h> #include <ctype.h> -#include "bstrlib.h" + #include "stmd.h" -#include "uthash.h" -#include "debug.h" -#include "scanners.h" +#include "html/houdini.h" #include "utf8.h" +#include "scanners.h" +#include "inlines.h" + +typedef struct Subject { + chunk input; + int pos; + int label_nestlevel; + reference_map *refmap; +} subject; + +static node_inl *parse_chunk_inlines(chunk *chunk, reference_map *refmap); +static node_inl *parse_inlines_while(subject* subj, int (*f)(subject*)); +static int parse_inline(subject* subj, node_inl ** last); -extern void free_reference(reference *ref) { - bdestroy(ref->label); - bdestroy(ref->url); - bdestroy(ref->title); - free(ref); -} - -extern void free_reference_map(reference **refmap) { - /* free the hash table contents */ - reference *s; - reference *tmp; - if (refmap != NULL) { - HASH_ITER(hh, *refmap, s, tmp) { - HASH_DEL(*refmap, s); - free_reference(s); - } - free(refmap); - } -} - -// normalize reference: collapse internal whitespace to single space, -// remove leading/trailing whitespace, case fold -static bstring normalize_reference(bstring s) -{ - bstring normalized = case_fold(s); - int pos = 0; - int startpos; - char c; - while ((c = bchar(normalized, pos))) { - if (isspace(c)) { - startpos = pos; - // skip til next non-space - pos++; - while (isspace(bchar(s, pos))) { - pos++; - } - bdelete(normalized, startpos, pos - startpos); - binsertch(normalized, startpos, 1, ' '); - pos = startpos + 1; - } - pos++; - } - btrimws(normalized); - return normalized; -} - -// Returns reference if refmap contains a reference with matching -// label, otherwise NULL. -extern reference* lookup_reference(reference** refmap, bstring lab) -{ - reference * ref = NULL; - bstring label = normalize_reference(lab); - if (refmap != NULL) { - HASH_FIND_STR(*refmap, (char*) label->data, ref); - } - bdestroy(label); - return ref; -} - -extern reference* make_reference(bstring label, bstring url, bstring title) -{ - reference * ref; - ref = malloc(sizeof(reference)); - ref->label = normalize_reference(label); - ref->url = bstrcpy(url); - ref->title = bstrcpy(title); - return ref; -} - -extern void add_reference(reference** refmap, reference* ref) -{ - reference * t = NULL; - HASH_FIND(hh, *refmap, (char*) ref->label->data, - (unsigned) blength(ref->label), t); - if (t == NULL) { - HASH_ADD_KEYPTR(hh, *refmap, (char*) ref->label->data, - (unsigned) blength(ref->label), ref); - } else { - free_reference(ref); // we free this now since it won't be in the refmap - } +static void subject_from_chunk(subject *e, chunk *chunk, reference_map *refmap); +static void subject_from_buf(subject *e, strbuf *buffer, reference_map *refmap); +static int subject_find_special_char(subject *subj); + +static unsigned char *bufdup(const unsigned char *buf) +{ + unsigned char *new = NULL; + + if (buf) { + int len = strlen((char *)buf); + new = malloc(len + 1); + memcpy(new, buf, len + 1); + } + + return new; +} + +static inline node_inl *make_link_(node_inl *label, unsigned char *url, unsigned char *title) +{ + node_inl* e = (node_inl*) malloc(sizeof(node_inl)); + e->tag = INL_LINK; + e->content.linkable.label = label; + e->content.linkable.url = url; + e->content.linkable.title = title; + e->next = NULL; + return e; +} + +inline static node_inl* make_ref_link(node_inl* label, reference *ref) +{ + return make_link_(label, bufdup(ref->url), bufdup(ref->title)); +} + +inline static node_inl* make_autolink(node_inl* label, chunk url, int is_email) +{ + return make_link_(label, clean_autolink(&url, is_email), NULL); } // Create an inline with a linkable string value. -inline static inl* make_linkable(int t, inl* label, bstring url, bstring title) +inline static node_inl* make_link(node_inl* label, chunk url, chunk title) { - inl* e = (inl*) malloc(sizeof(inl)); - e->tag = t; - e->content.linkable.label = label; - e->content.linkable.url = url; - e->content.linkable.title = title; - e->next = NULL; - return e; + return make_link_(label, clean_url(&url), clean_title(&title)); } -inline static inl* make_inlines(int t, inl* contents) +inline static node_inl* make_inlines(int t, node_inl* contents) { - inl* e = (inl*) malloc(sizeof(inl)); - e->tag = t; - e->content.inlines = contents; - e->next = NULL; - return e; + node_inl* e = (node_inl*) malloc(sizeof(node_inl)); + e->tag = t; + e->content.inlines = contents; + e->next = NULL; + return e; } // Create an inline with a literal string value. -inline static inl* make_literal(int t, bstring s) +inline static node_inl* make_literal(int t, chunk s) { - inl* e = (inl*) malloc(sizeof(inl)); - e->tag = t; - e->content.literal = s; - e->next = NULL; - return e; + node_inl* e = (node_inl*) malloc(sizeof(node_inl)); + e->tag = t; + e->content.literal = s; + e->next = NULL; + return e; } // Create an inline with no value. -inline static inl* make_simple(int t) +inline static node_inl* make_simple(int t) { - inl* e = (inl*) malloc(sizeof(inl)); - e->tag = t; - e->next = NULL; - return e; + node_inl* e = (node_inl*) malloc(sizeof(node_inl)); + e->tag = t; + e->next = NULL; + return e; } // Macros for creating various kinds of inlines. -#define make_str(s) make_literal(str, s) -#define make_code(s) make_literal(code, s) -#define make_raw_html(s) make_literal(raw_html, s) -#define make_entity(s) make_literal(entity, s) -#define make_linebreak() make_simple(linebreak) -#define make_softbreak() make_simple(softbreak) -#define make_link(label, url, title) make_linkable(link, label, url, title) -#define make_image(alt, url, title) make_linkable(image, alt, url, title) -#define make_emph(contents) make_inlines(emph, contents) -#define make_strong(contents) make_inlines(strong, contents) +#define make_str(s) make_literal(INL_STRING, s) +#define make_code(s) make_literal(INL_CODE, s) +#define make_raw_html(s) make_literal(INL_RAW_HTML, s) +#define make_linebreak() make_simple(INL_LINEBREAK) +#define make_softbreak() make_simple(INL_SOFTBREAK) +#define make_emph(contents) make_inlines(INL_EMPH, contents) +#define make_strong(contents) make_inlines(INL_STRONG, contents) // Free an inline list. -extern void free_inlines(inl* e) -{ - inl * next; - while (e != NULL) { - switch (e->tag){ - case str: - case raw_html: - case code: - case entity: - bdestroy(e->content.literal); - break; - case linebreak: - case softbreak: - break; - case link: - case image: - bdestroy(e->content.linkable.url); - bdestroy(e->content.linkable.title); - free_inlines(e->content.linkable.label); - break; - case emph: - case strong: - free_inlines(e->content.inlines); - break; - default: - break; - } - next = e->next; - free(e); - e = next; - } +extern void free_inlines(node_inl* e) +{ + node_inl * next; + while (e != NULL) { + switch (e->tag){ + case INL_STRING: + case INL_RAW_HTML: + case INL_CODE: + chunk_free(&e->content.literal); + break; + case INL_LINEBREAK: + case INL_SOFTBREAK: + break; + case INL_LINK: + case INL_IMAGE: + free(e->content.linkable.url); + free(e->content.linkable.title); + free_inlines(e->content.linkable.label); + break; + case INL_EMPH: + case INL_STRONG: + free_inlines(e->content.inlines); + break; + default: + break; + } + next = e->next; + free(e); + e = next; + } } // Append inline list b to the end of inline list a. // Return pointer to head of new list. -inline static inl* append_inlines(inl* a, inl* b) +inline static node_inl* append_inlines(node_inl* a, node_inl* b) { - if (a == NULL) { // NULL acts like an empty list - return b; - } - inl* cur = a; - while (cur->next) { - cur = cur->next; - } - cur->next = b; - return a; + if (a == NULL) { // NULL acts like an empty list + return b; + } + node_inl* cur = a; + while (cur->next) { + cur = cur->next; + } + cur->next = b; + return a; } -// Make a 'subject' from an input string. -static subject* make_subject(bstring s, reference** refmap) +static void subject_from_buf(subject *e, strbuf *buffer, reference_map *refmap) { - subject* e = (subject*) malloc(sizeof(subject)); - // remove final whitespace - brtrimws(s); - e->buffer = s; - e->pos = 0; - e->label_nestlevel = 0; - e->reference_map = refmap; - return e; + e->input.data = buffer->ptr; + e->input.len = buffer->size; + e->input.alloc = 0; + e->pos = 0; + e->label_nestlevel = 0; + e->refmap = refmap; + + chunk_rtrim(&e->input); +} + +static void subject_from_chunk(subject *e, chunk *chunk, reference_map *refmap) +{ + e->input.data = chunk->data; + e->input.len = chunk->len; + e->input.alloc = 0; + e->pos = 0; + e->label_nestlevel = 0; + e->refmap = refmap; + + chunk_rtrim(&e->input); } inline static int isbacktick(int c) { - return (c == '`'); + return (c == '`'); } -// Return the next character in the subject, without advancing. -// Return 0 if at the end of the subject. -#define peek_char(subj) bchar(subj->buffer, subj->pos) +static inline unsigned char peek_char(subject *subj) +{ + return (subj->pos < subj->input.len) ? subj->input.data[subj->pos] : 0; +} + +static inline unsigned char peek_at(subject *subj, int pos) +{ + return subj->input.data[pos]; +} // Return true if there are more characters in the subject. inline static int is_eof(subject* subj) { - return (subj->pos >= blength(subj->buffer)); + return (subj->pos >= subj->input.len); } // Advance the subject. Doesn't check for eof. -#define advance(subj) subj->pos += 1 +#define advance(subj) (subj)->pos += 1 // Take characters while a predicate holds, and return a string. -inline static bstring take_while(subject* subj, int (*f)(int)) +inline static chunk take_while(subject* subj, int (*f)(int)) { - unsigned char c; - int startpos = subj->pos; - int len = 0; - while ((c = peek_char(subj)) && (*f)(c)) { - advance(subj); - len++; - } - return bmidstr(subj->buffer, startpos, len); -} + unsigned char c; + int startpos = subj->pos; + int len = 0; -// Take one character and return a string, or NULL if eof. -inline static bstring take_one(subject* subj) -{ - int startpos = subj->pos; - if (is_eof(subj)){ - return NULL; - } else { - advance(subj); - return bmidstr(subj->buffer, startpos, 1); - } + while ((c = peek_char(subj)) && (*f)(c)) { + advance(subj); + len++; + } + + return chunk_dup(&subj->input, startpos, len); } // Try to process a backtick code span that began with a @@ -255,381 +220,353 @@ inline static bstring take_one(subject* subj) // after the closing backticks. static int scan_to_closing_backticks(subject* subj, int openticklength) { - // read non backticks - char c; - while ((c = peek_char(subj)) && c != '`') { - advance(subj); - } - if (is_eof(subj)) { - return 0; // did not find closing ticks, return 0 - } - int numticks = 0; - while (peek_char(subj) == '`') { - advance(subj); - numticks++; - } - if (numticks != openticklength){ - return(scan_to_closing_backticks(subj, openticklength)); - } - return (subj->pos); -} - -// Destructively modify bstring, collapsing consecutive -// space and newline characters into a single space. -static int normalize_whitespace(bstring s) -{ - bool last_char_was_space = false; - int pos = 0; - char c; - while ((c = bchar(s, pos))) { - switch (c) { - case ' ': - if (last_char_was_space) { - bdelete(s, pos, 1); - } else { - pos++; - } - last_char_was_space = true; - break; - case '\n': - if (last_char_was_space) { - bdelete(s, pos, 1); - } else { - bdelete(s, pos, 1); - binsertch(s, pos, 1, ' '); - pos++; - } - last_char_was_space = true; - break; - default: - pos++; - last_char_was_space = false; - } - } - return 0; + // read non backticks + char c; + while ((c = peek_char(subj)) && c != '`') { + advance(subj); + } + if (is_eof(subj)) { + return 0; // did not find closing ticks, return 0 + } + int numticks = 0; + while (peek_char(subj) == '`') { + advance(subj); + numticks++; + } + if (numticks != openticklength){ + return(scan_to_closing_backticks(subj, openticklength)); + } + return (subj->pos); } // Parse backtick code section or raw backticks, return an inline. // Assumes that the subject has a backtick at the current position. -static inl* handle_backticks(subject *subj) -{ - bstring openticks = take_while(subj, isbacktick); - bstring result; - int ticklength = blength(openticks); - int startpos = subj->pos; - int endpos = scan_to_closing_backticks(subj, ticklength); - if (endpos == 0) { // not found - subj->pos = startpos; // rewind - return make_str(openticks); - } else { - bdestroy(openticks); - result = bmidstr(subj->buffer, startpos, endpos - startpos - ticklength); - btrimws(result); - normalize_whitespace(result); - return make_code(result); - } +static node_inl* handle_backticks(subject *subj) +{ + chunk openticks = take_while(subj, isbacktick); + int startpos = subj->pos; + int endpos = scan_to_closing_backticks(subj, openticks.len); + + if (endpos == 0) { // not found + subj->pos = startpos; // rewind + return make_str(openticks); + } else { + strbuf buf = GH_BUF_INIT; + + strbuf_set(&buf, subj->input.data + startpos, endpos - startpos - openticks.len); + strbuf_trim(&buf); + strbuf_normalize_whitespace(&buf); + + return make_code(chunk_buf_detach(&buf)); + } } // Scan ***, **, or * and return number scanned, or 0. // Don't advance position. static int scan_delims(subject* subj, char c, bool * can_open, bool * can_close) { - int numdelims = 0; - char char_before, char_after; - int startpos = subj->pos; - - char_before = subj->pos == 0 ? '\n' : bchar(subj->buffer, subj->pos - 1); - while (peek_char(subj) == c) { - numdelims++; - advance(subj); - } - char_after = peek_char(subj); - *can_open = numdelims > 0 && numdelims <= 3 && !isspace(char_after); - *can_close = numdelims > 0 && numdelims <= 3 && !isspace(char_before); - if (c == '_') { - *can_open = *can_open && !isalnum(char_before); - *can_close = *can_close && !isalnum(char_after); - } - subj->pos = startpos; - return numdelims; + int numdelims = 0; + char char_before, char_after; + int startpos = subj->pos; + + char_before = subj->pos == 0 ? '\n' : peek_at(subj, subj->pos - 1); + while (peek_char(subj) == c) { + numdelims++; + advance(subj); + } + char_after = peek_char(subj); + *can_open = numdelims > 0 && numdelims <= 3 && !isspace(char_after); + *can_close = numdelims > 0 && numdelims <= 3 && !isspace(char_before); + if (c == '_') { + *can_open = *can_open && !isalnum(char_before); + *can_close = *can_close && !isalnum(char_after); + } + subj->pos = startpos; + return numdelims; } // Parse strong/emph or a fallback. // Assumes the subject has '_' or '*' at the current position. -static inl* handle_strong_emph(subject* subj, char c) -{ - bool can_open, can_close; - inl * result = NULL; - inl ** last = malloc(sizeof(inl *)); - inl * new; - inl * il; - inl * first_head = NULL; - inl * first_close = NULL; - int first_close_delims = 0; - int numdelims; - - *last = NULL; - - numdelims = scan_delims(subj, c, &can_open, &can_close); - subj->pos += numdelims; - - new = make_str(bmidstr(subj->buffer, subj->pos - numdelims, numdelims)); - *last = new; - first_head = new; - result = new; - - if (!can_open || numdelims == 0) { - goto done; - } - - switch (numdelims) { - case 1: - while (true) { - numdelims = scan_delims(subj, c, &can_open, &can_close); - if (numdelims >= 1 && can_close) { - subj->pos += 1; - first_head->tag = emph; - bdestroy(first_head->content.literal); - first_head->content.inlines = first_head->next; - first_head->next = NULL; - goto done; - } else { - if (!parse_inline(subj, last)) { - goto done; - } - } - } - break; - case 2: - while (true) { - numdelims = scan_delims(subj, c, &can_open, &can_close); - if (numdelims >= 2 && can_close) { - subj->pos += 2; - first_head->tag = strong; - bdestroy(first_head->content.literal); - first_head->content.inlines = first_head->next; - first_head->next = NULL; - goto done; - } else { - if (!parse_inline(subj, last)) { - goto done; - } - } - } - break; - case 3: - while (true) { - numdelims = scan_delims(subj, c, &can_open, &can_close); - if (can_close && numdelims >= 1 && numdelims <= 3 && - numdelims != first_close_delims) { - new = make_str(bmidstr(subj->buffer, subj->pos, numdelims)); - append_inlines(*last, new); - *last = new; - - if (first_close_delims == 1 && numdelims > 2) { - numdelims = 2; - } else if (first_close_delims == 2) { - numdelims = 1; - } else if (numdelims == 3) { - // If we opened with ***, we interpret it as ** followed by * - // giving us <strong><em> - numdelims = 1; - } - - subj->pos += numdelims; - if (first_close) { - first_head->tag = first_close_delims == 1 ? strong : emph; - bdestroy(first_head->content.literal); - first_head->content.inlines = - make_inlines(first_close_delims == 1 ? emph : strong, - first_head->next); - - il = first_head->next; - while (il->next && il->next != first_close) { - il = il->next; - } - il->next = NULL; - - first_head->content.inlines->next = first_close->next; - - il = first_head->content.inlines; - while (il->next && il->next != *last) { - il = il->next; - } - il->next = NULL; - free_inlines(*last); - - first_close->next = NULL; - free_inlines(first_close); - first_head->next = NULL; - goto done; - } else { - first_close = *last; - first_close_delims = numdelims; - } - } else { - if (!parse_inline(subj, last)) { - goto done; - } - } - } - break; - default: - goto done; - } - - done: - free(last); - return result; +static node_inl* handle_strong_emph(subject* subj, char c) +{ + bool can_open, can_close; + node_inl * result = NULL; + node_inl ** last = malloc(sizeof(node_inl *)); + node_inl * new; + node_inl * il; + node_inl * first_head = NULL; + node_inl * first_close = NULL; + int first_close_delims = 0; + int numdelims; + + *last = NULL; + + numdelims = scan_delims(subj, c, &can_open, &can_close); + subj->pos += numdelims; + + new = make_str(chunk_dup(&subj->input, subj->pos - numdelims, numdelims)); + *last = new; + first_head = new; + result = new; + + if (!can_open || numdelims == 0) { + goto done; + } + + switch (numdelims) { + case 1: + while (true) { + numdelims = scan_delims(subj, c, &can_open, &can_close); + if (numdelims >= 1 && can_close) { + subj->pos += 1; + first_head->tag = INL_EMPH; + chunk_free(&first_head->content.literal); + first_head->content.inlines = first_head->next; + first_head->next = NULL; + goto done; + } else { + if (!parse_inline(subj, last)) { + goto done; + } + } + } + break; + case 2: + while (true) { + numdelims = scan_delims(subj, c, &can_open, &can_close); + if (numdelims >= 2 && can_close) { + subj->pos += 2; + first_head->tag = INL_STRONG; + chunk_free(&first_head->content.literal); + first_head->content.inlines = first_head->next; + first_head->next = NULL; + goto done; + } else { + if (!parse_inline(subj, last)) { + goto done; + } + } + } + break; + case 3: + while (true) { + numdelims = scan_delims(subj, c, &can_open, &can_close); + if (can_close && numdelims >= 1 && numdelims <= 3 && + numdelims != first_close_delims) { + new = make_str(chunk_dup(&subj->input, subj->pos, numdelims)); + append_inlines(*last, new); + *last = new; + if (first_close_delims == 1 && numdelims > 2) { + numdelims = 2; + } else if (first_close_delims == 2) { + numdelims = 1; + } else if (numdelims == 3) { + // If we opened with ***, we interpret it as ** followed by * + // giving us <strong><em> + numdelims = 1; + } + subj->pos += numdelims; + if (first_close) { + first_head->tag = first_close_delims == 1 ? INL_STRONG : INL_EMPH; + chunk_free(&first_head->content.literal); + first_head->content.inlines = + make_inlines(first_close_delims == 1 ? INL_EMPH : INL_STRONG, + first_head->next); + + il = first_head->next; + while (il->next && il->next != first_close) { + il = il->next; + } + il->next = NULL; + + first_head->content.inlines->next = first_close->next; + + il = first_head->content.inlines; + while (il->next && il->next != *last) { + il = il->next; + } + il->next = NULL; + free_inlines(*last); + + first_close->next = NULL; + free_inlines(first_close); + first_head->next = NULL; + goto done; + } else { + first_close = *last; + first_close_delims = numdelims; + } + } else { + if (!parse_inline(subj, last)) { + goto done; + } + } + } + break; + default: + goto done; + } + +done: + free(last); + return result; } // Parse backslash-escape or just a backslash, returning an inline. -static inl* handle_backslash(subject *subj) +static node_inl* handle_backslash(subject *subj) { - advance(subj); - unsigned char nextchar = peek_char(subj); - if (ispunct(nextchar)) { // only ascii symbols and newline can be escaped - advance(subj); - return make_str(bformat("%c", nextchar)); - } else if (nextchar == '\n') { - advance(subj); - return make_linebreak(); - } else { - return make_str(bfromcstr("\\")); - } + advance(subj); + unsigned char nextchar = peek_char(subj); + if (ispunct(nextchar)) { // only ascii symbols and newline can be escaped + advance(subj); + return make_str(chunk_dup(&subj->input, subj->pos - 1, 1)); + } else if (nextchar == '\n') { + advance(subj); + return make_linebreak(); + } else { + return make_str(chunk_literal("\\")); + } } // Parse an entity or a regular "&" string. // Assumes the subject has an '&' character at the current position. -static inl* handle_entity(subject* subj) +static node_inl* handle_entity(subject* subj) { - int match; - inl * result; - match = scan_entity(subj->buffer, subj->pos); - if (match) { - result = make_entity(bmidstr(subj->buffer, subj->pos, match)); - subj->pos += match; - } else { - advance(subj); - result = make_str(bfromcstr("&")); - } - return result; + strbuf ent = GH_BUF_INIT; + size_t len; + + advance(subj); + + len = houdini_unescape_ent(&ent, + subj->input.data + subj->pos, + subj->input.len - subj->pos + ); + + if (len == 0) + return make_str(chunk_literal("&")); + + subj->pos += len; + return make_str(chunk_buf_detach(&ent)); } // Like make_str, but parses entities. // Returns an inline sequence consisting of str and entity elements. -static inl * make_str_with_entities(bstring s) -{ - inl * result = NULL; - inl * new; - int searchpos; - char c; - subject * subj = make_subject(s, NULL); - - while ((c = peek_char(subj))) { - switch (c) { - case '&': - new = handle_entity(subj); - break; - default: - searchpos = bstrchrp(subj->buffer, '&', subj->pos); - if (searchpos == BSTR_ERR) { - searchpos = blength(subj->buffer); - } - new = make_str(bmidstr(subj->buffer, subj->pos, searchpos - subj->pos)); - subj->pos = searchpos; - } - result = append_inlines(result, new); - } - free(subj); - return result; -} - -// Destructively unescape a string: remove backslashes before punctuation chars. -extern int unescape(bstring url) -{ - // remove backslashes before punctuation chars: - int searchpos = 0; - while ((searchpos = bstrchrp(url, '\\', searchpos)) != BSTR_ERR) { - if (ispunct(bchar(url, searchpos + 1))) { - bdelete(url, searchpos, 1); - } else { - searchpos++; - } - } - return 0; +static node_inl *make_str_with_entities(chunk *content) +{ + strbuf unescaped = GH_BUF_INIT; + + if (houdini_unescape_html(&unescaped, content->data, (size_t)content->len)) { + return make_str(chunk_buf_detach(&unescaped)); + } else { + return make_str(*content); + } } // Clean a URL: remove surrounding whitespace and surrounding <>, // and remove \ that escape punctuation. -static int clean_url(bstring url) +unsigned char *clean_url(chunk *url) +{ + strbuf buf = GH_BUF_INIT; + + chunk_trim(url); + + if (url->len == 0) + return NULL; + + if (url->data[0] == '<' && url->data[url->len - 1] == '>') { + houdini_unescape_html_f(&buf, url->data + 1, url->len - 2); + } else { + houdini_unescape_html_f(&buf, url->data, url->len); + } + + strbuf_unescape(&buf); + return strbuf_detach(&buf); +} + +unsigned char *clean_autolink(chunk *url, int is_email) { - // remove surrounding <> if any: - int urllength = blength(url); - btrimws(url); - if (bchar(url, 0) == '<' && bchar(url, urllength - 1) == '>') { - bdelete(url, 0, 1); - bdelete(url, urllength - 2, 1); - } - unescape(url); - return 0; + strbuf buf = GH_BUF_INIT; + + chunk_trim(url); + + if (url->len == 0) + return NULL; + + if (is_email) + strbuf_puts(&buf, "mailto:"); + + houdini_unescape_html_f(&buf, url->data, url->len); + return strbuf_detach(&buf); } // Clean a title: remove surrounding quotes and remove \ that escape punctuation. -static int clean_title(bstring title) +unsigned char *clean_title(chunk *title) { - // remove surrounding quotes if any: - int titlelength = blength(title); - if ((bchar(title, 0) == '\'' && bchar(title, titlelength - 1) == '\'') || - (bchar(title, 0) == '(' && bchar(title, titlelength - 1) == ')') || - (bchar(title, 0) == '"' && bchar(title, titlelength - 1) == '"')) { - bdelete(title, 0, 1); - bdelete(title, titlelength - 2, 1); - } - unescape(title); - return 0; + strbuf buf = GH_BUF_INIT; + unsigned char first, last; + + if (title->len == 0) + return NULL; + + first = title->data[0]; + last = title->data[title->len - 1]; + + // remove surrounding quotes if any: + if ((first == '\'' && last == '\'') || + (first == '(' && last == ')') || + (first == '"' && last == '"')) { + houdini_unescape_html_f(&buf, title->data + 1, title->len - 2); + } else { + houdini_unescape_html_f(&buf, title->data, title->len); + } + + strbuf_unescape(&buf); + return strbuf_detach(&buf); } // Parse an autolink or HTML tag. // Assumes the subject has a '<' character at the current position. -static inl* handle_pointy_brace(subject* subj) -{ - int matchlen = 0; - bstring contents; - inl* result; - - advance(subj); // advance past first < - // first try to match a URL autolink - matchlen = scan_autolink_uri(subj->buffer, subj->pos); - if (matchlen > 0) { - contents = bmidstr(subj->buffer, subj->pos, matchlen - 1); - subj->pos += matchlen; - result = make_link(make_str_with_entities(contents), - bstrcpy(contents), bfromcstr("")); - bdestroy(contents); - return result; - } - // next try to match an email autolink - matchlen = scan_autolink_email(subj->buffer, subj->pos); - if (matchlen > 0) { - contents = bmidstr(subj->buffer, subj->pos, matchlen - 1); - subj->pos += matchlen; - result = make_link(make_str_with_entities(contents), - bformat("mailto:%s", contents->data), - bfromcstr("")); - bdestroy(contents); - return result; - } - // finally, try to match an html tag - matchlen = scan_html_tag(subj->buffer, subj->pos); - if (matchlen > 0) { - contents = bmidstr(subj->buffer, subj->pos, matchlen); - binsertch(contents, 0, 1, '<'); - subj->pos += matchlen; - return make_raw_html(contents); - } else {// if nothing matches, just return the opening <: - return make_str(bfromcstr("<")); - } +static node_inl* handle_pointy_brace(subject* subj) +{ + int matchlen = 0; + chunk contents; + + advance(subj); // advance past first < + + // first try to match a URL autolink + matchlen = scan_autolink_uri(&subj->input, subj->pos); + if (matchlen > 0) { + contents = chunk_dup(&subj->input, subj->pos, matchlen - 1); + subj->pos += matchlen; + + return make_autolink( + make_str_with_entities(&contents), + contents, 0 + ); + } + + // next try to match an email autolink + matchlen = scan_autolink_email(&subj->input, subj->pos); + if (matchlen > 0) { + contents = chunk_dup(&subj->input, subj->pos, matchlen - 1); + subj->pos += matchlen; + + return make_autolink( + make_str_with_entities(&contents), + contents, 1 + ); + } + + // finally, try to match an html tag + matchlen = scan_html_tag(&subj->input, subj->pos); + if (matchlen > 0) { + contents = chunk_dup(&subj->input, subj->pos - 1, matchlen + 1); + subj->pos += matchlen; + return make_raw_html(contents); + } + + // if nothing matches, just return the opening <: + return make_str(chunk_literal("<")); } // Parse a link label. Returns 1 if successful. @@ -641,366 +578,384 @@ static inl* handle_pointy_brace(subject* subj) // markers. So, 2 below contains a link while 1 does not: // 1. [a link `with a ](/url)` character // 2. [a link *with emphasized ](/url) text* -static int link_label(subject* subj, bstring* raw_label) -{ - int nestlevel = 0; - inl* tmp = NULL; - bstring raw; - int startpos = subj->pos; - if (subj->label_nestlevel) { - // if we've already checked to the end of the subject - // for a label, even with a different starting [, we - // know we won't find one here and we can just return. - // Note: nestlevel 1 would be: [foo [bar] - // nestlevel 2 would be: [foo [bar [baz] - subj->label_nestlevel--; - return 0; - } - advance(subj); // advance past [ - char c; - while ((c = peek_char(subj)) && (c != ']' || nestlevel > 0)) { - switch (c) { - case '`': - tmp = handle_backticks(subj); - free_inlines(tmp); - break; - case '<': - tmp = handle_pointy_brace(subj); - free_inlines(tmp); - break; - case '[': // nested [] - nestlevel++; - advance(subj); - break; - case ']': // nested [] - nestlevel--; - advance(subj); - break; - case '\\': - advance(subj); - if (ispunct(peek_char(subj))) { - advance(subj); - } - break; - default: - advance(subj); - } - } - if (c == ']') { - if (raw_label != NULL) { - raw = bmidstr(subj->buffer, startpos + 1, subj->pos - (startpos + 1)); - *raw_label = raw; - } - subj->label_nestlevel = 0; - advance(subj); // advance past ] - return 1; - } else { - if (c == 0) { - subj->label_nestlevel = nestlevel; - } - subj->pos = startpos; // rewind - return 0; - } +static int link_label(subject* subj, chunk *raw_label) +{ + int nestlevel = 0; + node_inl* tmp = NULL; + int startpos = subj->pos; + + if (subj->label_nestlevel) { + // if we've already checked to the end of the subject + // for a label, even with a different starting [, we + // know we won't find one here and we can just return. + // Note: nestlevel 1 would be: [foo [bar] + // nestlevel 2 would be: [foo [bar [baz] + subj->label_nestlevel--; + return 0; + } + + advance(subj); // advance past [ + char c; + while ((c = peek_char(subj)) && (c != ']' || nestlevel > 0)) { + switch (c) { + case '`': + tmp = handle_backticks(subj); + free_inlines(tmp); + break; + case '<': + tmp = handle_pointy_brace(subj); + free_inlines(tmp); + break; + case '[': // nested [] + nestlevel++; + advance(subj); + break; + case ']': // nested [] + nestlevel--; + advance(subj); + break; + case '\\': + advance(subj); + if (ispunct(peek_char(subj))) { + advance(subj); + } + break; + default: + advance(subj); + } + } + if (c == ']') { + *raw_label = chunk_dup(&subj->input, startpos + 1, subj->pos - (startpos + 1)); + subj->label_nestlevel = 0; + advance(subj); // advance past ] + return 1; + } else { + if (c == 0) { + subj->label_nestlevel = nestlevel; + } + subj->pos = startpos; // rewind + return 0; + } } // Parse a link or the link portion of an image, or return a fallback. -static inl* handle_left_bracket(subject* subj) -{ - inl* lab = NULL; - inl* result = NULL; - reference* ref; - int n; - int sps; - int found_label; - int endlabel, starturl, endurl, starttitle, endtitle, endall; - bstring url, title, rawlabel, reflabel; - bstring rawlabel2 = NULL; - found_label = link_label(subj, &rawlabel); - endlabel = subj->pos; - if (found_label) { - if (peek_char(subj) == '(' && - ((sps = scan_spacechars(subj->buffer, subj->pos + 1)) > -1) && - ((n = scan_link_url(subj->buffer, subj->pos + 1 + sps)) > -1)) { - // try to parse an explicit link: - starturl = subj->pos + 1 + sps; // after ( - endurl = starturl + n; - starttitle = endurl + scan_spacechars(subj->buffer, endurl); - // ensure there are spaces btw url and title - endtitle = (starttitle == endurl) ? starttitle : - starttitle + scan_link_title(subj->buffer, starttitle); - endall = endtitle + scan_spacechars(subj->buffer, endtitle); - if (bchar(subj->buffer, endall) == ')') { - subj->pos = endall + 1; - url = bmidstr(subj->buffer, starturl, endurl - starturl); - clean_url(url); - title = bmidstr(subj->buffer, starttitle, endtitle - starttitle); - clean_title(title); - lab = parse_inlines(rawlabel, NULL); - bdestroy(rawlabel); - return make_link(lab, url, title); - } else { - // if we get here, we matched a label but didn't get further: - subj->pos = endlabel; - lab = parse_inlines(rawlabel, subj->reference_map); - bdestroy(rawlabel); - result = append_inlines(make_str(bfromcstr("[")), - append_inlines(lab, - make_str(bfromcstr("]")))); - return result; - } - } else { - // Check for reference link. - // First, see if there's another label: - subj->pos = subj->pos + scan_spacechars(subj->buffer, endlabel); - reflabel = rawlabel; - // if followed by a nonempty link label, we change reflabel to it: - if (peek_char(subj) == '[' && - link_label(subj, &rawlabel2)) { - if (blength(rawlabel2) > 0) { - reflabel = rawlabel2; - } - } else { - subj->pos = endlabel; - } - // lookup rawlabel in subject->reference_map: - ref = lookup_reference(subj->reference_map, reflabel); - if (ref != NULL) { // found - lab = parse_inlines(rawlabel, NULL); - result = make_link(lab, bstrcpy(ref->url), bstrcpy(ref->title)); - } else { - subj->pos = endlabel; - lab = parse_inlines(rawlabel, subj->reference_map); - result = append_inlines(make_str(bfromcstr("[")), - append_inlines(lab, make_str(bfromcstr("]")))); - } - bdestroy(rawlabel); - bdestroy(rawlabel2); - return result; - } - } - // If we fall through to here, it means we didn't match a link: - advance(subj); // advance past [ - return make_str(bfromcstr("[")); +static node_inl* handle_left_bracket(subject* subj) +{ + node_inl *lab = NULL; + node_inl *result = NULL; + reference *ref; + int n; + int sps; + int found_label; + int endlabel, starturl, endurl, starttitle, endtitle, endall; + + chunk rawlabel; + chunk url, title; + + found_label = link_label(subj, &rawlabel); + endlabel = subj->pos; + + if (found_label) { + if (peek_char(subj) == '(' && + ((sps = scan_spacechars(&subj->input, subj->pos + 1)) > -1) && + ((n = scan_link_url(&subj->input, subj->pos + 1 + sps)) > -1)) { + + // try to parse an explicit link: + starturl = subj->pos + 1 + sps; // after ( + endurl = starturl + n; + starttitle = endurl + scan_spacechars(&subj->input, endurl); + + // ensure there are spaces btw url and title + endtitle = (starttitle == endurl) ? starttitle : + starttitle + scan_link_title(&subj->input, starttitle); + + endall = endtitle + scan_spacechars(&subj->input, endtitle); + + if (peek_at(subj, endall) == ')') { + subj->pos = endall + 1; + + url = chunk_dup(&subj->input, starturl, endurl - starturl); + title = chunk_dup(&subj->input, starttitle, endtitle - starttitle); + lab = parse_chunk_inlines(&rawlabel, NULL); + + return make_link(lab, url, title); + } else { + // if we get here, we matched a label but didn't get further: + subj->pos = endlabel; + lab = parse_chunk_inlines(&rawlabel, subj->refmap); + result = append_inlines(make_str(chunk_literal("[")), + append_inlines(lab, + make_str(chunk_literal("]")))); + return result; + } + } else { + chunk rawlabel_tmp; + chunk reflabel; + + // Check for reference link. + // First, see if there's another label: + subj->pos = subj->pos + scan_spacechars(&subj->input, endlabel); + reflabel = rawlabel; + + // if followed by a nonempty link label, we change reflabel to it: + if (peek_char(subj) == '[' && link_label(subj, &rawlabel_tmp)) { + if (rawlabel_tmp.len > 0) + reflabel = rawlabel_tmp; + } else { + subj->pos = endlabel; + } + + // lookup rawlabel in subject->reference_map: + ref = reference_lookup(subj->refmap, &reflabel); + if (ref != NULL) { // found + lab = parse_chunk_inlines(&rawlabel, NULL); + result = make_ref_link(lab, ref); + } else { + subj->pos = endlabel; + lab = parse_chunk_inlines(&rawlabel, subj->refmap); + result = append_inlines(make_str(chunk_literal("[")), + append_inlines(lab, make_str(chunk_literal("]")))); + } + return result; + } + } + // If we fall through to here, it means we didn't match a link: + advance(subj); // advance past [ + return make_str(chunk_literal("[")); } // Parse a hard or soft linebreak, returning an inline. // Assumes the subject has a newline at the current position. -static inl* handle_newline(subject *subj) -{ - int nlpos = subj->pos; - // skip over newline - advance(subj); - // skip spaces at beginning of line - while (peek_char(subj) == ' ') { - advance(subj); - } - if (nlpos > 1 && - bchar(subj->buffer, nlpos - 1) == ' ' && - bchar(subj->buffer, nlpos - 2) == ' ') { - return make_linebreak(); - } else { - return make_softbreak(); - } +static node_inl* handle_newline(subject *subj) +{ + int nlpos = subj->pos; + // skip over newline + advance(subj); + // skip spaces at beginning of line + while (peek_char(subj) == ' ') { + advance(subj); + } + if (nlpos > 1 && + peek_at(subj, nlpos - 1) == ' ' && + peek_at(subj, nlpos - 2) == ' ') { + return make_linebreak(); + } else { + return make_softbreak(); + } } inline static int not_eof(subject* subj) { - return !is_eof(subj); + return !is_eof(subj); } // Parse inlines while a predicate is satisfied. Return inlines. -extern inl* parse_inlines_while(subject* subj, int (*f)(subject*)) +extern node_inl* parse_inlines_while(subject* subj, int (*f)(subject*)) { - inl* result = NULL; - inl** last = &result; - while ((*f)(subj) && parse_inline(subj, last)) { - } - return result; + node_inl* result = NULL; + node_inl** last = &result; + while ((*f)(subj) && parse_inline(subj, last)) { + } + return result; +} + +node_inl *parse_chunk_inlines(chunk *chunk, reference_map *refmap) +{ + subject subj; + subject_from_chunk(&subj, chunk, refmap); + return parse_inlines_while(&subj, not_eof); +} + +static int subject_find_special_char(subject *subj) +{ + // "\n\\`&_*[]<!" + static const int8_t SPECIAL_CHARS[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + int n = subj->pos + 1; + + while (n < subj->input.len) { + if (SPECIAL_CHARS[subj->input.data[n]]) + return n; + n++; + } + + return subj->input.len; } // Parse an inline, advancing subject, and add it to last element. // Adjust tail to point to new last element of list. // Return 0 if no inline can be parsed, 1 otherwise. -extern int parse_inline(subject* subj, inl ** last) -{ - inl* new = NULL; - bstring contents; - bstring special_chars; - unsigned char c; - int endpos; - c = peek_char(subj); - if (c == 0) { - return 0; - } - switch(c){ - case '\n': - new = handle_newline(subj); - break; - case '`': - new = handle_backticks(subj); - break; - case '\\': - new = handle_backslash(subj); - break; - case '&': - new = handle_entity(subj); - break; - case '<': - new = handle_pointy_brace(subj); - break; - case '_': - if (subj->pos > 0 && (isalnum(bchar(subj->buffer, subj->pos - 1)) || - bchar(subj->buffer, subj->pos - 1) == '_')) { - new = make_str(take_one(subj)); - } else { - new = handle_strong_emph(subj, '_'); - } - break; - case '*': - new = handle_strong_emph(subj, '*'); - break; - case '[': - new = handle_left_bracket(subj); - break; - case '!': - advance(subj); - if (peek_char(subj) == '[') { - new = handle_left_bracket(subj); - if (new != NULL && new->tag == link) { - new->tag = image; - } else { - new = append_inlines(make_str(bfromcstr("!")), new); - } - } else { - new = make_str(bfromcstr("!")); - } - break; - default: - // we read until we hit a special character - special_chars = bfromcstr("\n\\`&_*[]<!"); - endpos = binchr(subj->buffer, subj->pos, special_chars); - bdestroy(special_chars); - if (endpos == subj->pos) { - // current char is special: read a 1-character str - contents = take_one(subj); - } else if (endpos == BSTR_ERR) { - // special char not found, take whole rest of buffer: - endpos = subj->buffer->slen; - contents = bmidstr(subj->buffer, subj->pos, endpos - subj->pos); - subj->pos = endpos; - } else { - // take buffer from subj->pos to endpos to str. - contents = bmidstr(subj->buffer, subj->pos, endpos - subj->pos); - subj->pos = endpos; - // if we're at a newline, strip trailing spaces. - if (peek_char(subj) == '\n') { - brtrimws(contents); - } - } - new = make_str(contents); - } - if (*last == NULL) { - *last = new; - } else { - append_inlines(*last, new); - } - return 1; -} - -extern inl* parse_inlines(bstring input, reference** refmap) -{ - subject * subj = make_subject(input, refmap); - inl * result = parse_inlines_while(subj, not_eof); - free(subj); - return result; +static int parse_inline(subject* subj, node_inl ** last) +{ + node_inl* new = NULL; + chunk contents; + unsigned char c; + int endpos; + c = peek_char(subj); + if (c == 0) { + return 0; + } + switch(c){ + case '\n': + new = handle_newline(subj); + break; + case '`': + new = handle_backticks(subj); + break; + case '\\': + new = handle_backslash(subj); + break; + case '&': + new = handle_entity(subj); + break; + case '<': + new = handle_pointy_brace(subj); + break; + case '_': + if (subj->pos > 0) { + unsigned char prev = peek_at(subj, subj->pos - 1); + if (isalnum(prev) || prev == '_') { + new = make_str(chunk_literal("_")); + advance(subj); + break; + } + } + + new = handle_strong_emph(subj, '_'); + break; + case '*': + new = handle_strong_emph(subj, '*'); + break; + case '[': + new = handle_left_bracket(subj); + break; + case '!': + advance(subj); + if (peek_char(subj) == '[') { + new = handle_left_bracket(subj); + if (new != NULL && new->tag == INL_LINK) { + new->tag = INL_IMAGE; + } else { + new = append_inlines(make_str(chunk_literal("!")), new); + } + } else { + new = make_str(chunk_literal("!")); + } + break; + default: + endpos = subject_find_special_char(subj); + contents = chunk_dup(&subj->input, subj->pos, endpos - subj->pos); + subj->pos = endpos; + + // if we're at a newline, strip trailing spaces. + if (peek_char(subj) == '\n') { + chunk_rtrim(&contents); + } + + new = make_str(contents); + } + if (*last == NULL) { + *last = new; + } else { + append_inlines(*last, new); + } + return 1; +} + +extern node_inl* parse_inlines(strbuf *input, reference_map *refmap) +{ + subject subj; + subject_from_buf(&subj, input, refmap); + return parse_inlines_while(&subj, not_eof); } // Parse zero or more space characters, including at most one newline. void spnl(subject* subj) { - bool seen_newline = false; - while (peek_char(subj) == ' ' || - (!seen_newline && - (seen_newline = peek_char(subj) == '\n'))) { - advance(subj); - } + bool seen_newline = false; + while (peek_char(subj) == ' ' || + (!seen_newline && + (seen_newline = peek_char(subj) == '\n'))) { + advance(subj); + } } // Parse reference. Assumes string begins with '[' character. // Modify refmap if a reference is encountered. // Return 0 if no reference found, otherwise position of subject // after reference is parsed. -extern int parse_reference(bstring input, reference** refmap) -{ - subject * subj = make_subject(input, NULL); - bstring lab = NULL; - bstring url = NULL; - bstring title = NULL; - int matchlen = 0; - int beforetitle; - reference * new = NULL; - int newpos; - - // parse label: - if (!link_label(subj, &lab)) { - free(subj); - return 0; - } - // colon: - if (peek_char(subj) == ':') { - advance(subj); - } else { - free(subj); - bdestroy(lab); - return 0; - } - // parse link url: - spnl(subj); - matchlen = scan_link_url(subj->buffer, subj->pos); - if (matchlen) { - url = bmidstr(subj->buffer, subj->pos, matchlen); - clean_url(url); - subj->pos += matchlen; - } else { - free(subj); - bdestroy(lab); - bdestroy(url); - return 0; - } - // parse optional link_title - beforetitle = subj->pos; - spnl(subj); - matchlen = scan_link_title(subj->buffer, subj->pos); - if (matchlen) { - title = bmidstr(subj->buffer, subj->pos, matchlen); - clean_title(title); - subj->pos += matchlen; - } else { - subj->pos = beforetitle; - title = bfromcstr(""); - } - // parse final spaces and newline: - while (peek_char(subj) == ' ') { - advance(subj); - } - if (peek_char(subj) == '\n') { - advance(subj); - } else if (peek_char(subj) != 0) { - free(subj); - bdestroy(lab); - bdestroy(url); - bdestroy(title); - return 0; - } - // insert reference into refmap - new = make_reference(lab, url, title); - add_reference(refmap, new); - - newpos = subj->pos; - free(subj); - bdestroy(lab); - bdestroy(url); - bdestroy(title); - return newpos; +int parse_reference_inline(strbuf *input, reference_map *refmap) +{ + subject subj; + + chunk lab; + chunk url; + chunk title; + + int matchlen = 0; + int beforetitle; + + subject_from_buf(&subj, input, NULL); + + // parse label: + if (!link_label(&subj, &lab)) + return 0; + + // colon: + if (peek_char(&subj) == ':') { + advance(&subj); + } else { + return 0; + } + + // parse link url: + spnl(&subj); + matchlen = scan_link_url(&subj.input, subj.pos); + if (matchlen) { + url = chunk_dup(&subj.input, subj.pos, matchlen); + subj.pos += matchlen; + } else { + return 0; + } + + // parse optional link_title + beforetitle = subj.pos; + spnl(&subj); + matchlen = scan_link_title(&subj.input, subj.pos); + if (matchlen) { + title = chunk_dup(&subj.input, subj.pos, matchlen); + subj.pos += matchlen; + } else { + subj.pos = beforetitle; + title = chunk_literal(""); + } + // parse final spaces and newline: + while (peek_char(&subj) == ' ') { + advance(&subj); + } + if (peek_char(&subj) == '\n') { + advance(&subj); + } else if (peek_char(&subj) != 0) { + return 0; + } + // insert reference into refmap + reference_create(refmap, &lab, &url, &title); + return subj.pos; } diff --git a/src/inlines.h b/src/inlines.h new file mode 100644 index 0000000..8c6e2cb --- /dev/null +++ b/src/inlines.h @@ -0,0 +1,13 @@ +#ifndef _INLINES_H_ +#define _INLINES_H_ + +unsigned char *clean_url(chunk *url); +unsigned char *clean_autolink(chunk *url, int is_email); +unsigned char *clean_title(chunk *title); + +node_inl* parse_inlines(strbuf *input, reference_map *refmap); +void free_inlines(node_inl* e); + +int parse_reference_inline(strbuf *input, reference_map *refmap); + +#endif @@ -1,99 +1,77 @@ #include <stdlib.h> #include <stdio.h> -#include "bstrlib.h" +#include <string.h> #include "stmd.h" #include "debug.h" void print_usage() { - printf("Usage: stmd [FILE*]\n"); - printf("Options: --help, -h Print usage information\n"); - printf(" --ast Print AST instead of HTML\n"); - printf(" --version Print version\n"); + printf("Usage: stmd [FILE*]\n"); + printf("Options: --help, -h Print usage information\n"); + printf(" --ast Print AST instead of HTML\n"); + printf(" --version Print version\n"); } -int main(int argc, char *argv[]) { - int i; - bool ast = false; - int g = 0; - int numfps = 0; - int files[argc]; +static void print_document(node_block *document, bool ast) +{ + strbuf html = GH_BUF_INIT; + + if (ast) { + stmd_debug_print(document); + } else { + stmd_render_html(&html, document); + printf("%s", html.ptr); + strbuf_free(&html); + } +} - for (i=1; i < argc; i++) { - if (strcmp(argv[i], "--version") == 0) { - printf("stmd %s", VERSION); - printf(" - CommonMark converter (c) 2014 John MacFarlane\n"); - exit(0); - } else if ((strcmp(argv[i], "--help") == 0) || - (strcmp(argv[i], "-h") == 0)) { - print_usage(); - exit(0); - } else if (strcmp(argv[i], "--ast") == 0) { - ast = true; - } else if (*argv[i] == '-') { - print_usage(); - exit(1); - } else { // treat as file argument - files[g] = i; - g++; - } - } +int main(int argc, char *argv[]) +{ + int i, numfps = 0; + bool ast = false; + int files[argc]; + node_block *document = NULL; - numfps = g; - bstring s = NULL; - bstring html; - g = 0; - block * cur = make_document(); - int linenum = 1; - extern int errno; - FILE * fp = NULL; + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "--version") == 0) { + printf("stmd %s", VERSION); + printf(" - CommonMark converter (c) 2014 John MacFarlane\n"); + exit(0); + } else if ((strcmp(argv[i], "--help") == 0) || + (strcmp(argv[i], "-h") == 0)) { + print_usage(); + exit(0); + } else if (strcmp(argv[i], "--ast") == 0) { + ast = true; + } else if (*argv[i] == '-') { + print_usage(); + exit(1); + } else { // treat as file argument + files[numfps++] = i; + } + } - if (numfps == 0) { - // read from stdin - while ((s = bgets((bNgetc) fgetc, stdin, '\n'))) { - check(incorporate_line(s, linenum, &cur) == 0, - "error incorporating line %d", linenum); - bdestroy(s); - linenum++; - } - } else { - // iterate over input file pointers - for (g=0; g < numfps; g++) { + if (numfps == 0) { + document = stmd_parse_file(stdin); + print_document(document, ast); + stmd_free_nodes(document); + } else { + for (i = 0; i < numfps; i++) { + FILE *fp = fopen(argv[files[i]], "r"); - fp = fopen(argv[files[g]], "r"); - if (fp == NULL) { - fprintf(stderr, "Error opening file %s: %s\n", - argv[files[g]], strerror(errno)); - exit(1); - } + if (fp == NULL) { + fprintf(stderr, "Error opening file %s: %s\n", + argv[files[i]], strerror(errno)); + exit(1); + } - while ((s = bgets((bNgetc) fgetc, fp, '\n'))) { - check(incorporate_line(s, linenum, &cur) == 0, - "error incorporating line %d", linenum); - bdestroy(s); - linenum++; - } - fclose(fp); - } - } + document = stmd_parse_file(fp); + print_document(document, ast); + stmd_free_nodes(document); + fclose(fp); + } + } - while (cur != cur->top) { - finalize(cur, linenum); - cur = cur->parent; - } - check(cur == cur->top, "problems finalizing open containers"); - finalize(cur, linenum); - process_inlines(cur, cur->attributes.refmap); - if (ast) { - print_blocks(cur, 0); - } else { - check(blocks_to_html(cur, &html, false) == 0, "could not format as HTML"); - printf("%s", html->data); - bdestroy(html); - } - free_blocks(cur); - return 0; -error: - return -1; + return 0; } diff --git a/src/print.c b/src/print.c index a924870..83f8daa 100644 --- a/src/print.c +++ b/src/print.c @@ -1,168 +1,176 @@ #include <stdlib.h> #include <stdio.h> -#include "bstrlib.h" +#include <string.h> #include "stmd.h" #include "debug.h" -static bstring format_str(bstring s) +static void print_str(const unsigned char *s, int len) { - int pos = 0; - int len = blength(s); - bstring result = bfromcstr(""); - char c; - bformata(result, "\""); - while (pos < len) { - c = bchar(s, pos); - switch (c) { - case '\n': - bformata(result, "\\n"); - break; - case '"': - bformata(result, "\\\""); - break; - case '\\': - bformata(result, "\\\\"); - break; - default: - bformata(result, "%c", c); - } - pos++; - } - bformata(result, "\""); - return result; + int i; + + if (len < 0) + len = strlen((char *)s); + + putchar('"'); + for (i = 0; i < len; ++i) { + unsigned char c = s[i]; + + switch (c) { + case '\n': + printf("\\n"); + break; + case '"': + printf("\\\""); + break; + case '\\': + printf("\\\\"); + break; + default: + putchar((int)c); + } + } + putchar('"'); } -// Functions to pretty-print inline and block lists, for debugging. // Prettyprint an inline list, for debugging. -extern void print_blocks(block* b, int indent) +static void print_inlines(node_inl* ils, int indent) { - struct ListData * data; - while(b != NULL) { - // printf("%3d %3d %3d| ", b->start_line, b->start_column, b->end_line); - for (int i=0; i < indent; i++) { - putchar(' '); - } - switch(b->tag) { - case document: - printf("document\n"); - print_blocks(b->children, indent + 2); - break; - case block_quote: - printf("block_quote\n"); - print_blocks(b->children, indent + 2); - break; - case list_item: - data = &(b->attributes.list_data); - printf("list_item\n"); - print_blocks(b->children, indent + 2); - break; - case list: - data = &(b->attributes.list_data); - if (data->list_type == ordered) { - printf("list (type=ordered tight=%s start=%d delim=%s)\n", - (data->tight ? "true" : "false"), - data->start, - (data->delimiter == parens ? "parens" : "period")); - } else { - printf("list (type=bullet tight=%s bullet_char=%c)\n", - (data->tight ? "true" : "false"), - data->bullet_char); - } - print_blocks(b->children, indent + 2); - break; - case atx_header: - printf("atx_header (level=%d)\n", b->attributes.header_level); - print_inlines(b->inline_content, indent + 2); - break; - case setext_header: - printf("setext_header (level=%d)\n", b->attributes.header_level); - print_inlines(b->inline_content, indent + 2); - break; - case paragraph: - printf("paragraph\n"); - print_inlines(b->inline_content, indent + 2); - break; - case hrule: - printf("hrule\n"); - break; - case indented_code: - printf("indented_code %s\n", format_str(b->string_content)->data); - break; - case fenced_code: - printf("fenced_code length=%d info=%s %s\n", - b->attributes.fenced_code_data.fence_length, - format_str(b->attributes.fenced_code_data.info)->data, - format_str(b->string_content)->data); - break; - case html_block: - printf("html_block %s\n", format_str(b->string_content)->data); - break; - case reference_def: - printf("reference_def\n"); - break; - default: - log_warn("block type %d not implemented\n", b->tag); - break; - } - b = b->next; - } + while(ils != NULL) { + for (int i=0; i < indent; i++) { + putchar(' '); + } + switch(ils->tag) { + case INL_STRING: + printf("str "); + print_str(ils->content.literal.data, ils->content.literal.len); + putchar('\n'); + break; + case INL_LINEBREAK: + printf("linebreak\n"); + break; + case INL_SOFTBREAK: + printf("softbreak\n"); + break; + case INL_CODE: + printf("code "); + print_str(ils->content.literal.data, ils->content.literal.len); + putchar('\n'); + break; + case INL_RAW_HTML: + printf("html "); + print_str(ils->content.literal.data, ils->content.literal.len); + putchar('\n'); + break; + case INL_LINK: + case INL_IMAGE: + printf("%s url=", ils->tag == INL_LINK ? "link" : "image"); + + if (ils->content.linkable.url) + print_str(ils->content.linkable.url, -1); + + if (ils->content.linkable.title) { + printf(" title="); + print_str(ils->content.linkable.title, -1); + } + putchar('\n'); + print_inlines(ils->content.linkable.label, indent + 2); + break; + case INL_STRONG: + printf("strong\n"); + print_inlines(ils->content.linkable.label, indent + 2); + break; + case INL_EMPH: + printf("emph\n"); + print_inlines(ils->content.linkable.label, indent + 2); + break; + } + ils = ils->next; + } } +// Functions to pretty-print inline and node_block lists, for debugging. // Prettyprint an inline list, for debugging. -extern void print_inlines(inl* ils, int indent) +static void print_blocks(node_block* b, int indent) +{ + struct ListData *data; + + while(b != NULL) { + for (int i=0; i < indent; i++) { + putchar(' '); + } + + switch(b->tag) { + case BLOCK_DOCUMENT: + printf("document\n"); + print_blocks(b->children, indent + 2); + break; + case BLOCK_BQUOTE: + printf("block_quote\n"); + print_blocks(b->children, indent + 2); + break; + case BLOCK_LIST_ITEM: + printf("list_item\n"); + print_blocks(b->children, indent + 2); + break; + case BLOCK_LIST: + data = &(b->as.list); + if (data->list_type == ordered) { + printf("list (type=ordered tight=%s start=%d delim=%s)\n", + (data->tight ? "true" : "false"), + data->start, + (data->delimiter == parens ? "parens" : "period")); + } else { + printf("list (type=bullet tight=%s bullet_char=%c)\n", + (data->tight ? "true" : "false"), + data->bullet_char); + } + print_blocks(b->children, indent + 2); + break; + case BLOCK_ATX_HEADER: + printf("atx_header (level=%d)\n", b->as.header.level); + print_inlines(b->inline_content, indent + 2); + break; + case BLOCK_SETEXT_HEADER: + printf("setext_header (level=%d)\n", b->as.header.level); + print_inlines(b->inline_content, indent + 2); + break; + case BLOCK_PARAGRAPH: + printf("paragraph\n"); + print_inlines(b->inline_content, indent + 2); + break; + case BLOCK_HRULE: + printf("hrule\n"); + break; + case BLOCK_INDENTED_CODE: + printf("indented_code "); + print_str(b->string_content.ptr, -1); + putchar('\n'); + break; + case BLOCK_FENCED_CODE: + printf("fenced_code length=%d info=", + b->as.code.fence_length); + print_str(b->as.code.info.ptr, -1); + putchar(' '); + print_str(b->string_content.ptr, -1); + putchar('\n'); + break; + case BLOCK_HTML: + printf("html_block "); + print_str(b->string_content.ptr, -1); + putchar('\n'); + break; + case BLOCK_REFERENCE_DEF: + printf("reference_def\n"); + break; + default: + printf("# NOT IMPLEMENTED (%d)\n", b->tag); + break; + } + b = b->next; + } +} + +void stmd_debug_print(node_block *root) { - while(ils != NULL) { - /* - // we add 11 extra spaces for the line/column info - for (int i=0; i < 11; i++) { - putchar(' '); - } - putchar('|'); - putchar(' '); - */ - for (int i=0; i < indent; i++) { - putchar(' '); - } - switch(ils->tag) { - case str: - printf("str %s\n", format_str(ils->content.literal)->data); - break; - case linebreak: - printf("linebreak\n"); - break; - case softbreak: - printf("softbreak\n"); - break; - case code: - printf("code %s\n", format_str(ils->content.literal)->data); - break; - case raw_html: - printf("html %s\n", format_str(ils->content.literal)->data); - break; - case entity: - printf("entity %s\n", format_str(ils->content.literal)->data); - break; - case link: - printf("link url=%s title=%s\n", - format_str(ils->content.linkable.url)->data, - format_str(ils->content.linkable.title)->data); - print_inlines(ils->content.linkable.label, indent + 2); - break; - case image: - printf("image url=%s title=%s\n", - format_str(ils->content.linkable.url)->data, - format_str(ils->content.linkable.title)->data); - print_inlines(ils->content.linkable.label, indent + 2); - break; - case strong: - printf("strong\n"); - print_inlines(ils->content.linkable.label, indent + 2); - break; - case emph: - printf("emph\n"); - print_inlines(ils->content.linkable.label, indent + 2); - break; - } - ils = ils->next; - } + print_blocks(root, 0); } diff --git a/src/references.c b/src/references.c new file mode 100644 index 0000000..3e54b48 --- /dev/null +++ b/src/references.c @@ -0,0 +1,141 @@ +#include "stmd.h" +#include "utf8.h" +#include "references.h" +#include "inlines.h" + +static unsigned int +refhash(const unsigned char *link_ref) +{ + unsigned int hash = 0; + + while (*link_ref) + hash = (*link_ref++) + (hash << 6) + (hash << 16) - hash; + + return hash; +} + +static void reference_free(reference *ref) +{ + free(ref->label); + free(ref->url); + free(ref->title); + free(ref); +} + +// normalize reference: collapse internal whitespace to single space, +// remove leading/trailing whitespace, case fold +// Return NULL if the reference name is actually empty (i.e. composed +// solely from whitespace) +static unsigned char *normalize_reference(chunk *ref) +{ + strbuf normalized = GH_BUF_INIT; + unsigned char *result; + + if (ref->len == 0) + return NULL; + + utf8proc_case_fold(&normalized, ref->data, ref->len); + strbuf_trim(&normalized); + strbuf_normalize_whitespace(&normalized); + + result = strbuf_detach(&normalized); + assert(result); + + if (result[0] == '\0') { + free(result); + return NULL; + } + + return result; +} + +static void add_reference(reference_map *map, reference* ref) +{ + reference *t = ref->next = map->table[ref->hash % REFMAP_SIZE]; + + while (t) { + if (t->hash == ref->hash && + !strcmp((char *)t->label, (char *)ref->label)) { + reference_free(ref); + return; + } + + t = t->next; + } + + map->table[ref->hash % REFMAP_SIZE] = ref; +} + +extern void reference_create(reference_map *map, chunk *label, chunk *url, chunk *title) +{ + reference *ref; + unsigned char *reflabel = normalize_reference(label); + + /* empty reference name, or composed from only whitespace */ + if (reflabel == NULL) + return; + + ref = malloc(sizeof(reference)); + ref->label = reflabel; + ref->hash = refhash(ref->label); + ref->url = clean_url(url); + ref->title = clean_title(title); + ref->next = NULL; + + add_reference(map, ref); +} + +// Returns reference if refmap contains a reference with matching +// label, otherwise NULL. +reference* reference_lookup(reference_map *map, chunk *label) +{ + reference *ref = NULL; + unsigned char *norm; + unsigned int hash; + + if (map == NULL) + return NULL; + + norm = normalize_reference(label); + if (norm == NULL) + return NULL; + + hash = refhash(norm); + ref = map->table[hash % REFMAP_SIZE]; + + while (ref) { + if (ref->hash == hash && + !strcmp((char *)ref->label, (char *)norm)) + break; + ref = ref->next; + } + + free(norm); + return ref; +} + +void reference_map_free(reference_map *map) +{ + unsigned int i; + + for (i = 0; i < REFMAP_SIZE; ++i) { + reference *ref = map->table[i]; + reference *next; + + while (ref) { + next = ref->next; + reference_free(ref); + ref = next; + } + } + + free(map); +} + +reference_map *reference_map_new(void) +{ + reference_map *map = malloc(sizeof(reference_map)); + memset(map, 0x0, sizeof(reference_map)); + return map; +} + diff --git a/src/references.h b/src/references.h new file mode 100644 index 0000000..28937f1 --- /dev/null +++ b/src/references.h @@ -0,0 +1,27 @@ +#ifndef _REFERENCES_H_ +#define _REFERENCES_H_ + +#define REFMAP_SIZE 16 + +struct reference { + struct reference *next; + unsigned char *label; + unsigned char *url; + unsigned char *title; + unsigned int hash; +}; + +typedef struct reference reference; + +struct reference_map { + reference *table[REFMAP_SIZE]; +}; + +typedef struct reference_map reference_map; + +reference_map *reference_map_new(void); +void reference_map_free(reference_map *map); +reference* reference_lookup(reference_map *map, chunk *label); +extern void reference_create(reference_map *map, chunk *label, chunk *url, chunk *title); + +#endif diff --git a/src/scanners.h b/src/scanners.h index 71e0520..785d424 100644 --- a/src/scanners.h +++ b/src/scanners.h @@ -1,15 +1,42 @@ -#include "bstrlib.h" - -int scan_autolink_uri(bstring s, int pos); -int scan_autolink_email(bstring s, int pos); -int scan_html_tag(bstring s, int pos); -int scan_html_block_tag(bstring s, int pos); -int scan_link_url(bstring s, int pos); -int scan_link_title(bstring s, int pos); -int scan_spacechars(bstring s, int pos); -int scan_atx_header_start(bstring s, int pos); -int scan_setext_header_line(bstring s, int pos); -int scan_hrule(bstring s, int pos); -int scan_open_code_fence(bstring s, int pos); -int scan_close_code_fence(bstring s, int pos, int len); -int scan_entity(bstring s, int pos); +#include "stmd.h" + +extern int _scan_autolink_uri(const unsigned char *p); +extern int _scan_autolink_email(const unsigned char *p); +extern int _scan_html_tag(const unsigned char *p); +extern int _scan_html_block_tag(const unsigned char *p); +extern int _scan_link_url(const unsigned char *p); +extern int _scan_link_title(const unsigned char *p); +extern int _scan_spacechars(const unsigned char *p); +extern int _scan_atx_header_start(const unsigned char *p); +extern int _scan_setext_header_line(const unsigned char *p); +extern int _scan_hrule(const unsigned char *p); +extern int _scan_open_code_fence(const unsigned char *p); +extern int _scan_close_code_fence(const unsigned char *p); +extern int _scan_entity(const unsigned char *p); + +static int scan_at(int (*scanner)(const unsigned char *), chunk *c, int offset) +{ + int res; + unsigned char *ptr = (unsigned char *)c->data; + unsigned char lim = ptr[c->len]; + + ptr[c->len] = '\0'; + res = scanner(ptr + offset); + ptr[c->len] = lim; + + return res; +} + +#define scan_autolink_uri(c, n) scan_at(&_scan_autolink_uri, c, n) +#define scan_autolink_email(c, n) scan_at(&_scan_autolink_email, c, n) +#define scan_html_tag(c, n) scan_at(&_scan_html_tag, c, n) +#define scan_html_block_tag(c, n) scan_at(&_scan_html_block_tag, c, n) +#define scan_link_url(c, n) scan_at(&_scan_link_url, c, n) +#define scan_link_title(c, n) scan_at(&_scan_link_title, c, n) +#define scan_spacechars(c, n) scan_at(&_scan_spacechars, c, n) +#define scan_atx_header_start(c, n) scan_at(&_scan_atx_header_start, c, n) +#define scan_setext_header_line(c, n) scan_at(&_scan_setext_header_line, c, n) +#define scan_hrule(c, n) scan_at(&_scan_hrule, c, n) +#define scan_open_code_fence(c, n) scan_at(&_scan_open_code_fence, c, n) +#define scan_close_code_fence(c, n) scan_at(&_scan_close_code_fence, c, n) +#define scan_entity(c, n) scan_at(&_scan_entity, c, n) diff --git a/src/scanners.re b/src/scanners.re index 305d1ea..28aba9d 100644 --- a/src/scanners.re +++ b/src/scanners.re @@ -1,4 +1,4 @@ -#include "bstrlib.h" +#include <stdlib.h> /*!re2c re2c:define:YYCTYPE = "unsigned char"; @@ -55,11 +55,10 @@ */ // Try to match URI autolink after first <, returning number of chars matched. -extern int scan_autolink_uri(bstring s, int pos) +extern int _scan_autolink_uri(const unsigned char *p) { - unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); - unsigned char * start = p; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c scheme [:]([^\x00-\x20<>\\]|escaped_char)*[>] { return (p - start); } .? { return 0; } @@ -67,11 +66,10 @@ extern int scan_autolink_uri(bstring s, int pos) } // Try to match email autolink after first <, returning num of chars matched. -extern int scan_autolink_email(bstring s, int pos) +extern int _scan_autolink_email(const unsigned char *p) { - unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); - unsigned char * start = p; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c [a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+ [@] @@ -83,11 +81,10 @@ extern int scan_autolink_email(bstring s, int pos) } // Try to match an HTML tag after first <, returning num of chars matched. -extern int scan_html_tag(bstring s, int pos) +extern int _scan_html_tag(const unsigned char *p) { - unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); - unsigned char * start = p; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c htmltag { return (p - start); } .? { return 0; } @@ -96,11 +93,10 @@ extern int scan_html_tag(bstring s, int pos) // Try to match an HTML block tag including first <, // returning num of chars matched. -extern int scan_html_block_tag(bstring s, int pos) +extern int _scan_html_block_tag(const unsigned char *p) { - unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); - unsigned char * start = p; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c [<] [/] blocktagname (spacechar | [>]) { return (p - start); } [<] blocktagname (spacechar | [/>]) { return (p - start); } @@ -113,11 +109,10 @@ extern int scan_html_block_tag(bstring s, int pos) // This may optionally be contained in <..>; otherwise // whitespace and unbalanced right parentheses aren't allowed. // Newlines aren't ever allowed. -extern int scan_link_url(bstring s, int pos) +extern int _scan_link_url(const unsigned char *p) { - unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); - unsigned char * start = p; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c [ \n]* [<] ([^<>\n\\\x00] | escaped_char | [\\])* [>] { return (p - start); } [ \n]* (reg_char+ | escaped_char | in_parens_nosp)* { return (p - start); } @@ -128,11 +123,10 @@ extern int scan_link_url(bstring s, int pos) // Try to match a link title (in single quotes, in double quotes, or // in parentheses), returning number of chars matched. Allow one // level of internal nesting (quotes within quotes). -extern int scan_link_title(bstring s, int pos) +extern int _scan_link_title(const unsigned char *p) { - unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); - unsigned char * start = p; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c ["] (escaped_char|[^"\x00])* ["] { return (p - start); } ['] (escaped_char|[^'\x00])* ['] { return (p - start); } @@ -142,10 +136,9 @@ extern int scan_link_title(bstring s, int pos) } // Match space characters, including newlines. -extern int scan_spacechars(bstring s, int pos) +extern int _scan_spacechars(const unsigned char *p) { - unsigned char * p = &(s->data[pos]); - unsigned char * start = p; + const unsigned char *start = p; \ /*!re2c [ \t\n]* { return (p - start); } . { return 0; } @@ -153,11 +146,10 @@ extern int scan_spacechars(bstring s, int pos) } // Match ATX header start. -extern int scan_atx_header_start(bstring s, int pos) +extern int _scan_atx_header_start(const unsigned char *p) { - unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); - unsigned char * start = p; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c [#]{1,6} ([ ]+|[\n]) { return (p - start); } .? { return 0; } @@ -166,10 +158,9 @@ extern int scan_atx_header_start(bstring s, int pos) // Match sexext header line. Return 1 for level-1 header, // 2 for level-2, 0 for no match. -extern int scan_setext_header_line(bstring s, int pos) +extern int _scan_setext_header_line(const unsigned char *p) { - unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); + const unsigned char *marker = NULL; /*!re2c [=]+ [ ]* [\n] { return 1; } [-]+ [ ]* [\n] { return 2; } @@ -180,11 +171,10 @@ extern int scan_setext_header_line(bstring s, int pos) // Scan a horizontal rule line: "...three or more hyphens, asterisks, // or underscores on a line by themselves. If you wish, you may use // spaces between the hyphens or asterisks." -extern int scan_hrule(bstring s, int pos) +extern int _scan_hrule(const unsigned char *p) { - unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); - unsigned char * start = p; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c ([*][ ]*){3,} [ \t]* [\n] { return (p - start); } ([_][ ]*){3,} [ \t]* [\n] { return (p - start); } @@ -194,11 +184,10 @@ extern int scan_hrule(bstring s, int pos) } // Scan an opening code fence. -extern int scan_open_code_fence(bstring s, int pos) +extern int _scan_open_code_fence(const unsigned char *p) { - unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); - unsigned char * start = p; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c [`]{3,} / [^`\n\x00]*[\n] { return (p - start); } [~]{3,} / [^~\n\x00]*[\n] { return (p - start); } @@ -207,29 +196,22 @@ extern int scan_open_code_fence(bstring s, int pos) } // Scan a closing code fence with length at least len. -extern int scan_close_code_fence(bstring s, int pos, int len) +extern int _scan_close_code_fence(const unsigned char *p) { - unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); - unsigned char * start = p; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c - ([`]{3,} | [~]{3,}) / spacechar* [\n] - { if (p - start > len) { - return (p - start); - } else { - return 0; - } } + ([`]{3,} | [~]{3,}) / spacechar* [\n] { return (p - start); } .? { return 0; } */ } // Scans an entity. // Returns number of chars matched. -extern int scan_entity(bstring s, int pos) +extern int _scan_entity(const unsigned char *p) { - unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); - unsigned char * start = p; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c [&] ([#] ([Xx][A-Fa-f0-9]{1,8}|[0-9]{1,8}) |[A-Za-z][A-Za-z0-9]{1,31} ) [;] { return (p - start); } @@ -1,121 +1,115 @@ +#ifndef _STDMD_H_ +#define _STDMD_H_ + #include <stdbool.h> -#include "bstrlib.h" -#include "uthash.h" +#include <stdio.h> +#include "buffer.h" +#include "chunk.h" +#include "references.h" #define VERSION "0.1" #define CODE_INDENT 4 -typedef struct Inline { - enum { str, softbreak, linebreak, code, raw_html, entity, - emph, strong, link, image } tag; - union { - bstring literal; - struct Inline* inlines; - struct { struct Inline* label; - bstring url; - bstring title; - } linkable; - } content; - struct Inline* next; -} inl; - -typedef struct Reference { - bstring label; - bstring url; - bstring title; - UT_hash_handle hh; // used by uthash -} reference; +struct node_inl { + enum { + INL_STRING, + INL_SOFTBREAK, + INL_LINEBREAK, + INL_CODE, + INL_RAW_HTML, + INL_EMPH, + INL_STRONG, + INL_LINK, + INL_IMAGE + } tag; + union { + chunk literal; + struct node_inl *inlines; + struct { + struct node_inl *label; + unsigned char *url; + unsigned char *title; + } linkable; + } content; + struct node_inl *next; +}; -typedef struct Subject { - bstring buffer; - int pos; - reference** reference_map; - int label_nestlevel; -} subject; +typedef struct node_inl node_inl; // Types for blocks - struct ListData { - enum { bullet, - ordered } list_type; - int marker_offset; - int padding; - int start; - enum { period, - parens } delimiter; - unsigned char bullet_char; - bool tight; + enum { + bullet, + ordered + } list_type; + int marker_offset; + int padding; + int start; + enum { + period, + parens + } delimiter; + unsigned char bullet_char; + bool tight; }; struct FencedCodeData { - int fence_length; - int fence_offset; - char fence_char; - bstring info; + int fence_length; + int fence_offset; + char fence_char; + strbuf info; }; -typedef struct Block { - enum { document, - block_quote, - list, - list_item, - fenced_code, - indented_code, - html_block, - paragraph, - atx_header, - setext_header, - hrule, - reference_def - } tag; - int start_line; - int start_column; - int end_line; - bool open; - bool last_line_blank; - struct Block* children; - struct Block* last_child; - struct Block* parent; - struct Block* top; - bstring string_content; - inl* inline_content; - union { - struct ListData list_data; - struct FencedCodeData fenced_code_data; - int header_level; - reference** refmap; - } attributes; - struct Block * next; - struct Block * prev; -} block; +struct node_block { + enum { + BLOCK_DOCUMENT, + BLOCK_BQUOTE, + BLOCK_LIST, + BLOCK_LIST_ITEM, + BLOCK_FENCED_CODE, + BLOCK_INDENTED_CODE, + BLOCK_HTML, + BLOCK_PARAGRAPH, + BLOCK_ATX_HEADER, + BLOCK_SETEXT_HEADER, + BLOCK_HRULE, + BLOCK_REFERENCE_DEF + } tag; + int start_line; + int start_column; + int end_line; + bool open; + bool last_line_blank; + struct node_block* children; + struct node_block* last_child; + struct node_block* parent; + struct node_block* top; + strbuf string_content; + node_inl* inline_content; -int parse_inline(subject* subj, inl ** last); -inl* parse_inlines(bstring input, reference** refmap); -inl* parse_inlines_while(subject* subj, int (*f)(subject*)); -void free_inlines(inl* e); -int parse_reference(bstring input, reference** refmap); -void free_reference(reference *ref); -void free_reference_map(reference **refmap); -reference* make_reference(bstring label, bstring url, bstring title); -reference* lookup_reference(reference** refmap, bstring label); -void add_reference(reference** refmap, reference* ref); -int unescape(bstring s); + union { + struct ListData list; + struct FencedCodeData code; + struct { + int level; + } header; + struct { + reference_map *refmap; + } document; + } as; -extern block* make_document(); -extern block* add_child(block* parent, - int block_type, int start_line, int start_column); -void free_blocks(block* e); + struct node_block *next; + struct node_block *prev; +}; -// FOR NOW: -int process_inlines(block* cur, reference** refmap); -int incorporate_line(bstring ln, int line_number, block** curptr); -int finalize(block* b, int line_number); +typedef struct node_block node_block; -void print_inlines(inl* ils, int indent); -void print_blocks(block* blk, int indent); +node_block *stmd_parse_document(const unsigned char *buffer, size_t len); +node_block *stmd_parse_file(FILE *f); -int blocks_to_html(block* b, bstring* result, bool tight); -int inlines_to_html(inl* b, bstring* result); +void stmd_free_nodes(node_block *e); -int bdetab(bstring s, int utf8); +void stmd_debug_print(node_block *root); +void stmd_render_html(strbuf *html, node_block *root); +#endif @@ -1,106 +1,193 @@ #include <stdlib.h> -#include "bstrlib.h" -#include "debug.h" - -#define advance(s) \ - s++; \ - check(*s >> 6 == 0x02, "UTF-8 decode error on byte %x", *s); - -// Reads a unicode code point from a UTF8-encoded string, and -// puts it in the pointer n. If something illegal -// is encountered, 0xFFFD is emitted. -// Returns a pointer to next position in string, or NULL if no -// more characters remain. -extern unsigned char * from_utf8(unsigned char * s, unsigned int *n) +#include <stdint.h> +#include <unistd.h> +#include <assert.h> + +#include "utf8.h" + +static const int8_t utf8proc_utf8class[256] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0 }; + +static void encode_unknown(strbuf *buf) { - int x = 0; - - if (*s == 0) { - return NULL; - } else if (*s < 0x80) { - x = *s; - } else if (*s >> 5 == 0x06) { - x = *s & 0x1F; - advance(s); - x = (x << 6) + (*s & 0x3F); - } else if (*s >> 4 == 0x0E) { - x = *s & 0x0F; - advance(s); - x = (x << 6) + (*s & 0x3F); - advance(s); - x = (x << 6) + (*s & 0x3F); - } else if (*s >> 3 == 0x1E) { - x = *s & 0x07; - advance(s); - x = (x << 6) + (*s & 0x3F); - advance(s); - x = (x << 6) + (*s & 0x3F); - advance(s); - x = (x << 6) + (*s & 0x3F); - } else if (*s >> 2 == 0x3E) { - x = *s & 0x03; - advance(s); - x = (x << 6) + (*s & 0x3F); - advance(s); - x = (x << 6) + (*s & 0x3F); - advance(s); - x = (x << 6) + (*s & 0x3F); - advance(s); - x = (x << 6) + (*s & 0x3F); - } else { - log_err("UTF-8 decode error on byte %x", *s); - goto error; - } - *n = x; - s++; - return s; - error: - *n = 0xFFFD; - return s; + static const uint8_t repl[] = {239, 191, 189}; + strbuf_put(buf, repl, 3); } -// Converts the unicode code point c to UTF-8, -// putting the result in dest. Returns 0 on success, -1 on error. -extern int to_utf8(unsigned int c, bstring dest) +int utf8proc_charlen(const uint8_t *str, int str_len) { - if (c < 0x80) { - bconchar(dest, c); - } else if (c < 0x800) { - bconchar(dest, 192 + c/64); - bconchar(dest, 128 + c%64); - } else if (c - 0xd800u < 0x800) { - goto error; - } else if (c < 0x10000) { - bconchar(dest, 224 + c / 4096); - bconchar(dest, 128 + c /64%64); - bconchar(dest, 128 + c%64); - } else if (c < 0x110000) { - bconchar(dest, 240 + c/262144); - bconchar(dest, 128 + c/4096%64); - bconchar(dest, 128 + c/64%64); - bconchar(dest, 128 + c%64); - } else { - goto error; - } - return 0; -error: - return -1; + int length, i; + + if (!str_len) + return 0; + + length = utf8proc_utf8class[str[0]]; + + if (!length) + return -1; + + if (str_len >= 0 && length > str_len) + return -str_len; + + for (i = 1; i < length; i++) { + if ((str[i] & 0xC0) != 0x80) + return -i; + } + + return length; } -#define bufpush(x) \ - check(to_utf8(x, buf) == 0, "UTF-8 encode error on code point %04x", x) +void utf8proc_detab(strbuf *ob, const uint8_t *line, size_t size) +{ + static const uint8_t whitespace[] = " "; + + size_t i = 0, tab = 0; + + while (i < size) { + size_t org = i; + + while (i < size && line[i] != '\t' && line[i] <= 0x80) { + i++; tab++; + } + + if (i > org) + strbuf_put(ob, line + org, i - org); + + if (i >= size) + break; + + if (line[i] == '\t') { + int numspaces = 4 - (tab % 4); + strbuf_put(ob, whitespace, numspaces); + i += 1; + tab += numspaces; + } else { + int charlen = utf8proc_charlen(line + i, size - i); + + if (charlen >= 0) { + strbuf_put(ob, line + i, charlen); + } else { + encode_unknown(ob); + charlen = -charlen; + } + + i += charlen; + tab += 1; + } + } +} + +int utf8proc_iterate(const uint8_t *str, int str_len, int32_t *dst) +{ + int length; + int32_t uc = -1; + + *dst = -1; + length = utf8proc_charlen(str, str_len); + if (length < 0) + return -1; + + switch (length) { + case 1: + uc = str[0]; + break; + case 2: + uc = ((str[0] & 0x1F) << 6) + (str[1] & 0x3F); + if (uc < 0x80) uc = -1; + break; + case 3: + uc = ((str[0] & 0x0F) << 12) + ((str[1] & 0x3F) << 6) + + (str[2] & 0x3F); + if (uc < 0x800 || (uc >= 0xD800 && uc < 0xE000) || + (uc >= 0xFDD0 && uc < 0xFDF0)) uc = -1; + break; + case 4: + uc = ((str[0] & 0x07) << 18) + ((str[1] & 0x3F) << 12) + + ((str[2] & 0x3F) << 6) + (str[3] & 0x3F); + if (uc < 0x10000 || uc >= 0x110000) uc = -1; + break; + } -// Returns the case-folded version of the source string, or NULL on error. -extern bstring case_fold(bstring source) + if (uc < 0 || ((uc & 0xFFFF) >= 0xFFFE)) + return -1; + + *dst = uc; + return length; +} + +void utf8proc_encode_char(int32_t uc, strbuf *buf) { - unsigned char * s = source->data; - unsigned int c = 0; - bstring buf = bfromcstr(""); - while ((s = from_utf8(s, &c))) { -#include "case_fold_switch.c" - } - return buf; -error: - return NULL; + uint8_t dst[4]; + int len = 0; + + assert(uc >= 0); + + if (uc < 0x80) { + dst[0] = uc; + len = 1; + } else if (uc < 0x800) { + dst[0] = 0xC0 + (uc >> 6); + dst[1] = 0x80 + (uc & 0x3F); + len = 2; + } else if (uc == 0xFFFF) { + dst[0] = 0xFF; + len = 1; + } else if (uc == 0xFFFE) { + dst[0] = 0xFE; + len = 1; + } else if (uc < 0x10000) { + dst[0] = 0xE0 + (uc >> 12); + dst[1] = 0x80 + ((uc >> 6) & 0x3F); + dst[2] = 0x80 + (uc & 0x3F); + len = 3; + } else if (uc < 0x110000) { + dst[0] = 0xF0 + (uc >> 18); + dst[1] = 0x80 + ((uc >> 12) & 0x3F); + dst[2] = 0x80 + ((uc >> 6) & 0x3F); + dst[3] = 0x80 + (uc & 0x3F); + len = 4; + } else { + encode_unknown(buf); + return; + } + + strbuf_put(buf, dst, len); +} + +void utf8proc_case_fold(strbuf *dest, const uint8_t *str, int len) +{ + int32_t c; + +#define bufpush(x) \ + utf8proc_encode_char(x, dest) + + while (len > 0) { + int char_len = utf8proc_iterate(str, len, &c); + + if (char_len >= 0) { +#include "case_fold_switch.inc" + } else { + encode_unknown(dest); + char_len = -char_len; + } + + str += char_len; + len -= char_len; + } } @@ -1,6 +1,13 @@ -#include <stdlib.h> -#include "bstrlib.h" +#ifndef _H_STMD_UTF8_ +#define _H_STMD_UTF8_ -extern unsigned char * from_utf8(unsigned char * s, unsigned int *n); -extern int to_utf8(unsigned int c, bstring dest); -extern bstring case_fold(bstring source); +#include <stdint.h> +#include "buffer.h" + +void utf8proc_case_fold(strbuf *dest, const uint8_t *str, int len); +void utf8proc_encode_char(int32_t uc, strbuf *buf); +int utf8proc_iterate(const uint8_t *str, int str_len, int32_t *dst); +int utf8proc_charlen(const uint8_t *str, int str_len); +void utf8proc_detab(strbuf *dest, const uint8_t *line, size_t size); + +#endif diff --git a/src/uthash.h b/src/uthash.h deleted file mode 100644 index b9bc7e9..0000000 --- a/src/uthash.h +++ /dev/null @@ -1,948 +0,0 @@ -/* -Copyright (c) 2003-2013, Troy D. Hanson http://troydhanson.github.com/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef UTHASH_H -#define UTHASH_H - -#include <string.h> /* memcmp,strlen */ -#include <stddef.h> /* ptrdiff_t */ -#include <stdlib.h> /* exit() */ - -/* These macros use decltype or the earlier __typeof GNU extension. - As decltype is only available in newer compilers (VS2010 or gcc 4.3+ - when compiling c++ source) this code uses whatever method is needed - or, for VS2008 where neither is available, uses casting workarounds. */ -#ifdef _MSC_VER /* MS compiler */ -#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ -#define DECLTYPE(x) (decltype(x)) -#else /* VS2008 or older (or VS2010 in C mode) */ -#define NO_DECLTYPE -#define DECLTYPE(x) -#endif -#else /* GNU, Sun and other compilers */ -#define DECLTYPE(x) (__typeof(x)) -#endif - -#ifdef NO_DECLTYPE -#define DECLTYPE_ASSIGN(dst,src) \ -do { \ - char **_da_dst = (char**)(&(dst)); \ - *_da_dst = (char*)(src); \ -} while(0) -#else -#define DECLTYPE_ASSIGN(dst,src) \ -do { \ - (dst) = DECLTYPE(dst)(src); \ -} while(0) -#endif - -/* a number of the hash function use uint32_t which isn't defined on win32 */ -#ifdef _MSC_VER -typedef unsigned int uint32_t; -typedef unsigned char uint8_t; -#else -#include <inttypes.h> /* uint32_t */ -#endif - -#define UTHASH_VERSION 1.9.8 - -#ifndef uthash_fatal -#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */ -#endif -#ifndef uthash_malloc -#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ -#endif -#ifndef uthash_free -#define uthash_free(ptr,sz) free(ptr) /* free fcn */ -#endif - -#ifndef uthash_noexpand_fyi -#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ -#endif -#ifndef uthash_expand_fyi -#define uthash_expand_fyi(tbl) /* can be defined to log expands */ -#endif - -/* initial number of buckets */ -#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */ -#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */ -#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */ - -/* calculate the element whose hash handle address is hhe */ -#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) - -#define HASH_FIND(hh,head,keyptr,keylen,out) \ -do { \ - unsigned _hf_bkt,_hf_hashv; \ - out=NULL; \ - if (head) { \ - HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \ - if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \ - HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \ - keyptr,keylen,out); \ - } \ - } \ -} while (0) - -#ifdef HASH_BLOOM -#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM) -#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0) -#define HASH_BLOOM_MAKE(tbl) \ -do { \ - (tbl)->bloom_nbits = HASH_BLOOM; \ - (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ - if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \ - memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \ - (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ -} while (0) - -#define HASH_BLOOM_FREE(tbl) \ -do { \ - uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ -} while (0) - -#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8))) -#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8))) - -#define HASH_BLOOM_ADD(tbl,hashv) \ - HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) - -#define HASH_BLOOM_TEST(tbl,hashv) \ - HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) - -#else -#define HASH_BLOOM_MAKE(tbl) -#define HASH_BLOOM_FREE(tbl) -#define HASH_BLOOM_ADD(tbl,hashv) -#define HASH_BLOOM_TEST(tbl,hashv) (1) -#define HASH_BLOOM_BYTELEN 0 -#endif - -#define HASH_MAKE_TABLE(hh,head) \ -do { \ - (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \ - sizeof(UT_hash_table)); \ - if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \ - memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \ - (head)->hh.tbl->tail = &((head)->hh); \ - (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ - (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ - (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ - (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ - HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ - if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \ - memset((head)->hh.tbl->buckets, 0, \ - HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ - HASH_BLOOM_MAKE((head)->hh.tbl); \ - (head)->hh.tbl->signature = HASH_SIGNATURE; \ -} while(0) - -#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ - HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add) - -#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ -do { \ - replaced=NULL; \ - HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced); \ - if (replaced!=NULL) { \ - HASH_DELETE(hh,head,replaced); \ - }; \ - HASH_ADD(hh,head,fieldname,keylen_in,add); \ -} while(0) - -#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ -do { \ - unsigned _ha_bkt; \ - (add)->hh.next = NULL; \ - (add)->hh.key = (char*)(keyptr); \ - (add)->hh.keylen = (unsigned)(keylen_in); \ - if (!(head)) { \ - head = (add); \ - (head)->hh.prev = NULL; \ - HASH_MAKE_TABLE(hh,head); \ - } else { \ - (head)->hh.tbl->tail->next = (add); \ - (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ - (head)->hh.tbl->tail = &((add)->hh); \ - } \ - (head)->hh.tbl->num_items++; \ - (add)->hh.tbl = (head)->hh.tbl; \ - HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \ - (add)->hh.hashv, _ha_bkt); \ - HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \ - HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \ - HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \ - HASH_FSCK(hh,head); \ -} while(0) - -#define HASH_TO_BKT( hashv, num_bkts, bkt ) \ -do { \ - bkt = ((hashv) & ((num_bkts) - 1)); \ -} while(0) - -/* delete "delptr" from the hash table. - * "the usual" patch-up process for the app-order doubly-linked-list. - * The use of _hd_hh_del below deserves special explanation. - * These used to be expressed using (delptr) but that led to a bug - * if someone used the same symbol for the head and deletee, like - * HASH_DELETE(hh,users,users); - * We want that to work, but by changing the head (users) below - * we were forfeiting our ability to further refer to the deletee (users) - * in the patch-up process. Solution: use scratch space to - * copy the deletee pointer, then the latter references are via that - * scratch pointer rather than through the repointed (users) symbol. - */ -#define HASH_DELETE(hh,head,delptr) \ -do { \ - unsigned _hd_bkt; \ - struct UT_hash_handle *_hd_hh_del; \ - if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \ - uthash_free((head)->hh.tbl->buckets, \ - (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ - HASH_BLOOM_FREE((head)->hh.tbl); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - head = NULL; \ - } else { \ - _hd_hh_del = &((delptr)->hh); \ - if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \ - (head)->hh.tbl->tail = \ - (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ - (head)->hh.tbl->hho); \ - } \ - if ((delptr)->hh.prev) { \ - ((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ - (head)->hh.tbl->hho))->next = (delptr)->hh.next; \ - } else { \ - DECLTYPE_ASSIGN(head,(delptr)->hh.next); \ - } \ - if (_hd_hh_del->next) { \ - ((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \ - (head)->hh.tbl->hho))->prev = \ - _hd_hh_del->prev; \ - } \ - HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ - HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ - (head)->hh.tbl->num_items--; \ - } \ - HASH_FSCK(hh,head); \ -} while (0) - - -/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ -#define HASH_FIND_STR(head,findstr,out) \ - HASH_FIND(hh,head,findstr,strlen(findstr),out) -#define HASH_ADD_STR(head,strfield,add) \ - HASH_ADD(hh,head,strfield,strlen(add->strfield),add) -#define HASH_REPLACE_STR(head,strfield,add,replaced) \ - HASH_REPLACE(hh,head,strfield,strlen(add->strfield),add,replaced) -#define HASH_FIND_INT(head,findint,out) \ - HASH_FIND(hh,head,findint,sizeof(int),out) -#define HASH_ADD_INT(head,intfield,add) \ - HASH_ADD(hh,head,intfield,sizeof(int),add) -#define HASH_REPLACE_INT(head,intfield,add,replaced) \ - HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) -#define HASH_FIND_PTR(head,findptr,out) \ - HASH_FIND(hh,head,findptr,sizeof(void *),out) -#define HASH_ADD_PTR(head,ptrfield,add) \ - HASH_ADD(hh,head,ptrfield,sizeof(void *),add) -#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \ - HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) -#define HASH_DEL(head,delptr) \ - HASH_DELETE(hh,head,delptr) - -/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. - * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. - */ -#ifdef HASH_DEBUG -#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) -#define HASH_FSCK(hh,head) \ -do { \ - unsigned _bkt_i; \ - unsigned _count, _bkt_count; \ - char *_prev; \ - struct UT_hash_handle *_thh; \ - if (head) { \ - _count = 0; \ - for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \ - _bkt_count = 0; \ - _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ - _prev = NULL; \ - while (_thh) { \ - if (_prev != (char*)(_thh->hh_prev)) { \ - HASH_OOPS("invalid hh_prev %p, actual %p\n", \ - _thh->hh_prev, _prev ); \ - } \ - _bkt_count++; \ - _prev = (char*)(_thh); \ - _thh = _thh->hh_next; \ - } \ - _count += _bkt_count; \ - if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ - HASH_OOPS("invalid bucket count %d, actual %d\n", \ - (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ - } \ - } \ - if (_count != (head)->hh.tbl->num_items) { \ - HASH_OOPS("invalid hh item count %d, actual %d\n", \ - (head)->hh.tbl->num_items, _count ); \ - } \ - /* traverse hh in app order; check next/prev integrity, count */ \ - _count = 0; \ - _prev = NULL; \ - _thh = &(head)->hh; \ - while (_thh) { \ - _count++; \ - if (_prev !=(char*)(_thh->prev)) { \ - HASH_OOPS("invalid prev %p, actual %p\n", \ - _thh->prev, _prev ); \ - } \ - _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ - _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \ - (head)->hh.tbl->hho) : NULL ); \ - } \ - if (_count != (head)->hh.tbl->num_items) { \ - HASH_OOPS("invalid app item count %d, actual %d\n", \ - (head)->hh.tbl->num_items, _count ); \ - } \ - } \ -} while (0) -#else -#define HASH_FSCK(hh,head) -#endif - -/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to - * the descriptor to which this macro is defined for tuning the hash function. - * The app can #include <unistd.h> to get the prototype for write(2). */ -#ifdef HASH_EMIT_KEYS -#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ -do { \ - unsigned _klen = fieldlen; \ - write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ - write(HASH_EMIT_KEYS, keyptr, fieldlen); \ -} while (0) -#else -#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) -#endif - -/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ -#ifdef HASH_FUNCTION -#define HASH_FCN HASH_FUNCTION -#else -#define HASH_FCN HASH_JEN -#endif - -/* The Bernstein hash function, used in Perl prior to v5.6 */ -#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _hb_keylen=keylen; \ - char *_hb_key=(char*)(key); \ - (hashv) = 0; \ - while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \ - bkt = (hashv) & (num_bkts-1); \ -} while (0) - - -/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at - * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ -#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _sx_i; \ - char *_hs_key=(char*)(key); \ - hashv = 0; \ - for(_sx_i=0; _sx_i < keylen; _sx_i++) \ - hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ - bkt = hashv & (num_bkts-1); \ -} while (0) - -#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _fn_i; \ - char *_hf_key=(char*)(key); \ - hashv = 2166136261UL; \ - for(_fn_i=0; _fn_i < keylen; _fn_i++) \ - hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _ho_i; \ - char *_ho_key=(char*)(key); \ - hashv = 0; \ - for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ - hashv += _ho_key[_ho_i]; \ - hashv += (hashv << 10); \ - hashv ^= (hashv >> 6); \ - } \ - hashv += (hashv << 3); \ - hashv ^= (hashv >> 11); \ - hashv += (hashv << 15); \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -#define HASH_JEN_MIX(a,b,c) \ -do { \ - a -= b; a -= c; a ^= ( c >> 13 ); \ - b -= c; b -= a; b ^= ( a << 8 ); \ - c -= a; c -= b; c ^= ( b >> 13 ); \ - a -= b; a -= c; a ^= ( c >> 12 ); \ - b -= c; b -= a; b ^= ( a << 16 ); \ - c -= a; c -= b; c ^= ( b >> 5 ); \ - a -= b; a -= c; a ^= ( c >> 3 ); \ - b -= c; b -= a; b ^= ( a << 10 ); \ - c -= a; c -= b; c ^= ( b >> 15 ); \ -} while (0) - -#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _hj_i,_hj_j,_hj_k; \ - unsigned char *_hj_key=(unsigned char*)(key); \ - hashv = 0xfeedbeef; \ - _hj_i = _hj_j = 0x9e3779b9; \ - _hj_k = (unsigned)(keylen); \ - while (_hj_k >= 12) { \ - _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ - + ( (unsigned)_hj_key[2] << 16 ) \ - + ( (unsigned)_hj_key[3] << 24 ) ); \ - _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ - + ( (unsigned)_hj_key[6] << 16 ) \ - + ( (unsigned)_hj_key[7] << 24 ) ); \ - hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ - + ( (unsigned)_hj_key[10] << 16 ) \ - + ( (unsigned)_hj_key[11] << 24 ) ); \ - \ - HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ - \ - _hj_key += 12; \ - _hj_k -= 12; \ - } \ - hashv += keylen; \ - switch ( _hj_k ) { \ - case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \ - case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \ - case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \ - case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \ - case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \ - case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \ - case 5: _hj_j += _hj_key[4]; \ - case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \ - case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \ - case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \ - case 1: _hj_i += _hj_key[0]; \ - } \ - HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -/* The Paul Hsieh hash function */ -#undef get16bits -#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ - || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) -#define get16bits(d) (*((const uint16_t *) (d))) -#endif - -#if !defined (get16bits) -#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ - +(uint32_t)(((const uint8_t *)(d))[0]) ) -#endif -#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned char *_sfh_key=(unsigned char*)(key); \ - uint32_t _sfh_tmp, _sfh_len = keylen; \ - \ - int _sfh_rem = _sfh_len & 3; \ - _sfh_len >>= 2; \ - hashv = 0xcafebabe; \ - \ - /* Main loop */ \ - for (;_sfh_len > 0; _sfh_len--) { \ - hashv += get16bits (_sfh_key); \ - _sfh_tmp = (uint32_t)(get16bits (_sfh_key+2)) << 11 ^ hashv; \ - hashv = (hashv << 16) ^ _sfh_tmp; \ - _sfh_key += 2*sizeof (uint16_t); \ - hashv += hashv >> 11; \ - } \ - \ - /* Handle end cases */ \ - switch (_sfh_rem) { \ - case 3: hashv += get16bits (_sfh_key); \ - hashv ^= hashv << 16; \ - hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)] << 18); \ - hashv += hashv >> 11; \ - break; \ - case 2: hashv += get16bits (_sfh_key); \ - hashv ^= hashv << 11; \ - hashv += hashv >> 17; \ - break; \ - case 1: hashv += *_sfh_key; \ - hashv ^= hashv << 10; \ - hashv += hashv >> 1; \ - } \ - \ - /* Force "avalanching" of final 127 bits */ \ - hashv ^= hashv << 3; \ - hashv += hashv >> 5; \ - hashv ^= hashv << 4; \ - hashv += hashv >> 17; \ - hashv ^= hashv << 25; \ - hashv += hashv >> 6; \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -#ifdef HASH_USING_NO_STRICT_ALIASING -/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads. - * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error. - * MurmurHash uses the faster approach only on CPU's where we know it's safe. - * - * Note the preprocessor built-in defines can be emitted using: - * - * gcc -m64 -dM -E - < /dev/null (on gcc) - * cc -## a.c (where a.c is a simple test file) (Sun Studio) - */ -#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86)) -#define MUR_GETBLOCK(p,i) p[i] -#else /* non intel */ -#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0) -#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1) -#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2) -#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3) -#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL)) -#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__)) -#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24)) -#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16)) -#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8)) -#else /* assume little endian non-intel */ -#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24)) -#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16)) -#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8)) -#endif -#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \ - (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \ - (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \ - MUR_ONE_THREE(p)))) -#endif -#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) -#define MUR_FMIX(_h) \ -do { \ - _h ^= _h >> 16; \ - _h *= 0x85ebca6b; \ - _h ^= _h >> 13; \ - _h *= 0xc2b2ae35l; \ - _h ^= _h >> 16; \ -} while(0) - -#define HASH_MUR(key,keylen,num_bkts,hashv,bkt) \ -do { \ - const uint8_t *_mur_data = (const uint8_t*)(key); \ - const int _mur_nblocks = (keylen) / 4; \ - uint32_t _mur_h1 = 0xf88D5353; \ - uint32_t _mur_c1 = 0xcc9e2d51; \ - uint32_t _mur_c2 = 0x1b873593; \ - uint32_t _mur_k1 = 0; \ - const uint8_t *_mur_tail; \ - const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \ - int _mur_i; \ - for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) { \ - _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \ - _mur_k1 *= _mur_c1; \ - _mur_k1 = MUR_ROTL32(_mur_k1,15); \ - _mur_k1 *= _mur_c2; \ - \ - _mur_h1 ^= _mur_k1; \ - _mur_h1 = MUR_ROTL32(_mur_h1,13); \ - _mur_h1 = _mur_h1*5+0xe6546b64; \ - } \ - _mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \ - _mur_k1=0; \ - switch((keylen) & 3) { \ - case 3: _mur_k1 ^= _mur_tail[2] << 16; \ - case 2: _mur_k1 ^= _mur_tail[1] << 8; \ - case 1: _mur_k1 ^= _mur_tail[0]; \ - _mur_k1 *= _mur_c1; \ - _mur_k1 = MUR_ROTL32(_mur_k1,15); \ - _mur_k1 *= _mur_c2; \ - _mur_h1 ^= _mur_k1; \ - } \ - _mur_h1 ^= (keylen); \ - MUR_FMIX(_mur_h1); \ - hashv = _mur_h1; \ - bkt = hashv & (num_bkts-1); \ -} while(0) -#endif /* HASH_USING_NO_STRICT_ALIASING */ - -/* key comparison function; return 0 if keys equal */ -#define HASH_KEYCMP(a,b,len) memcmp(a,b,len) - -/* iterate over items in a known bucket to find desired item */ -#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \ -do { \ - if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \ - else out=NULL; \ - while (out) { \ - if ((out)->hh.keylen == keylen_in) { \ - if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) break; \ - } \ - if ((out)->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); \ - else out = NULL; \ - } \ -} while(0) - -/* add an item to a bucket */ -#define HASH_ADD_TO_BKT(head,addhh) \ -do { \ - head.count++; \ - (addhh)->hh_next = head.hh_head; \ - (addhh)->hh_prev = NULL; \ - if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \ - (head).hh_head=addhh; \ - if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \ - && (addhh)->tbl->noexpand != 1) { \ - HASH_EXPAND_BUCKETS((addhh)->tbl); \ - } \ -} while(0) - -/* remove an item from a given bucket */ -#define HASH_DEL_IN_BKT(hh,head,hh_del) \ - (head).count--; \ - if ((head).hh_head == hh_del) { \ - (head).hh_head = hh_del->hh_next; \ - } \ - if (hh_del->hh_prev) { \ - hh_del->hh_prev->hh_next = hh_del->hh_next; \ - } \ - if (hh_del->hh_next) { \ - hh_del->hh_next->hh_prev = hh_del->hh_prev; \ - } - -/* Bucket expansion has the effect of doubling the number of buckets - * and redistributing the items into the new buckets. Ideally the - * items will distribute more or less evenly into the new buckets - * (the extent to which this is true is a measure of the quality of - * the hash function as it applies to the key domain). - * - * With the items distributed into more buckets, the chain length - * (item count) in each bucket is reduced. Thus by expanding buckets - * the hash keeps a bound on the chain length. This bounded chain - * length is the essence of how a hash provides constant time lookup. - * - * The calculation of tbl->ideal_chain_maxlen below deserves some - * explanation. First, keep in mind that we're calculating the ideal - * maximum chain length based on the *new* (doubled) bucket count. - * In fractions this is just n/b (n=number of items,b=new num buckets). - * Since the ideal chain length is an integer, we want to calculate - * ceil(n/b). We don't depend on floating point arithmetic in this - * hash, so to calculate ceil(n/b) with integers we could write - * - * ceil(n/b) = (n/b) + ((n%b)?1:0) - * - * and in fact a previous version of this hash did just that. - * But now we have improved things a bit by recognizing that b is - * always a power of two. We keep its base 2 log handy (call it lb), - * so now we can write this with a bit shift and logical AND: - * - * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) - * - */ -#define HASH_EXPAND_BUCKETS(tbl) \ -do { \ - unsigned _he_bkt; \ - unsigned _he_bkt_i; \ - struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ - UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ - _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ - 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ - if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \ - memset(_he_new_buckets, 0, \ - 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ - tbl->ideal_chain_maxlen = \ - (tbl->num_items >> (tbl->log2_num_buckets+1)) + \ - ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \ - tbl->nonideal_items = 0; \ - for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \ - { \ - _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \ - while (_he_thh) { \ - _he_hh_nxt = _he_thh->hh_next; \ - HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \ - _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \ - if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \ - tbl->nonideal_items++; \ - _he_newbkt->expand_mult = _he_newbkt->count / \ - tbl->ideal_chain_maxlen; \ - } \ - _he_thh->hh_prev = NULL; \ - _he_thh->hh_next = _he_newbkt->hh_head; \ - if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \ - _he_thh; \ - _he_newbkt->hh_head = _he_thh; \ - _he_thh = _he_hh_nxt; \ - } \ - } \ - uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ - tbl->num_buckets *= 2; \ - tbl->log2_num_buckets++; \ - tbl->buckets = _he_new_buckets; \ - tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \ - (tbl->ineff_expands+1) : 0; \ - if (tbl->ineff_expands > 1) { \ - tbl->noexpand=1; \ - uthash_noexpand_fyi(tbl); \ - } \ - uthash_expand_fyi(tbl); \ -} while(0) - - -/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ -/* Note that HASH_SORT assumes the hash handle name to be hh. - * HASH_SRT was added to allow the hash handle name to be passed in. */ -#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) -#define HASH_SRT(hh,head,cmpfcn) \ -do { \ - unsigned _hs_i; \ - unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ - struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ - if (head) { \ - _hs_insize = 1; \ - _hs_looping = 1; \ - _hs_list = &((head)->hh); \ - while (_hs_looping) { \ - _hs_p = _hs_list; \ - _hs_list = NULL; \ - _hs_tail = NULL; \ - _hs_nmerges = 0; \ - while (_hs_p) { \ - _hs_nmerges++; \ - _hs_q = _hs_p; \ - _hs_psize = 0; \ - for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \ - _hs_psize++; \ - _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ - ((void*)((char*)(_hs_q->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - if (! (_hs_q) ) break; \ - } \ - _hs_qsize = _hs_insize; \ - while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \ - if (_hs_psize == 0) { \ - _hs_e = _hs_q; \ - _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ - ((void*)((char*)(_hs_q->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - _hs_qsize--; \ - } else if ( (_hs_qsize == 0) || !(_hs_q) ) { \ - _hs_e = _hs_p; \ - if (_hs_p){ \ - _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ - ((void*)((char*)(_hs_p->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - } \ - _hs_psize--; \ - } else if (( \ - cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \ - DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \ - ) <= 0) { \ - _hs_e = _hs_p; \ - if (_hs_p){ \ - _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ - ((void*)((char*)(_hs_p->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - } \ - _hs_psize--; \ - } else { \ - _hs_e = _hs_q; \ - _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ - ((void*)((char*)(_hs_q->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - _hs_qsize--; \ - } \ - if ( _hs_tail ) { \ - _hs_tail->next = ((_hs_e) ? \ - ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \ - } else { \ - _hs_list = _hs_e; \ - } \ - if (_hs_e) { \ - _hs_e->prev = ((_hs_tail) ? \ - ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \ - } \ - _hs_tail = _hs_e; \ - } \ - _hs_p = _hs_q; \ - } \ - if (_hs_tail){ \ - _hs_tail->next = NULL; \ - } \ - if ( _hs_nmerges <= 1 ) { \ - _hs_looping=0; \ - (head)->hh.tbl->tail = _hs_tail; \ - DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ - } \ - _hs_insize *= 2; \ - } \ - HASH_FSCK(hh,head); \ - } \ -} while (0) - -/* This function selects items from one hash into another hash. - * The end result is that the selected items have dual presence - * in both hashes. There is no copy of the items made; rather - * they are added into the new hash through a secondary hash - * hash handle that must be present in the structure. */ -#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ -do { \ - unsigned _src_bkt, _dst_bkt; \ - void *_last_elt=NULL, *_elt; \ - UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ - ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ - if (src) { \ - for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ - for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ - _src_hh; \ - _src_hh = _src_hh->hh_next) { \ - _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ - if (cond(_elt)) { \ - _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ - _dst_hh->key = _src_hh->key; \ - _dst_hh->keylen = _src_hh->keylen; \ - _dst_hh->hashv = _src_hh->hashv; \ - _dst_hh->prev = _last_elt; \ - _dst_hh->next = NULL; \ - if (_last_elt_hh) { _last_elt_hh->next = _elt; } \ - if (!dst) { \ - DECLTYPE_ASSIGN(dst,_elt); \ - HASH_MAKE_TABLE(hh_dst,dst); \ - } else { \ - _dst_hh->tbl = (dst)->hh_dst.tbl; \ - } \ - HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ - HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \ - (dst)->hh_dst.tbl->num_items++; \ - _last_elt = _elt; \ - _last_elt_hh = _dst_hh; \ - } \ - } \ - } \ - } \ - HASH_FSCK(hh_dst,dst); \ -} while (0) - -#define HASH_CLEAR(hh,head) \ -do { \ - if (head) { \ - uthash_free((head)->hh.tbl->buckets, \ - (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ - HASH_BLOOM_FREE((head)->hh.tbl); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - (head)=NULL; \ - } \ -} while(0) - -#define HASH_OVERHEAD(hh,head) \ - (size_t)((((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ - ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ - (sizeof(UT_hash_table)) + \ - (HASH_BLOOM_BYTELEN))) - -#ifdef NO_DECLTYPE -#define HASH_ITER(hh,head,el,tmp) \ -for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \ - el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL)) -#else -#define HASH_ITER(hh,head,el,tmp) \ -for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \ - el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL)) -#endif - -/* obtain a count of items in the hash */ -#define HASH_COUNT(head) HASH_CNT(hh,head) -#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0) - -typedef struct UT_hash_bucket { - struct UT_hash_handle *hh_head; - unsigned count; - - /* expand_mult is normally set to 0. In this situation, the max chain length - * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If - * the bucket's chain exceeds this length, bucket expansion is triggered). - * However, setting expand_mult to a non-zero value delays bucket expansion - * (that would be triggered by additions to this particular bucket) - * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. - * (The multiplier is simply expand_mult+1). The whole idea of this - * multiplier is to reduce bucket expansions, since they are expensive, in - * situations where we know that a particular bucket tends to be overused. - * It is better to let its chain length grow to a longer yet-still-bounded - * value, than to do an O(n) bucket expansion too often. - */ - unsigned expand_mult; - -} UT_hash_bucket; - -/* random signature used only to find hash tables in external analysis */ -#define HASH_SIGNATURE 0xa0111fe1 -#define HASH_BLOOM_SIGNATURE 0xb12220f2 - -typedef struct UT_hash_table { - UT_hash_bucket *buckets; - unsigned num_buckets, log2_num_buckets; - unsigned num_items; - struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ - ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ - - /* in an ideal situation (all buckets used equally), no bucket would have - * more than ceil(#items/#buckets) items. that's the ideal chain length. */ - unsigned ideal_chain_maxlen; - - /* nonideal_items is the number of items in the hash whose chain position - * exceeds the ideal chain maxlen. these items pay the penalty for an uneven - * hash distribution; reaching them in a chain traversal takes >ideal steps */ - unsigned nonideal_items; - - /* ineffective expands occur when a bucket doubling was performed, but - * afterward, more than half the items in the hash had nonideal chain - * positions. If this happens on two consecutive expansions we inhibit any - * further expansion, as it's not helping; this happens when the hash - * function isn't a good fit for the key domain. When expansion is inhibited - * the hash will still work, albeit no longer in constant time. */ - unsigned ineff_expands, noexpand; - - uint32_t signature; /* used only to find hash tables in external analysis */ -#ifdef HASH_BLOOM - uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ - uint8_t *bloom_bv; - char bloom_nbits; -#endif - -} UT_hash_table; - -typedef struct UT_hash_handle { - struct UT_hash_table *tbl; - void *prev; /* prev element in app order */ - void *next; /* next element in app order */ - struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ - struct UT_hash_handle *hh_next; /* next hh in bucket order */ - void *key; /* ptr to enclosing struct's key */ - unsigned keylen; /* enclosing struct's key len */ - unsigned hashv; /* result of hash-fcn(key) */ -} UT_hash_handle; - -#endif /* UTHASH_H */ |