From 3963b3ec58fb792e43833696493f69ce6596289e Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 10:24:26 -0400 Subject: [PATCH 01/29] FIXED: Lex space followed by tab as space, not text --- Sources/libMultiMarkdown/lexer.c | 370 +++++++++++++++--------------- Sources/libMultiMarkdown/lexer.re | 1 + 2 files changed, 189 insertions(+), 182 deletions(-) diff --git a/Sources/libMultiMarkdown/lexer.c b/Sources/libMultiMarkdown/lexer.c index 9622db53..d2c41cc7 100644 --- a/Sources/libMultiMarkdown/lexer.c +++ b/Sources/libMultiMarkdown/lexer.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.14.3 on Fri Mar 10 13:21:57 2017 */ +/* Generated by re2c 0.14.3 on Tue Mar 14 10:21:05 2017 */ /** MultiMarkdown 6 -- Lightweight markup processor to produce HTML, LaTeX, and more. @@ -132,12 +132,12 @@ int scan(Scanner * s, const char * stop) { yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); switch (yych) { - case '+': goto yy264; - case '-': goto yy263; - case '=': goto yy260; - case '>': goto yy262; - case '{': goto yy258; - case '~': goto yy261; + case '+': goto yy266; + case '-': goto yy265; + case '=': goto yy262; + case '>': goto yy264; + case '{': goto yy260; + case '~': goto yy263; default: goto yy3; } yy3: @@ -146,7 +146,7 @@ int scan(Scanner * s, const char * stop) { yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); switch (yych) { - case '+': goto yy255; + case '+': goto yy257; default: goto yy5; } yy5: @@ -154,7 +154,7 @@ int scan(Scanner * s, const char * stop) { yy6: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '-': goto yy249; + case '-': goto yy251; default: goto yy7; } yy7: @@ -163,7 +163,7 @@ int scan(Scanner * s, const char * stop) { yyaccept = 2; yych = *(YYMARKER = ++YYCURSOR); switch (yych) { - case '<': goto yy246; + case '<': goto yy248; default: goto yy9; } yy9: @@ -172,8 +172,8 @@ int scan(Scanner * s, const char * stop) { yyaccept = 3; yych = *(YYMARKER = ++YYCURSOR); switch (yych) { - case '>': goto yy242; - case '~': goto yy241; + case '>': goto yy244; + case '~': goto yy243; default: goto yy11; } yy11: @@ -182,7 +182,7 @@ int scan(Scanner * s, const char * stop) { yyaccept = 4; yych = *(YYMARKER = ++YYCURSOR); switch (yych) { - case '=': goto yy238; + case '=': goto yy240; default: goto yy13; } yy13: @@ -190,11 +190,11 @@ int scan(Scanner * s, const char * stop) { yy14: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '#': goto yy234; - case '%': goto yy228; - case '>': goto yy236; - case '?': goto yy230; - case '^': goto yy232; + case '#': goto yy236; + case '%': goto yy230; + case '>': goto yy238; + case '?': goto yy232; + case '^': goto yy234; default: goto yy15; } yy15: @@ -205,7 +205,7 @@ int scan(Scanner * s, const char * stop) { yy18: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '[': goto yy226; + case '[': goto yy228; default: goto yy19; } yy19: @@ -222,7 +222,7 @@ int scan(Scanner * s, const char * stop) { yy26: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '}': goto yy224; + case '}': goto yy226; default: goto yy27; } yy27: @@ -233,7 +233,7 @@ int scan(Scanner * s, const char * stop) { yy30: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '\'': goto yy222; + case '\'': goto yy224; default: goto yy31; } yy31: @@ -242,8 +242,8 @@ int scan(Scanner * s, const char * stop) { yyaccept = 5; yych = *(YYMARKER = ++YYCURSOR); switch (yych) { - case ' ': goto yy214; - case '.': goto yy215; + case ' ': goto yy216; + case '.': goto yy217; default: goto yy19; } yy33: @@ -254,7 +254,7 @@ int scan(Scanner * s, const char * stop) { yych = *(YYMARKER = ++YYCURSOR); switch (yych) { case 'A': - case 'a': goto yy209; + case 'a': goto yy211; default: goto yy36; } yy36: @@ -265,41 +265,41 @@ int scan(Scanner * s, const char * stop) { yy39: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '\n': goto yy132; - case '\r': goto yy134; - case ' ': goto yy137; - case '!': goto yy197; - case '"': goto yy187; - case '#': goto yy167; - case '$': goto yy165; - case '%': goto yy163; - case '&': goto yy151; - case '\'': goto yy185; - case '(': goto yy179; - case ')': goto yy177; - case '*': goto yy143; - case '+': goto yy161; - case ',': goto yy193; - case '-': goto yy159; - case '.': goto yy199; - case '/': goto yy147; - case ':': goto yy189; - case ';': goto yy191; - case '<': goto yy155; - case '=': goto yy157; - case '>': goto yy153; - case '?': goto yy195; - case '@': goto yy149; - case '[': goto yy171; - case '\\': goto yy135; - case ']': goto yy169; - case '^': goto yy145; - case '_': goto yy141; - case '`': goto yy183; - case '{': goto yy175; - case '|': goto yy139; - case '}': goto yy173; - case '~': goto yy181; + case '\n': goto yy134; + case '\r': goto yy136; + case ' ': goto yy139; + case '!': goto yy199; + case '"': goto yy189; + case '#': goto yy169; + case '$': goto yy167; + case '%': goto yy165; + case '&': goto yy153; + case '\'': goto yy187; + case '(': goto yy181; + case ')': goto yy179; + case '*': goto yy145; + case '+': goto yy163; + case ',': goto yy195; + case '-': goto yy161; + case '.': goto yy201; + case '/': goto yy149; + case ':': goto yy191; + case ';': goto yy193; + case '<': goto yy157; + case '=': goto yy159; + case '>': goto yy155; + case '?': goto yy197; + case '@': goto yy151; + case '[': goto yy173; + case '\\': goto yy137; + case ']': goto yy171; + case '^': goto yy147; + case '_': goto yy143; + case '`': goto yy185; + case '{': goto yy177; + case '|': goto yy141; + case '}': goto yy175; + case '~': goto yy183; default: goto yy40; } yy40: @@ -307,7 +307,7 @@ int scan(Scanner * s, const char * stop) { yy41: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '$': goto yy130; + case '$': goto yy132; default: goto yy42; } yy42: @@ -319,11 +319,13 @@ int scan(Scanner * s, const char * stop) { ++YYCURSOR; { return INDENT_TAB; } yy47: + YYCTXMARKER = YYCURSOR + 1; yych = *++YYCURSOR; switch (yych) { + case '\t': goto yy119; case '\n': goto yy53; - case '\r': goto yy121; - case ' ': goto yy119; + case '\r': goto yy123; + case ' ': goto yy121; default: goto yy19; } yy48: @@ -428,8 +430,8 @@ int scan(Scanner * s, const char * stop) { case 5: goto yy19; case 6: goto yy36; case 7: goto yy49; - case 8: goto yy127; - default: goto yy259; + case 8: goto yy129; + default: goto yy261; } yy71: ++YYCURSOR; @@ -666,85 +668,86 @@ int scan(Scanner * s, const char * stop) { default: goto yy117; } yy119: + ++YYCURSOR; + YYCURSOR = YYCTXMARKER; + { return NON_INDENT_SPACE; } +yy121: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '\n': goto yy123; - case '\r': goto yy125; - case ' ': goto yy122; - default: goto yy120; + case '\n': goto yy125; + case '\r': goto yy127; + case ' ': goto yy124; + default: goto yy122; } -yy120: +yy122: { return NON_INDENT_SPACE; } -yy121: +yy123: yych = *++YYCURSOR; switch (yych) { case '\n': goto yy53; default: goto yy54; } -yy122: +yy124: yych = *++YYCURSOR; switch (yych) { - case '\n': goto yy123; - case '\r': goto yy125; - case ' ': goto yy126; - default: goto yy120; + case '\n': goto yy125; + case '\r': goto yy127; + case ' ': goto yy128; + default: goto yy122; } -yy123: +yy125: ++YYCURSOR; -yy124: +yy126: { return TEXT_LINEBREAK; } -yy125: +yy127: yych = *++YYCURSOR; switch (yych) { - case '\n': goto yy123; - default: goto yy124; + case '\n': goto yy125; + default: goto yy126; } -yy126: +yy128: yyaccept = 8; yych = *(YYMARKER = ++YYCURSOR); switch (yych) { - case '\n': goto yy123; - case '\r': goto yy125; - case ' ': goto yy128; - default: goto yy127; + case '\n': goto yy125; + case '\r': goto yy127; + case ' ': goto yy130; + default: goto yy129; } -yy127: +yy129: { return INDENT_SPACE; } -yy128: +yy130: ++YYCURSOR; yych = *YYCURSOR; switch (yych) { - case '\n': goto yy123; - case '\r': goto yy125; - case ' ': goto yy128; + case '\n': goto yy125; + case '\r': goto yy127; + case ' ': goto yy130; default: goto yy70; } -yy130: +yy132: ++YYCURSOR; { return MATH_DOLLAR_DOUBLE; } -yy132: +yy134: ++YYCURSOR; -yy133: +yy135: { return TEXT_LINEBREAK; } -yy134: +yy136: yych = *++YYCURSOR; switch (yych) { - case '\n': goto yy132; - default: goto yy133; + case '\n': goto yy134; + default: goto yy135; } -yy135: +yy137: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '(': goto yy201; - case ')': goto yy203; - case '[': goto yy205; - case ']': goto yy207; - default: goto yy136; + case '(': goto yy203; + case ')': goto yy205; + case '[': goto yy207; + case ']': goto yy209; + default: goto yy138; } -yy136: - { return ESCAPED_CHARACTER; } -yy137: - ++YYCURSOR; +yy138: { return ESCAPED_CHARACTER; } yy139: ++YYCURSOR; @@ -841,226 +844,229 @@ int scan(Scanner * s, const char * stop) { { return ESCAPED_CHARACTER; } yy201: ++YYCURSOR; - { return MATH_PAREN_OPEN; } + { return ESCAPED_CHARACTER; } yy203: ++YYCURSOR; - { return MATH_PAREN_CLOSE; } + { return MATH_PAREN_OPEN; } yy205: ++YYCURSOR; - { return MATH_BRACKET_OPEN; } + { return MATH_PAREN_CLOSE; } yy207: ++YYCURSOR; - { return MATH_BRACKET_CLOSE; } + { return MATH_BRACKET_OPEN; } yy209: + ++YYCURSOR; + { return MATH_BRACKET_CLOSE; } +yy211: yych = *++YYCURSOR; switch (yych) { case 'M': - case 'm': goto yy210; + case 'm': goto yy212; default: goto yy70; } -yy210: +yy212: yych = *++YYCURSOR; switch (yych) { case 'P': - case 'p': goto yy211; + case 'p': goto yy213; default: goto yy70; } -yy211: +yy213: yych = *++YYCURSOR; switch (yych) { - case ';': goto yy212; + case ';': goto yy214; default: goto yy70; } -yy212: +yy214: ++YYCURSOR; { return AMPERSAND_LONG; } -yy214: +yy216: yych = *++YYCURSOR; switch (yych) { - case '.': goto yy218; + case '.': goto yy220; default: goto yy70; } -yy215: +yy217: yych = *++YYCURSOR; switch (yych) { - case '.': goto yy216; + case '.': goto yy218; default: goto yy70; } -yy216: +yy218: ++YYCURSOR; { return ELLIPSIS; } -yy218: +yy220: yych = *++YYCURSOR; switch (yych) { - case ' ': goto yy219; + case ' ': goto yy221; default: goto yy70; } -yy219: +yy221: yych = *++YYCURSOR; switch (yych) { - case '.': goto yy220; + case '.': goto yy222; default: goto yy70; } -yy220: +yy222: ++YYCURSOR; { return ELLIPSIS; } -yy222: +yy224: ++YYCURSOR; { return QUOTE_RIGHT_ALT; } -yy224: +yy226: ++YYCURSOR; { return BRACE_DOUBLE_RIGHT; } -yy226: +yy228: ++YYCURSOR; { return BRACKET_IMAGE_LEFT; } -yy228: +yy230: ++YYCURSOR; { return BRACKET_VARIABLE_LEFT; } -yy230: +yy232: ++YYCURSOR; { return BRACKET_GLOSSARY_LEFT; } -yy232: +yy234: ++YYCURSOR; { return BRACKET_FOOTNOTE_LEFT; } -yy234: +yy236: ++YYCURSOR; { return BRACKET_CITATION_LEFT; } -yy236: +yy238: ++YYCURSOR; { return BRACKET_ABBREVIATION_LEFT; } -yy238: +yy240: yych = *++YYCURSOR; switch (yych) { - case '}': goto yy239; + case '}': goto yy241; default: goto yy70; } -yy239: +yy241: ++YYCURSOR; { return CRITIC_HI_CLOSE; } -yy241: +yy243: yych = *++YYCURSOR; switch (yych) { - case '}': goto yy244; + case '}': goto yy246; default: goto yy70; } -yy242: +yy244: ++YYCURSOR; { return CRITIC_SUB_DIV; } -yy244: +yy246: ++YYCURSOR; { return CRITIC_SUB_CLOSE; } -yy246: +yy248: yych = *++YYCURSOR; switch (yych) { - case '}': goto yy247; + case '}': goto yy249; default: goto yy70; } -yy247: +yy249: ++YYCURSOR; { return CRITIC_COM_CLOSE; } -yy249: +yy251: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '-': goto yy253; - case '}': goto yy251; - default: goto yy250; + case '-': goto yy255; + case '}': goto yy253; + default: goto yy252; } -yy250: +yy252: { return DASH_N; } -yy251: +yy253: ++YYCURSOR; { return CRITIC_DEL_CLOSE; } -yy253: +yy255: ++YYCURSOR; { return DASH_M; } -yy255: +yy257: yych = *++YYCURSOR; switch (yych) { - case '}': goto yy256; + case '}': goto yy258; default: goto yy70; } -yy256: +yy258: ++YYCURSOR; { return CRITIC_ADD_CLOSE; } -yy258: +yy260: yyaccept = 9; yych = *(YYMARKER = ++YYCURSOR); switch (yych) { - case 'T': goto yy275; - default: goto yy259; + case 'T': goto yy277; + default: goto yy261; } -yy259: +yy261: { return BRACE_DOUBLE_LEFT; } -yy260: +yy262: yych = *++YYCURSOR; switch (yych) { - case '=': goto yy273; + case '=': goto yy275; default: goto yy70; } -yy261: +yy263: yych = *++YYCURSOR; switch (yych) { - case '~': goto yy271; + case '~': goto yy273; default: goto yy70; } -yy262: +yy264: yych = *++YYCURSOR; switch (yych) { - case '>': goto yy269; + case '>': goto yy271; default: goto yy70; } -yy263: +yy265: yych = *++YYCURSOR; switch (yych) { - case '-': goto yy267; + case '-': goto yy269; default: goto yy70; } -yy264: +yy266: yych = *++YYCURSOR; switch (yych) { - case '+': goto yy265; + case '+': goto yy267; default: goto yy70; } -yy265: +yy267: ++YYCURSOR; { return CRITIC_ADD_OPEN; } -yy267: +yy269: ++YYCURSOR; { return CRITIC_DEL_OPEN; } -yy269: +yy271: ++YYCURSOR; { return CRITIC_COM_OPEN; } -yy271: +yy273: ++YYCURSOR; { return CRITIC_SUB_OPEN; } -yy273: +yy275: ++YYCURSOR; { return CRITIC_HI_OPEN; } -yy275: +yy277: yych = *++YYCURSOR; switch (yych) { - case 'O': goto yy276; + case 'O': goto yy278; default: goto yy70; } -yy276: +yy278: yych = *++YYCURSOR; switch (yych) { - case 'C': goto yy277; + case 'C': goto yy279; default: goto yy70; } -yy277: +yy279: yych = *++YYCURSOR; switch (yych) { - case '}': goto yy278; + case '}': goto yy280; default: goto yy70; } -yy278: +yy280: yych = *++YYCURSOR; switch (yych) { - case '}': goto yy279; + case '}': goto yy281; default: goto yy70; } -yy279: +yy281: ++YYCURSOR; { return TOC; } } diff --git a/Sources/libMultiMarkdown/lexer.re b/Sources/libMultiMarkdown/lexer.re index 9648f66f..cba2e0a9 100644 --- a/Sources/libMultiMarkdown/lexer.re +++ b/Sources/libMultiMarkdown/lexer.re @@ -226,6 +226,7 @@ int scan(Scanner * s, const char * stop) { ' '? NL { return TEXT_NL; } NON_INDENT_SPACE { return NON_INDENT_SPACE; } + ' ' / '\t' { return NON_INDENT_SPACE; } "*" { return STAR; } "+" { return PLUS; } From c6748af30b85b06ba579c8179e4efb8723349ad2 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 10:24:50 -0400 Subject: [PATCH 02/29] FIXED: Fix null dereference error in CriticMarkup substitution --- Sources/libMultiMarkdown/html.c | 2 ++ Sources/libMultiMarkdown/latex.c | 2 ++ Sources/libMultiMarkdown/odf.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/Sources/libMultiMarkdown/html.c b/Sources/libMultiMarkdown/html.c index c6bf025e..1e54f6ce 100644 --- a/Sources/libMultiMarkdown/html.c +++ b/Sources/libMultiMarkdown/html.c @@ -1353,6 +1353,7 @@ void mmd_export_token_html(DString * out, const char * source, token * t, scratc break; case PAIR_CRITIC_SUB_DEL: if ((scratch->extensions & EXT_CRITIC) && + (t->next) && (t->next->type == PAIR_CRITIC_SUB_ADD)) { t->child->type = TEXT_EMPTY; t->child->mate->type = TEXT_EMPTY; @@ -1371,6 +1372,7 @@ void mmd_export_token_html(DString * out, const char * source, token * t, scratc break; case PAIR_CRITIC_SUB_ADD: if ((scratch->extensions & EXT_CRITIC) && + (t->prev) && (t->prev->type == PAIR_CRITIC_SUB_DEL)) { t->child->type = TEXT_EMPTY; t->child->mate->type = TEXT_EMPTY; diff --git a/Sources/libMultiMarkdown/latex.c b/Sources/libMultiMarkdown/latex.c index 617f0649..0a287b0b 100644 --- a/Sources/libMultiMarkdown/latex.c +++ b/Sources/libMultiMarkdown/latex.c @@ -1345,6 +1345,7 @@ void mmd_export_token_latex(DString * out, const char * source, token * t, scrat break; case PAIR_CRITIC_SUB_DEL: if ((scratch->extensions & EXT_CRITIC) && + (t->next) && (t->next->type == PAIR_CRITIC_SUB_ADD)) { t->child->type = TEXT_EMPTY; t->child->mate->type = TEXT_EMPTY; @@ -1363,6 +1364,7 @@ void mmd_export_token_latex(DString * out, const char * source, token * t, scrat break; case PAIR_CRITIC_SUB_ADD: if ((scratch->extensions & EXT_CRITIC) && + (t->prev) && (t->prev->type == PAIR_CRITIC_SUB_DEL)) { t->child->type = TEXT_EMPTY; t->child->mate->type = TEXT_EMPTY; diff --git a/Sources/libMultiMarkdown/odf.c b/Sources/libMultiMarkdown/odf.c index a610d7fe..25f4e586 100644 --- a/Sources/libMultiMarkdown/odf.c +++ b/Sources/libMultiMarkdown/odf.c @@ -1331,6 +1331,7 @@ void mmd_export_token_odf(DString * out, const char * source, token * t, scratch break; case PAIR_CRITIC_SUB_DEL: if ((scratch->extensions & EXT_CRITIC) && + (t->next) && (t->next->type == PAIR_CRITIC_SUB_ADD)) { t->child->type = TEXT_EMPTY; t->child->mate->type = TEXT_EMPTY; @@ -1349,6 +1350,7 @@ void mmd_export_token_odf(DString * out, const char * source, token * t, scratch break; case PAIR_CRITIC_SUB_ADD: if ((scratch->extensions & EXT_CRITIC) && + (t->prev) && (t->prev->type == PAIR_CRITIC_SUB_DEL)) { t->child->type = TEXT_EMPTY; t->child->mate->type = TEXT_EMPTY; From 33e63f6c3cd9898ec1e2c97bc024c22be82f13ea Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 10:59:33 -0400 Subject: [PATCH 03/29] FIXED: Fix potential bug with line->block parser --- Sources/libMultiMarkdown/parser.c | 231 ++++++++++++++-------------- Sources/libMultiMarkdown/parser.h | 12 +- Sources/libMultiMarkdown/parser.out | 139 +++++++++-------- Sources/libMultiMarkdown/parser.y | 7 +- test/parser_test.y | 16 +- 5 files changed, 209 insertions(+), 196 deletions(-) diff --git a/Sources/libMultiMarkdown/parser.c b/Sources/libMultiMarkdown/parser.c index 8c4cd996..7926ab19 100644 --- a/Sources/libMultiMarkdown/parser.c +++ b/Sources/libMultiMarkdown/parser.c @@ -108,15 +108,15 @@ typedef union { #define ParseARG_STORE yypParser->engine = engine #define YYFALLBACK 1 #define YYNSTATE 44 -#define YYNRULE 135 +#define YYNRULE 136 #define YY_MAX_SHIFT 43 -#define YY_MIN_SHIFTREDUCE 137 -#define YY_MAX_SHIFTREDUCE 271 -#define YY_MIN_REDUCE 272 -#define YY_MAX_REDUCE 406 -#define YY_ERROR_ACTION 407 -#define YY_ACCEPT_ACTION 408 -#define YY_NO_ACTION 409 +#define YY_MIN_SHIFTREDUCE 138 +#define YY_MAX_SHIFTREDUCE 273 +#define YY_MIN_REDUCE 274 +#define YY_MAX_REDUCE 409 +#define YY_ERROR_ACTION 410 +#define YY_ACCEPT_ACTION 411 +#define YY_NO_ACTION 412 /************* End control #defines *******************************************/ /* Define the yytestcase() macro to be a no-op if is not already defined @@ -188,95 +188,93 @@ typedef union { ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (278) +#define YY_ACTTAB_COUNT (266) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 408, 1, 139, 32, 149, 150, 151, 152, 153, 154, - /* 10 */ 43, 156, 31, 29, 40, 38, 30, 14, 163, 164, - /* 20 */ 165, 42, 218, 13, 13, 29, 241, 227, 228, 270, - /* 30 */ 34, 34, 27, 266, 26, 25, 42, 40, 38, 221, - /* 40 */ 8, 224, 41, 193, 15, 15, 272, 146, 270, 182, - /* 50 */ 16, 270, 266, 227, 228, 266, 255, 140, 141, 142, - /* 60 */ 143, 144, 145, 232, 7, 6, 17, 4, 3, 2, - /* 70 */ 18, 28, 219, 147, 5, 241, 243, 246, 249, 244, - /* 80 */ 247, 250, 261, 146, 224, 167, 16, 270, 189, 227, - /* 90 */ 228, 266, 255, 140, 141, 142, 143, 144, 145, 232, - /* 100 */ 7, 6, 17, 4, 3, 2, 18, 241, 263, 147, - /* 110 */ 5, 241, 243, 246, 249, 244, 247, 250, 261, 138, - /* 120 */ 32, 149, 150, 151, 152, 153, 154, 43, 156, 31, - /* 130 */ 29, 40, 38, 30, 14, 163, 164, 165, 262, 253, - /* 140 */ 254, 186, 29, 251, 37, 37, 256, 34, 34, 27, - /* 150 */ 257, 26, 25, 23, 40, 38, 216, 8, 199, 41, - /* 160 */ 217, 15, 15, 211, 213, 214, 252, 194, 196, 192, - /* 170 */ 195, 197, 253, 254, 28, 198, 251, 9, 42, 9, - /* 180 */ 13, 13, 33, 33, 172, 10, 10, 19, 19, 166, - /* 190 */ 5, 175, 175, 35, 35, 5, 28, 36, 36, 252, - /* 200 */ 190, 187, 188, 191, 28, 39, 39, 10, 10, 19, - /* 210 */ 19, 179, 234, 174, 174, 10, 10, 19, 19, 28, - /* 220 */ 206, 173, 173, 233, 253, 254, 28, 6, 251, 28, - /* 230 */ 10, 10, 19, 19, 28, 7, 180, 180, 166, 20, - /* 240 */ 20, 166, 24, 24, 201, 11, 11, 21, 21, 28, - /* 250 */ 207, 252, 183, 184, 185, 227, 228, 182, 217, 274, - /* 260 */ 12, 12, 22, 22, 274, 202, 274, 274, 274, 274, - /* 270 */ 274, 274, 274, 274, 274, 274, 274, 200, + /* 0 */ 411, 1, 140, 32, 150, 151, 152, 153, 154, 155, + /* 10 */ 43, 157, 30, 29, 40, 38, 31, 14, 164, 165, + /* 20 */ 166, 42, 219, 13, 13, 29, 268, 272, 37, 37, + /* 30 */ 34, 34, 27, 225, 26, 25, 28, 40, 38, 265, + /* 40 */ 8, 242, 41, 194, 15, 15, 274, 147, 167, 20, + /* 50 */ 20, 16, 228, 229, 268, 272, 256, 141, 142, 143, + /* 60 */ 144, 145, 146, 233, 7, 6, 17, 4, 3, 2, + /* 70 */ 18, 264, 28, 148, 5, 242, 244, 247, 250, 245, + /* 80 */ 248, 251, 263, 147, 167, 24, 24, 16, 228, 229, + /* 90 */ 268, 272, 256, 141, 142, 143, 144, 145, 146, 233, + /* 100 */ 7, 6, 17, 4, 3, 2, 18, 33, 33, 148, + /* 110 */ 5, 242, 244, 247, 250, 245, 248, 251, 263, 139, + /* 120 */ 32, 150, 151, 152, 153, 154, 155, 43, 157, 30, + /* 130 */ 29, 40, 38, 31, 14, 164, 165, 166, 254, 255, + /* 140 */ 252, 23, 29, 268, 272, 35, 35, 34, 34, 27, + /* 150 */ 42, 26, 25, 222, 40, 38, 190, 8, 187, 41, + /* 160 */ 200, 15, 15, 28, 220, 253, 195, 197, 193, 196, + /* 170 */ 198, 254, 255, 252, 10, 10, 19, 19, 28, 199, + /* 180 */ 176, 176, 9, 42, 9, 13, 13, 214, 215, 10, + /* 190 */ 10, 19, 19, 228, 229, 175, 175, 28, 253, 191, + /* 200 */ 188, 189, 192, 254, 255, 252, 28, 173, 10, 10, + /* 210 */ 19, 19, 167, 5, 174, 174, 183, 10, 10, 19, + /* 220 */ 19, 228, 229, 181, 181, 28, 259, 36, 36, 257, + /* 230 */ 253, 184, 185, 186, 225, 258, 11, 11, 21, 21, + /* 240 */ 28, 208, 235, 28, 201, 39, 39, 218, 217, 212, + /* 250 */ 5, 12, 12, 22, 22, 234, 203, 168, 180, 242, + /* 260 */ 6, 7, 218, 183, 207, 202, }; static const YYCODETYPE yy_lookahead[] = { /* 0 */ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 10 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 20 */ 58, 80, 81, 82, 83, 63, 29, 7, 8, 5, - /* 30 */ 68, 69, 70, 9, 72, 73, 80, 75, 76, 83, - /* 40 */ 78, 6, 80, 71, 82, 83, 0, 1, 5, 29, - /* 50 */ 4, 5, 9, 7, 8, 9, 10, 11, 12, 13, + /* 20 */ 58, 80, 81, 82, 83, 63, 8, 9, 68, 69, + /* 30 */ 68, 69, 70, 4, 72, 73, 48, 75, 76, 4, + /* 40 */ 78, 29, 80, 71, 82, 83, 0, 1, 60, 61, + /* 50 */ 62, 5, 6, 7, 8, 9, 10, 11, 12, 13, /* 60 */ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - /* 70 */ 24, 48, 29, 27, 28, 29, 30, 31, 32, 33, - /* 80 */ 34, 35, 36, 1, 6, 62, 4, 5, 71, 7, + /* 70 */ 24, 36, 48, 27, 28, 29, 30, 31, 32, 33, + /* 80 */ 34, 35, 36, 1, 60, 61, 62, 5, 6, 7, /* 90 */ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - /* 100 */ 18, 19, 20, 21, 22, 23, 24, 29, 6, 27, + /* 100 */ 18, 19, 20, 21, 22, 23, 24, 59, 60, 27, /* 110 */ 28, 29, 30, 31, 32, 33, 34, 35, 36, 40, /* 120 */ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - /* 130 */ 51, 52, 53, 54, 55, 56, 57, 58, 36, 2, - /* 140 */ 3, 71, 63, 6, 68, 69, 6, 68, 69, 70, - /* 150 */ 10, 72, 73, 63, 75, 76, 5, 78, 63, 80, - /* 160 */ 9, 82, 83, 77, 2, 3, 29, 30, 31, 32, - /* 170 */ 33, 34, 2, 3, 48, 74, 6, 79, 80, 81, - /* 180 */ 82, 83, 59, 60, 67, 59, 60, 61, 62, 60, - /* 190 */ 28, 65, 66, 59, 60, 28, 48, 59, 60, 29, - /* 200 */ 30, 31, 32, 33, 48, 59, 60, 59, 60, 61, - /* 210 */ 62, 69, 6, 65, 66, 59, 60, 61, 62, 48, - /* 220 */ 76, 65, 66, 17, 2, 3, 48, 19, 6, 48, - /* 230 */ 59, 60, 61, 62, 48, 18, 65, 66, 60, 61, - /* 240 */ 62, 60, 61, 62, 75, 59, 60, 61, 62, 48, - /* 250 */ 64, 29, 30, 31, 32, 7, 8, 29, 9, 84, - /* 260 */ 59, 60, 61, 62, 84, 64, 84, 84, 84, 84, - /* 270 */ 84, 84, 84, 84, 84, 84, 84, 29, + /* 130 */ 51, 52, 53, 54, 55, 56, 57, 58, 2, 3, + /* 140 */ 4, 63, 63, 8, 9, 59, 60, 68, 69, 70, + /* 150 */ 80, 72, 73, 83, 75, 76, 71, 78, 71, 80, + /* 160 */ 63, 82, 83, 48, 29, 29, 30, 31, 32, 33, + /* 170 */ 34, 2, 3, 4, 59, 60, 61, 62, 48, 74, + /* 180 */ 65, 66, 79, 80, 81, 82, 83, 2, 3, 59, + /* 190 */ 60, 61, 62, 6, 7, 65, 66, 48, 29, 30, + /* 200 */ 31, 32, 33, 2, 3, 4, 48, 67, 59, 60, + /* 210 */ 61, 62, 60, 28, 65, 66, 29, 59, 60, 61, + /* 220 */ 62, 6, 7, 65, 66, 48, 1, 59, 60, 4, + /* 230 */ 29, 30, 31, 32, 4, 10, 59, 60, 61, 62, + /* 240 */ 48, 64, 4, 48, 29, 59, 60, 8, 9, 77, + /* 250 */ 28, 59, 60, 61, 62, 17, 64, 62, 69, 29, + /* 260 */ 19, 18, 8, 29, 76, 75, }; -#define YY_SHIFT_USE_DFLT (278) +#define YY_SHIFT_USE_DFLT (266) #define YY_SHIFT_COUNT (43) -#define YY_SHIFT_MIN (-3) -#define YY_SHIFT_MAX (249) -static const short yy_shift_ofst[] = { - /* 0 */ 82, 46, 78, 78, 78, 78, 78, 78, 24, 24, - /* 10 */ 78, 78, 78, 43, 162, 24, 35, 35, 35, -3, - /* 20 */ -3, -3, -3, 35, -3, 137, 170, 222, 20, 248, - /* 30 */ 102, 140, 206, 35, 167, 35, 35, 167, 208, 35, - /* 40 */ 217, 151, 249, 228, +#define YY_SHIFT_MIN (0) +#define YY_SHIFT_MAX (254) +static const unsigned short int yy_shift_ofst[] = { + /* 0 */ 82, 46, 230, 230, 230, 230, 230, 230, 18, 18, + /* 10 */ 230, 230, 230, 135, 185, 18, 29, 29, 29, 12, + /* 20 */ 12, 12, 12, 29, 12, 136, 169, 201, 187, 215, + /* 30 */ 225, 35, 238, 29, 222, 29, 29, 222, 241, 29, + /* 40 */ 243, 239, 254, 234, }; #define YY_REDUCE_USE_DFLT (-60) #define YY_REDUCE_COUNT (40) #define YY_REDUCE_MIN (-59) -#define YY_REDUCE_MAX (201) +#define YY_REDUCE_MAX (195) static const short yy_reduce_ofst[] = { - /* 0 */ -38, 79, 126, 148, 156, 171, 186, 201, 98, -59, - /* 10 */ 178, 181, 181, -44, 76, -44, 123, 134, 138, 23, - /* 20 */ 23, 23, 23, 146, 23, -28, 17, 70, 90, 95, - /* 30 */ 86, 101, 117, 129, 142, 129, 129, 142, 144, 129, - /* 40 */ 169, + /* 0 */ -38, 79, 115, 130, 149, 158, 177, 192, 103, -59, + /* 10 */ -12, 24, 24, 70, -40, 70, 48, 86, 168, 195, + /* 20 */ 195, 195, 195, 186, 195, -28, 85, 87, 78, 97, + /* 30 */ 105, 172, 140, 152, 189, 152, 152, 189, 188, 152, + /* 40 */ 190, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 407, 407, 372, 371, 370, 316, 345, 340, 400, 350, - /* 10 */ 364, 343, 338, 355, 297, 357, 399, 374, 373, 366, - /* 20 */ 306, 344, 339, 304, 305, 383, 380, 377, 361, 293, - /* 30 */ 296, 292, 283, 347, 406, 312, 311, 313, 295, 303, - /* 40 */ 294, 404, 404, 290, + /* 0 */ 410, 410, 374, 373, 372, 318, 347, 342, 403, 352, + /* 10 */ 366, 345, 340, 357, 299, 359, 402, 376, 375, 368, + /* 20 */ 308, 346, 341, 306, 307, 385, 382, 379, 363, 295, + /* 30 */ 294, 298, 285, 349, 409, 314, 313, 315, 297, 305, + /* 40 */ 296, 407, 407, 292, }; /********** End of lemon-generated parsing tables *****************************/ @@ -297,15 +295,15 @@ static const YYACTIONTYPE yy_default[] = { #ifdef YYFALLBACK static const YYCODETYPE yyFallback[] = { 0, /* $ => nothing */ - 10, /* LINE_HR => LINE_HTML */ + 0, /* LINE_HR => nothing */ 1, /* LINE_SETEXT_1 => LINE_HR */ 1, /* LINE_SETEXT_2 => LINE_HR */ - 6, /* LINE_PLAIN => LINE_CONTINUATION */ - 4, /* LINE_TABLE_SEPARATOR => LINE_PLAIN */ 0, /* LINE_CONTINUATION => nothing */ - 6, /* LINE_INDENTED_TAB => LINE_CONTINUATION */ - 6, /* LINE_INDENTED_SPACE => LINE_CONTINUATION */ - 6, /* LINE_TABLE => LINE_CONTINUATION */ + 4, /* LINE_PLAIN => LINE_CONTINUATION */ + 4, /* LINE_INDENTED_TAB => LINE_CONTINUATION */ + 4, /* LINE_INDENTED_SPACE => LINE_CONTINUATION */ + 4, /* LINE_TABLE => LINE_CONTINUATION */ + 4, /* LINE_TABLE_SEPARATOR => LINE_CONTINUATION */ 0, /* LINE_HTML => nothing */ 10, /* LINE_ATX_1 => LINE_HTML */ 10, /* LINE_ATX_2 => LINE_HTML */ @@ -409,8 +407,8 @@ void ParseTrace(FILE *TraceFILE, char *zTracePrompt){ ** are required. The following table supplies these names */ static const char *const yyTokenName[] = { "$", "LINE_HR", "LINE_SETEXT_1", "LINE_SETEXT_2", - "LINE_PLAIN", "LINE_TABLE_SEPARATOR", "LINE_CONTINUATION", "LINE_INDENTED_TAB", - "LINE_INDENTED_SPACE", "LINE_TABLE", "LINE_HTML", "LINE_ATX_1", + "LINE_CONTINUATION", "LINE_PLAIN", "LINE_INDENTED_TAB", "LINE_INDENTED_SPACE", + "LINE_TABLE", "LINE_TABLE_SEPARATOR", "LINE_HTML", "LINE_ATX_1", "LINE_ATX_2", "LINE_ATX_3", "LINE_ATX_4", "LINE_ATX_5", "LINE_ATX_6", "LINE_BLOCKQUOTE", "LINE_LIST_BULLETED", "LINE_LIST_ENUMERATED", "LINE_DEF_ABBREVIATION", "LINE_DEF_CITATION", "LINE_DEF_FOOTNOTE", "LINE_DEF_GLOSSARY", @@ -557,20 +555,21 @@ static const char *const yyRuleName[] = { /* 118 */ "html_block ::= LINE_HTML", /* 119 */ "html_line ::= LINE_CONTINUATION", /* 120 */ "html_line ::= LINE_HTML", - /* 121 */ "indented_code ::= indented_line", - /* 122 */ "list_bullet ::= item_bullet", - /* 123 */ "list_enum ::= item_enum", - /* 124 */ "meta_block ::= LINE_META", - /* 125 */ "meta_line ::= LINE_META", - /* 126 */ "meta_line ::= LINE_CONTINUATION", - /* 127 */ "para ::= LINE_PLAIN", - /* 128 */ "table ::= table_header", - /* 129 */ "header_rows ::= LINE_TABLE", - /* 130 */ "table_body ::= table_section", - /* 131 */ "all_rows ::= row", - /* 132 */ "row ::= header_rows", - /* 133 */ "row ::= LINE_TABLE_SEPARATOR", - /* 134 */ "para ::= defs", + /* 121 */ "html_line ::= LINE_HR", + /* 122 */ "indented_code ::= indented_line", + /* 123 */ "list_bullet ::= item_bullet", + /* 124 */ "list_enum ::= item_enum", + /* 125 */ "meta_block ::= LINE_META", + /* 126 */ "meta_line ::= LINE_META", + /* 127 */ "meta_line ::= LINE_CONTINUATION", + /* 128 */ "para ::= LINE_PLAIN", + /* 129 */ "table ::= table_header", + /* 130 */ "header_rows ::= LINE_TABLE", + /* 131 */ "table_body ::= table_section", + /* 132 */ "all_rows ::= row", + /* 133 */ "row ::= header_rows", + /* 134 */ "row ::= LINE_TABLE_SEPARATOR", + /* 135 */ "para ::= defs", }; #endif /* NDEBUG */ @@ -1040,6 +1039,7 @@ static const struct { { 50, 1 }, { 74, 1 }, { 74, 1 }, + { 74, 1 }, { 51, 1 }, { 52, 1 }, { 53, 1 }, @@ -1382,20 +1382,21 @@ static void yy_reduce( /* (118) html_block ::= LINE_HTML */ yytestcase(yyruleno==118); /* (119) html_line ::= LINE_CONTINUATION */ yytestcase(yyruleno==119); /* (120) html_line ::= LINE_HTML */ yytestcase(yyruleno==120); - /* (121) indented_code ::= indented_line (OPTIMIZED OUT) */ assert(yyruleno!=121); - /* (122) list_bullet ::= item_bullet (OPTIMIZED OUT) */ assert(yyruleno!=122); - /* (123) list_enum ::= item_enum (OPTIMIZED OUT) */ assert(yyruleno!=123); - /* (124) meta_block ::= LINE_META */ yytestcase(yyruleno==124); - /* (125) meta_line ::= LINE_META */ yytestcase(yyruleno==125); - /* (126) meta_line ::= LINE_CONTINUATION */ yytestcase(yyruleno==126); - /* (127) para ::= LINE_PLAIN */ yytestcase(yyruleno==127); - /* (128) table ::= table_header */ yytestcase(yyruleno==128); - /* (129) header_rows ::= LINE_TABLE */ yytestcase(yyruleno==129); - /* (130) table_body ::= table_section (OPTIMIZED OUT) */ assert(yyruleno!=130); - /* (131) all_rows ::= row (OPTIMIZED OUT) */ assert(yyruleno!=131); - /* (132) row ::= header_rows */ yytestcase(yyruleno==132); - /* (133) row ::= LINE_TABLE_SEPARATOR */ yytestcase(yyruleno==133); - /* (134) para ::= defs */ yytestcase(yyruleno==134); + /* (121) html_line ::= LINE_HR */ yytestcase(yyruleno==121); + /* (122) indented_code ::= indented_line (OPTIMIZED OUT) */ assert(yyruleno!=122); + /* (123) list_bullet ::= item_bullet (OPTIMIZED OUT) */ assert(yyruleno!=123); + /* (124) list_enum ::= item_enum (OPTIMIZED OUT) */ assert(yyruleno!=124); + /* (125) meta_block ::= LINE_META */ yytestcase(yyruleno==125); + /* (126) meta_line ::= LINE_META */ yytestcase(yyruleno==126); + /* (127) meta_line ::= LINE_CONTINUATION */ yytestcase(yyruleno==127); + /* (128) para ::= LINE_PLAIN */ yytestcase(yyruleno==128); + /* (129) table ::= table_header */ yytestcase(yyruleno==129); + /* (130) header_rows ::= LINE_TABLE */ yytestcase(yyruleno==130); + /* (131) table_body ::= table_section (OPTIMIZED OUT) */ assert(yyruleno!=131); + /* (132) all_rows ::= row (OPTIMIZED OUT) */ assert(yyruleno!=132); + /* (133) row ::= header_rows */ yytestcase(yyruleno==133); + /* (134) row ::= LINE_TABLE_SEPARATOR */ yytestcase(yyruleno==134); + /* (135) para ::= defs */ yytestcase(yyruleno==135); break; /********** End reduce actions ************************************************/ }; diff --git a/Sources/libMultiMarkdown/parser.h b/Sources/libMultiMarkdown/parser.h index 55917c25..5c1dc2c5 100644 --- a/Sources/libMultiMarkdown/parser.h +++ b/Sources/libMultiMarkdown/parser.h @@ -1,12 +1,12 @@ #define LINE_HR 1 #define LINE_SETEXT_1 2 #define LINE_SETEXT_2 3 -#define LINE_PLAIN 4 -#define LINE_TABLE_SEPARATOR 5 -#define LINE_CONTINUATION 6 -#define LINE_INDENTED_TAB 7 -#define LINE_INDENTED_SPACE 8 -#define LINE_TABLE 9 +#define LINE_CONTINUATION 4 +#define LINE_PLAIN 5 +#define LINE_INDENTED_TAB 6 +#define LINE_INDENTED_SPACE 7 +#define LINE_TABLE 8 +#define LINE_TABLE_SEPARATOR 9 #define LINE_HTML 10 #define LINE_ATX_1 11 #define LINE_ATX_2 12 diff --git a/Sources/libMultiMarkdown/parser.out b/Sources/libMultiMarkdown/parser.out index 91097891..ed89f4aa 100644 --- a/Sources/libMultiMarkdown/parser.out +++ b/Sources/libMultiMarkdown/parser.out @@ -110,10 +110,10 @@ State 0: LINE_HR shift-reduce 9 block ::= LINE_HR LINE_PLAIN shift 16 - LINE_TABLE_SEPARATOR shift-reduce 133 row ::= LINE_TABLE_SEPARATOR LINE_INDENTED_TAB shift-reduce 90 indented_line ::= LINE_INDENTED_TAB LINE_INDENTED_SPACE shift-reduce 91 indented_line ::= LINE_INDENTED_SPACE - LINE_TABLE shift-reduce 129 header_rows ::= LINE_TABLE + LINE_TABLE shift-reduce 130 header_rows ::= LINE_TABLE + LINE_TABLE_SEPARATOR shift-reduce 134 row ::= LINE_TABLE_SEPARATOR LINE_HTML shift-reduce 118 html_block ::= LINE_HTML LINE_ATX_1 shift-reduce 3 block ::= LINE_ATX_1 LINE_ATX_2 shift-reduce 4 block ::= LINE_ATX_2 @@ -138,7 +138,7 @@ State 0: LINE_FENCE_BACKTICK_START_3 shift-reduce 107 fenced_3 ::= LINE_FENCE_BACKTICK_START_3 LINE_FENCE_BACKTICK_START_4 shift-reduce 110 fenced_4 ::= LINE_FENCE_BACKTICK_START_4 LINE_FENCE_BACKTICK_START_5 shift-reduce 113 fenced_5 ::= LINE_FENCE_BACKTICK_START_5 - LINE_META shift-reduce 124 meta_block ::= LINE_META + LINE_META shift-reduce 125 meta_block ::= LINE_META doc accept blocks shift 1 block shift-reduce 2 blocks ::= block @@ -151,11 +151,11 @@ State 0: definition_block shift-reduce 17 block ::= definition_block empty shift 43 fenced_block shift-reduce 19 block ::= fenced_block - html_block shift 31 + html_block shift 30 indented_code shift 29 list_bullet shift 40 list_enum shift 38 - meta_block shift 30 + meta_block shift 31 para shift 14 setext_1 shift-reduce 26 block ::= setext_1 setext_2 shift-reduce 27 block ::= setext_2 @@ -285,10 +285,10 @@ State 1: $ reduce 0 doc ::= blocks LINE_HR shift-reduce 9 block ::= LINE_HR LINE_PLAIN shift 16 - LINE_TABLE_SEPARATOR shift-reduce 133 row ::= LINE_TABLE_SEPARATOR LINE_INDENTED_TAB shift-reduce 90 indented_line ::= LINE_INDENTED_TAB LINE_INDENTED_SPACE shift-reduce 91 indented_line ::= LINE_INDENTED_SPACE - LINE_TABLE shift-reduce 129 header_rows ::= LINE_TABLE + LINE_TABLE shift-reduce 130 header_rows ::= LINE_TABLE + LINE_TABLE_SEPARATOR shift-reduce 134 row ::= LINE_TABLE_SEPARATOR LINE_HTML shift-reduce 118 html_block ::= LINE_HTML LINE_ATX_1 shift-reduce 3 block ::= LINE_ATX_1 LINE_ATX_2 shift-reduce 4 block ::= LINE_ATX_2 @@ -313,7 +313,7 @@ State 1: LINE_FENCE_BACKTICK_START_3 shift-reduce 107 fenced_3 ::= LINE_FENCE_BACKTICK_START_3 LINE_FENCE_BACKTICK_START_4 shift-reduce 110 fenced_4 ::= LINE_FENCE_BACKTICK_START_4 LINE_FENCE_BACKTICK_START_5 shift-reduce 113 fenced_5 ::= LINE_FENCE_BACKTICK_START_5 - LINE_META shift-reduce 124 meta_block ::= LINE_META + LINE_META shift-reduce 125 meta_block ::= LINE_META block shift-reduce 1 blocks ::= blocks block blockquote shift 32 def_abbreviation shift-reduce 12 block ::= def_abbreviation @@ -324,11 +324,11 @@ State 1: definition_block shift-reduce 17 block ::= definition_block empty shift 43 fenced_block shift-reduce 19 block ::= fenced_block - html_block shift 31 + html_block shift 30 indented_code shift 29 list_bullet shift 40 list_enum shift 38 - meta_block shift 30 + meta_block shift 31 para shift 14 setext_1 shift-reduce 26 block ::= setext_1 setext_2 shift-reduce 27 block ::= setext_2 @@ -524,7 +524,7 @@ State 7: State 8: table ::= table_header * table_body - (128) table ::= table_header * + (129) table ::= table_header * header_rows ::= * header_rows LINE_TABLE header_rows ::= * LINE_TABLE table_body ::= * table_body table_section @@ -536,16 +536,16 @@ State 8: row ::= * header_rows row ::= * LINE_TABLE_SEPARATOR - LINE_TABLE_SEPARATOR shift-reduce 133 row ::= LINE_TABLE_SEPARATOR - LINE_TABLE_SEPARATOR reduce 128 ** Parsing conflict ** - LINE_TABLE shift-reduce 129 header_rows ::= LINE_TABLE - LINE_TABLE reduce 128 ** Parsing conflict ** + LINE_TABLE shift-reduce 130 header_rows ::= LINE_TABLE + LINE_TABLE reduce 129 ** Parsing conflict ** + LINE_TABLE_SEPARATOR shift-reduce 134 row ::= LINE_TABLE_SEPARATOR + LINE_TABLE_SEPARATOR reduce 129 ** Parsing conflict ** table_body shift 9 header_rows shift 42 table_section shift 9 /* because table_section==table_body */ all_rows shift 13 row shift 13 /* because row==all_rows */ - {default} reduce 128 table ::= table_header + {default} reduce 129 table ::= table_header State 9: (78) table ::= table_header table_body * @@ -559,10 +559,10 @@ State 9: row ::= * header_rows row ::= * LINE_TABLE_SEPARATOR - LINE_TABLE_SEPARATOR shift-reduce 133 row ::= LINE_TABLE_SEPARATOR - LINE_TABLE_SEPARATOR reduce 78 ** Parsing conflict ** - LINE_TABLE shift-reduce 129 header_rows ::= LINE_TABLE + LINE_TABLE shift-reduce 130 header_rows ::= LINE_TABLE LINE_TABLE reduce 78 ** Parsing conflict ** + LINE_TABLE_SEPARATOR shift-reduce 134 row ::= LINE_TABLE_SEPARATOR + LINE_TABLE_SEPARATOR reduce 78 ** Parsing conflict ** header_rows shift 42 table_section shift-reduce 81 table_body ::= table_body table_section all_rows shift 13 @@ -644,10 +644,10 @@ State 13: row ::= * header_rows row ::= * LINE_TABLE_SEPARATOR - LINE_TABLE_SEPARATOR shift-reduce 133 row ::= LINE_TABLE_SEPARATOR - LINE_TABLE_SEPARATOR reduce 83 ** Parsing conflict ** - LINE_TABLE shift-reduce 129 header_rows ::= LINE_TABLE + LINE_TABLE shift-reduce 130 header_rows ::= LINE_TABLE LINE_TABLE reduce 83 ** Parsing conflict ** + LINE_TABLE_SEPARATOR shift-reduce 134 row ::= LINE_TABLE_SEPARATOR + LINE_TABLE_SEPARATOR reduce 83 ** Parsing conflict ** LINE_EMPTY shift-reduce 82 table_section ::= all_rows LINE_EMPTY LINE_EMPTY reduce 83 ** Parsing conflict ** header_rows shift 42 @@ -680,10 +680,10 @@ State 15: row ::= * LINE_TABLE_SEPARATOR (85) para ::= all_rows * - LINE_TABLE_SEPARATOR shift-reduce 133 row ::= LINE_TABLE_SEPARATOR - LINE_TABLE_SEPARATOR reduce 85 ** Parsing conflict ** - LINE_TABLE shift-reduce 129 header_rows ::= LINE_TABLE + LINE_TABLE shift-reduce 130 header_rows ::= LINE_TABLE LINE_TABLE reduce 85 ** Parsing conflict ** + LINE_TABLE_SEPARATOR shift-reduce 134 row ::= LINE_TABLE_SEPARATOR + LINE_TABLE_SEPARATOR reduce 85 ** Parsing conflict ** header_rows shift 42 row shift-reduce 84 all_rows ::= all_rows row {default} reduce 85 para ::= all_rows @@ -693,12 +693,12 @@ State 16: chunk ::= * chunk_line chunk_line ::= * LINE_CONTINUATION para ::= LINE_PLAIN * chunk - (127) para ::= LINE_PLAIN * + (128) para ::= LINE_PLAIN * LINE_CONTINUATION shift-reduce 87 chunk_line ::= LINE_CONTINUATION chunk shift 33 chunk_line shift 33 /* because chunk_line==chunk */ - {default} reduce 127 para ::= LINE_PLAIN + {default} reduce 128 para ::= LINE_PLAIN State 17: chunk ::= * chunk chunk_line @@ -929,29 +929,32 @@ State 29: {default} reduce 21 block ::= indented_code State 30: - (24) block ::= meta_block * - meta_block ::= meta_block * meta_line - meta_line ::= * LINE_META - meta_line ::= * LINE_CONTINUATION - - LINE_CONTINUATION shift-reduce 126 meta_line ::= LINE_CONTINUATION - LINE_META shift-reduce 125 meta_line ::= LINE_META - LINE_META reduce 24 ** Parsing conflict ** - meta_line shift-reduce 74 meta_block ::= meta_block meta_line - {default} reduce 24 block ::= meta_block - -State 31: (20) block ::= html_block * html_block ::= html_block * html_line html_line ::= * LINE_CONTINUATION html_line ::= * LINE_HTML + html_line ::= * LINE_HR + LINE_HR shift-reduce 121 html_line ::= LINE_HR + LINE_HR reduce 20 ** Parsing conflict ** LINE_CONTINUATION shift-reduce 119 html_line ::= LINE_CONTINUATION LINE_HTML shift-reduce 120 html_line ::= LINE_HTML LINE_HTML reduce 20 ** Parsing conflict ** html_line shift-reduce 61 html_block ::= html_block html_line {default} reduce 20 block ::= html_block +State 31: + (24) block ::= meta_block * + meta_block ::= meta_block * meta_line + meta_line ::= * LINE_META + meta_line ::= * LINE_CONTINUATION + + LINE_CONTINUATION shift-reduce 127 meta_line ::= LINE_CONTINUATION + LINE_META shift-reduce 126 meta_line ::= LINE_META + LINE_META reduce 24 ** Parsing conflict ** + meta_line shift-reduce 74 meta_block ::= meta_block meta_line + {default} reduce 24 block ::= meta_block + State 32: (11) block ::= blockquote * blockquote ::= blockquote * quote_line @@ -977,12 +980,12 @@ State 34: defs ::= defs * def def ::= * LINE_DEFINITION tail def ::= * LINE_DEFINITION - (134) para ::= defs * + (135) para ::= defs * LINE_DEFINITION shift 5 - LINE_DEFINITION reduce 134 ** Parsing conflict ** + LINE_DEFINITION reduce 135 ** Parsing conflict ** def shift-reduce 42 defs ::= defs def - {default} reduce 134 para ::= defs + {default} reduce 135 para ::= defs State 35: chunk ::= chunk * chunk_line @@ -1051,21 +1054,21 @@ State 40: State 41: table_header ::= header_rows * LINE_TABLE_SEPARATOR header_rows ::= header_rows * LINE_TABLE - (132) row ::= header_rows * + (133) row ::= header_rows * - LINE_TABLE_SEPARATOR shift-reduce 79 table_header ::= header_rows LINE_TABLE_SEPARATOR - LINE_TABLE_SEPARATOR reduce 132 ** Parsing conflict ** LINE_TABLE shift-reduce 80 header_rows ::= header_rows LINE_TABLE - LINE_TABLE reduce 132 ** Parsing conflict ** - {default} reduce 132 row ::= header_rows + LINE_TABLE reduce 133 ** Parsing conflict ** + LINE_TABLE_SEPARATOR shift-reduce 79 table_header ::= header_rows LINE_TABLE_SEPARATOR + LINE_TABLE_SEPARATOR reduce 133 ** Parsing conflict ** + {default} reduce 133 row ::= header_rows State 42: header_rows ::= header_rows * LINE_TABLE - (132) row ::= header_rows * + (133) row ::= header_rows * LINE_TABLE shift-reduce 80 header_rows ::= header_rows LINE_TABLE - LINE_TABLE reduce 132 ** Parsing conflict ** - {default} reduce 132 row ::= header_rows + LINE_TABLE reduce 133 ** Parsing conflict ** + {default} reduce 133 row ::= header_rows State 43: (18) block ::= empty * @@ -1081,12 +1084,12 @@ Symbols: 1: LINE_HR 2: LINE_SETEXT_1 3: LINE_SETEXT_2 - 4: LINE_PLAIN - 5: LINE_TABLE_SEPARATOR - 6: LINE_CONTINUATION - 7: LINE_INDENTED_TAB - 8: LINE_INDENTED_SPACE - 9: LINE_TABLE + 4: LINE_CONTINUATION + 5: LINE_PLAIN + 6: LINE_INDENTED_TAB + 7: LINE_INDENTED_SPACE + 8: LINE_TABLE + 9: LINE_TABLE_SEPARATOR 10: LINE_HTML 11: LINE_ATX_1 12: LINE_ATX_2 @@ -1115,16 +1118,16 @@ Symbols: 35: LINE_FENCE_BACKTICK_START_5 36: LINE_META 37: error: - 38: doc: LINE_HR LINE_PLAIN LINE_TABLE_SEPARATOR LINE_INDENTED_TAB LINE_INDENTED_SPACE LINE_TABLE LINE_HTML LINE_ATX_1 LINE_ATX_2 LINE_ATX_3 LINE_ATX_4 LINE_ATX_5 LINE_ATX_6 LINE_BLOCKQUOTE LINE_LIST_BULLETED LINE_LIST_ENUMERATED LINE_DEF_ABBREVIATION LINE_DEF_CITATION LINE_DEF_FOOTNOTE LINE_DEF_GLOSSARY LINE_DEF_LINK LINE_TOC LINE_DEFINITION LINE_EMPTY LINE_FENCE_BACKTICK_3 LINE_FENCE_BACKTICK_4 LINE_FENCE_BACKTICK_5 LINE_FENCE_BACKTICK_START_3 LINE_FENCE_BACKTICK_START_4 LINE_FENCE_BACKTICK_START_5 LINE_META - 39: blocks: LINE_HR LINE_PLAIN LINE_TABLE_SEPARATOR LINE_INDENTED_TAB LINE_INDENTED_SPACE LINE_TABLE LINE_HTML LINE_ATX_1 LINE_ATX_2 LINE_ATX_3 LINE_ATX_4 LINE_ATX_5 LINE_ATX_6 LINE_BLOCKQUOTE LINE_LIST_BULLETED LINE_LIST_ENUMERATED LINE_DEF_ABBREVIATION LINE_DEF_CITATION LINE_DEF_FOOTNOTE LINE_DEF_GLOSSARY LINE_DEF_LINK LINE_TOC LINE_DEFINITION LINE_EMPTY LINE_FENCE_BACKTICK_3 LINE_FENCE_BACKTICK_4 LINE_FENCE_BACKTICK_5 LINE_FENCE_BACKTICK_START_3 LINE_FENCE_BACKTICK_START_4 LINE_FENCE_BACKTICK_START_5 LINE_META - 40: block: LINE_HR LINE_PLAIN LINE_TABLE_SEPARATOR LINE_INDENTED_TAB LINE_INDENTED_SPACE LINE_TABLE LINE_HTML LINE_ATX_1 LINE_ATX_2 LINE_ATX_3 LINE_ATX_4 LINE_ATX_5 LINE_ATX_6 LINE_BLOCKQUOTE LINE_LIST_BULLETED LINE_LIST_ENUMERATED LINE_DEF_ABBREVIATION LINE_DEF_CITATION LINE_DEF_FOOTNOTE LINE_DEF_GLOSSARY LINE_DEF_LINK LINE_TOC LINE_DEFINITION LINE_EMPTY LINE_FENCE_BACKTICK_3 LINE_FENCE_BACKTICK_4 LINE_FENCE_BACKTICK_5 LINE_FENCE_BACKTICK_START_3 LINE_FENCE_BACKTICK_START_4 LINE_FENCE_BACKTICK_START_5 LINE_META + 38: doc: LINE_HR LINE_PLAIN LINE_INDENTED_TAB LINE_INDENTED_SPACE LINE_TABLE LINE_TABLE_SEPARATOR LINE_HTML LINE_ATX_1 LINE_ATX_2 LINE_ATX_3 LINE_ATX_4 LINE_ATX_5 LINE_ATX_6 LINE_BLOCKQUOTE LINE_LIST_BULLETED LINE_LIST_ENUMERATED LINE_DEF_ABBREVIATION LINE_DEF_CITATION LINE_DEF_FOOTNOTE LINE_DEF_GLOSSARY LINE_DEF_LINK LINE_TOC LINE_DEFINITION LINE_EMPTY LINE_FENCE_BACKTICK_3 LINE_FENCE_BACKTICK_4 LINE_FENCE_BACKTICK_5 LINE_FENCE_BACKTICK_START_3 LINE_FENCE_BACKTICK_START_4 LINE_FENCE_BACKTICK_START_5 LINE_META + 39: blocks: LINE_HR LINE_PLAIN LINE_INDENTED_TAB LINE_INDENTED_SPACE LINE_TABLE LINE_TABLE_SEPARATOR LINE_HTML LINE_ATX_1 LINE_ATX_2 LINE_ATX_3 LINE_ATX_4 LINE_ATX_5 LINE_ATX_6 LINE_BLOCKQUOTE LINE_LIST_BULLETED LINE_LIST_ENUMERATED LINE_DEF_ABBREVIATION LINE_DEF_CITATION LINE_DEF_FOOTNOTE LINE_DEF_GLOSSARY LINE_DEF_LINK LINE_TOC LINE_DEFINITION LINE_EMPTY LINE_FENCE_BACKTICK_3 LINE_FENCE_BACKTICK_4 LINE_FENCE_BACKTICK_5 LINE_FENCE_BACKTICK_START_3 LINE_FENCE_BACKTICK_START_4 LINE_FENCE_BACKTICK_START_5 LINE_META + 40: block: LINE_HR LINE_PLAIN LINE_INDENTED_TAB LINE_INDENTED_SPACE LINE_TABLE LINE_TABLE_SEPARATOR LINE_HTML LINE_ATX_1 LINE_ATX_2 LINE_ATX_3 LINE_ATX_4 LINE_ATX_5 LINE_ATX_6 LINE_BLOCKQUOTE LINE_LIST_BULLETED LINE_LIST_ENUMERATED LINE_DEF_ABBREVIATION LINE_DEF_CITATION LINE_DEF_FOOTNOTE LINE_DEF_GLOSSARY LINE_DEF_LINK LINE_TOC LINE_DEFINITION LINE_EMPTY LINE_FENCE_BACKTICK_3 LINE_FENCE_BACKTICK_4 LINE_FENCE_BACKTICK_5 LINE_FENCE_BACKTICK_START_3 LINE_FENCE_BACKTICK_START_4 LINE_FENCE_BACKTICK_START_5 LINE_META 41: blockquote: LINE_BLOCKQUOTE 42: def_abbreviation: LINE_DEF_ABBREVIATION 43: def_citation: LINE_DEF_CITATION 44: def_footnote: LINE_DEF_FOOTNOTE 45: def_glossary: LINE_DEF_GLOSSARY 46: def_link: LINE_DEF_LINK - 47: definition_block: LINE_PLAIN LINE_TABLE_SEPARATOR LINE_TABLE LINE_DEFINITION + 47: definition_block: LINE_PLAIN LINE_TABLE LINE_TABLE_SEPARATOR LINE_DEFINITION 48: empty: LINE_EMPTY 49: fenced_block: LINE_FENCE_BACKTICK_3 LINE_FENCE_BACKTICK_4 LINE_FENCE_BACKTICK_5 LINE_FENCE_BACKTICK_START_3 LINE_FENCE_BACKTICK_START_4 LINE_FENCE_BACKTICK_START_5 50: html_block: LINE_HTML @@ -1132,9 +1135,9 @@ Symbols: 52: list_bullet: LINE_LIST_BULLETED 53: list_enum: LINE_LIST_ENUMERATED 54: meta_block: LINE_META - 55: para: LINE_PLAIN LINE_TABLE_SEPARATOR LINE_TABLE LINE_DEFINITION - 56: setext_1: LINE_PLAIN LINE_TABLE_SEPARATOR LINE_TABLE LINE_DEFINITION - 57: setext_2: LINE_PLAIN LINE_TABLE_SEPARATOR LINE_TABLE LINE_DEFINITION + 55: para: LINE_PLAIN LINE_TABLE LINE_TABLE_SEPARATOR LINE_DEFINITION + 56: setext_1: LINE_PLAIN LINE_TABLE LINE_TABLE_SEPARATOR LINE_DEFINITION + 57: setext_2: LINE_PLAIN LINE_TABLE LINE_TABLE_SEPARATOR LINE_DEFINITION 58: table: LINE_TABLE 59: chunk: LINE_CONTINUATION 60: chunk_line: LINE_CONTINUATION @@ -1151,13 +1154,13 @@ Symbols: 71: fenced_line: LINE_SETEXT_1 LINE_SETEXT_2 LINE_CONTINUATION LINE_EMPTY 72: fenced_4: LINE_FENCE_BACKTICK_4 LINE_FENCE_BACKTICK_START_4 73: fenced_5: LINE_FENCE_BACKTICK_5 LINE_FENCE_BACKTICK_START_5 - 74: html_line: LINE_CONTINUATION LINE_HTML + 74: html_line: LINE_HR LINE_CONTINUATION LINE_HTML 75: item_bullet: LINE_LIST_BULLETED 76: item_enum: LINE_LIST_ENUMERATED 77: meta_line: LINE_CONTINUATION LINE_META 78: table_header: LINE_TABLE - 79: table_body: LINE_TABLE_SEPARATOR LINE_TABLE + 79: table_body: LINE_TABLE LINE_TABLE_SEPARATOR 80: header_rows: LINE_TABLE - 81: table_section: LINE_TABLE_SEPARATOR LINE_TABLE - 82: all_rows: LINE_TABLE_SEPARATOR LINE_TABLE - 83: row: LINE_TABLE_SEPARATOR LINE_TABLE + 81: table_section: LINE_TABLE LINE_TABLE_SEPARATOR + 82: all_rows: LINE_TABLE LINE_TABLE_SEPARATOR + 83: row: LINE_TABLE LINE_TABLE_SEPARATOR diff --git a/Sources/libMultiMarkdown/parser.y b/Sources/libMultiMarkdown/parser.y index d5f162c4..62e0e588 100644 --- a/Sources/libMultiMarkdown/parser.y +++ b/Sources/libMultiMarkdown/parser.y @@ -64,11 +64,11 @@ %fallback LINE_HR LINE_SETEXT_1 LINE_SETEXT_2. -%fallback LINE_PLAIN LINE_TABLE_SEPARATOR. +//%fallback LINE_PLAIN LINE_TABLE_SEPARATOR. -%fallback LINE_CONTINUATION LINE_PLAIN LINE_INDENTED_TAB LINE_INDENTED_SPACE LINE_TABLE. +%fallback LINE_CONTINUATION LINE_PLAIN LINE_INDENTED_TAB LINE_INDENTED_SPACE LINE_TABLE LINE_TABLE_SEPARATOR. -%fallback LINE_HTML LINE_ATX_1 LINE_ATX_2 LINE_ATX_3 LINE_ATX_4 LINE_ATX_5 LINE_ATX_6 LINE_HR LINE_BLOCKQUOTE +%fallback LINE_HTML LINE_ATX_1 LINE_ATX_2 LINE_ATX_3 LINE_ATX_4 LINE_ATX_5 LINE_ATX_6 LINE_BLOCKQUOTE LINE_LIST_BULLETED LINE_LIST_ENUMERATED LINE_DEF_ABBREVIATION LINE_DEF_CITATION LINE_DEF_FOOTNOTE LINE_DEF_GLOSSARY LINE_DEF_LINK LINE_FENCE_BACKTICK LINE_FENCE_BACKTICK_START. @@ -271,6 +271,7 @@ html_block ::= LINE_HTML. html_line ::= LINE_CONTINUATION. html_line ::= LINE_HTML. +html_line ::= LINE_HR. // Indented code blocks diff --git a/test/parser_test.y b/test/parser_test.y index 46af54b4..118bea16 100644 --- a/test/parser_test.y +++ b/test/parser_test.y @@ -69,11 +69,13 @@ %fallback LINE_HR LINE_SETEXT_1 LINE_SETEXT_2. -%fallback LINE_PLAIN LINE_TABLE_SEPARATOR. +//%fallback LINE_PLAIN LINE_TABLE_SEPARATOR. -%fallback LINE_CONTINUATION LINE_PLAIN LINE_INDENTED_TAB LINE_INDENTED_SPACE LINE_TABLE. +%fallback LINE_CONTINUATION LINE_INDENTED_TAB LINE_INDENTED_SPACE LINE_TABLE LINE_TABLE_SEPARATOR. -%fallback LINE_HTML LINE_ATX_1 LINE_ATX_2 LINE_ATX_3 LINE_ATX_4 LINE_ATX_5 LINE_ATX_6 LINE_HR LINE_BLOCKQUOTE LINE_LIST_BULLETED LINE_LIST_ENUMERATED LINE_DEF_CITATION LINE_DEF_FOOTNOTE LINE_DEF_LINK LINE_FENCE_BACKTICK LINE_FENCE_BACKTICK_START. +%fallback LINE_HTML LINE_ATX_1 LINE_ATX_2 LINE_ATX_3 LINE_ATX_4 LINE_ATX_5 LINE_ATX_6 LINE_BLOCKQUOTE +LINE_LIST_BULLETED LINE_LIST_ENUMERATED LINE_DEF_ABBREVIATION LINE_DEF_CITATION LINE_DEF_FOOTNOTE +LINE_DEF_GLOSSARY LINE_DEF_LINK LINE_FENCE_BACKTICK LINE_FENCE_BACKTICK_START. // Copy clean grammar via `lemon -g parser.y` here @@ -90,8 +92,10 @@ block ::= LINE_ATX_6. block ::= LINE_HR. block ::= LINE_TOC. block ::= blockquote. +block ::= def_abbreviation. block ::= def_citation. block ::= def_footnote. +block ::= def_glossary. block ::= def_link. block ::= definition_block. block ::= empty. @@ -114,7 +118,9 @@ opt_ext_chunk ::= chunk nested_chunks. blockquote ::= blockquote quote_line. def_citation ::= LINE_DEF_CITATION tail. def_footnote ::= LINE_DEF_FOOTNOTE tail. +def_glossary ::= LINE_DEF_GLOSSARY tail. def_link ::= LINE_DEF_LINK chunk. +def_abbreviation ::= LINE_DEF_ABBREVIATION chunk. definition_block ::= para defs. defs ::= defs def. def ::= LINE_DEFINITION tail. @@ -174,7 +180,9 @@ quote_line ::= LINE_BLOCKQUOTE. quote_line ::= LINE_CONTINUATION. def_citation ::= LINE_DEF_CITATION. def_footnote ::= LINE_DEF_FOOTNOTE. +def_glossary ::= LINE_DEF_GLOSSARY. def_link ::= LINE_DEF_LINK. +def_abbreviation ::= LINE_DEF_ABBREVIATION. defs ::= def. empty ::= LINE_EMPTY. fenced_block ::= fenced_3. @@ -225,7 +233,7 @@ para ::= defs. void ParseFree(); void ParseTrace(); - #define kMaxToken 34 + #define kMaxToken 36 int i,j,k,l,m, n; From 2b948cf3f70dc4db27d3808d7e7aa2ab9cc1ed3e Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 12:16:27 -0400 Subject: [PATCH 04/29] FIXED: Don't let labels end on '\' that is escaping the closing ']' --- Sources/libMultiMarkdown/scanners.c | 4028 +++++++++++++------------- Sources/libMultiMarkdown/scanners.re | 2 +- 2 files changed, 2031 insertions(+), 1999 deletions(-) diff --git a/Sources/libMultiMarkdown/scanners.c b/Sources/libMultiMarkdown/scanners.c index bf59122e..e2ac3d1c 100644 --- a/Sources/libMultiMarkdown/scanners.c +++ b/Sources/libMultiMarkdown/scanners.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.14.3 on Mon Mar 6 14:49:25 2017 */ +/* Generated by re2c 0.14.3 on Tue Mar 14 12:15:24 2017 */ /** MultiMarkdown 6 -- Lightweight markup processor to produce HTML, LaTeX, and more. @@ -3459,8 +3459,8 @@ size_t scan_ref_abbreviation(const char * c) { yy145: yych = *(marker = ++c); switch (yych) { - case ' ': goto yy157; - case '[': goto yy158; + case ' ': goto yy158; + case '[': goto yy159; default: goto yy144; } yy146: @@ -3473,68 +3473,73 @@ size_t scan_ref_abbreviation(const char * c) { yych = *++c; goto yy144; yy148: - yych = *++c; + ++c; + yych = *c; switch (yych) { - case ']': goto yy149; + case 0x00: + case '\n': + case '\r': + case ']': goto yy150; + case '\\': goto yy148; default: goto yy151; } -yy149: +yy150: c = marker; goto yy144; -yy150: +yy151: ++c; yych = *c; -yy151: switch (yych) { case 0x00: case '\n': - case '\r': goto yy149; - case ']': goto yy152; - default: goto yy150; + case '\r': goto yy150; + case '\\': goto yy148; + case ']': goto yy153; + default: goto yy151; } -yy152: +yy153: yych = *++c; switch (yych) { - case ':': goto yy153; - default: goto yy149; + case ':': goto yy154; + default: goto yy150; } -yy153: +yy154: yych = *++c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy149; - default: goto yy154; + case '\r': goto yy150; + default: goto yy155; } -yy154: +yy155: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy156; - default: goto yy154; + case '\r': goto yy157; + default: goto yy155; } -yy156: - { return (size_t)( c - start ); } yy157: + { return (size_t)( c - start ); } +yy158: yych = *++c; switch (yych) { - case ' ': goto yy159; - case '[': goto yy158; - default: goto yy149; + case ' ': goto yy160; + case '[': goto yy159; + default: goto yy150; } -yy158: +yy159: yych = *++c; switch (yych) { case '>': goto yy148; - default: goto yy149; + default: goto yy150; } -yy159: +yy160: ++c; switch ((yych = *c)) { - case '[': goto yy158; - default: goto yy149; + case '[': goto yy159; + default: goto yy150; } } @@ -3550,92 +3555,97 @@ size_t scan_ref_citation(const char * c) { char yych; yych = *c; switch (yych) { - case '\n': goto yy162; - case ' ': goto yy163; - case '[': goto yy164; - default: goto yy165; + case '\n': goto yy163; + case ' ': goto yy164; + case '[': goto yy165; + default: goto yy166; } -yy162: - { return 0; } yy163: + { return 0; } +yy164: yych = *(marker = ++c); switch (yych) { - case ' ': goto yy175; - case '[': goto yy176; - default: goto yy162; + case ' ': goto yy177; + case '[': goto yy178; + default: goto yy163; } -yy164: +yy165: yych = *(marker = ++c); switch (yych) { - case '#': goto yy166; - default: goto yy162; + case '#': goto yy167; + default: goto yy163; } -yy165: - yych = *++c; - goto yy162; yy166: yych = *++c; + goto yy163; +yy167: + ++c; + yych = *c; switch (yych) { - case ']': goto yy167; - default: goto yy169; + case 0x00: + case '\n': + case '\r': + case ']': goto yy169; + case '\\': goto yy167; + default: goto yy170; } -yy167: +yy169: c = marker; - goto yy162; -yy168: + goto yy163; +yy170: ++c; yych = *c; -yy169: switch (yych) { case 0x00: case '\n': - case '\r': goto yy167; - case ']': goto yy170; - default: goto yy168; + case '\r': goto yy169; + case '\\': goto yy167; + case ']': goto yy172; + default: goto yy170; } -yy170: +yy172: yych = *++c; switch (yych) { - case ':': goto yy171; - default: goto yy167; + case ':': goto yy173; + default: goto yy169; } -yy171: +yy173: yych = *++c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy167; - default: goto yy172; + case '\r': goto yy169; + default: goto yy174; } -yy172: +yy174: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy174; - default: goto yy172; + case '\r': goto yy176; + default: goto yy174; } -yy174: +yy176: { return (size_t)( c - start ); } -yy175: +yy177: yych = *++c; switch (yych) { - case ' ': goto yy177; - case '[': goto yy176; - default: goto yy167; + case ' ': goto yy179; + case '[': goto yy178; + default: goto yy169; } -yy176: +yy178: yych = *++c; switch (yych) { - case '#': goto yy166; - default: goto yy167; + case '#': goto yy167; + default: goto yy169; } -yy177: +yy179: ++c; switch ((yych = *c)) { - case '[': goto yy176; - default: goto yy167; + case '[': goto yy178; + default: goto yy169; } } @@ -3651,92 +3661,97 @@ size_t scan_ref_foot(const char * c) { char yych; yych = *c; switch (yych) { - case '\n': goto yy180; - case ' ': goto yy181; - case '[': goto yy182; - default: goto yy183; - } -yy180: - { return 0; } -yy181: - yych = *(marker = ++c); - switch (yych) { - case ' ': goto yy193; - case '[': goto yy194; - default: goto yy180; + case '\n': goto yy182; + case ' ': goto yy183; + case '[': goto yy184; + default: goto yy185; } yy182: + { return 0; } +yy183: yych = *(marker = ++c); switch (yych) { - case '^': goto yy184; - default: goto yy180; + case ' ': goto yy196; + case '[': goto yy197; + default: goto yy182; } -yy183: - yych = *++c; - goto yy180; yy184: - yych = *++c; + yych = *(marker = ++c); switch (yych) { - case ']': goto yy185; - default: goto yy187; + case '^': goto yy186; + default: goto yy182; } yy185: - c = marker; - goto yy180; + yych = *++c; + goto yy182; yy186: ++c; yych = *c; -yy187: switch (yych) { case 0x00: case '\n': - case '\r': goto yy185; + case '\r': case ']': goto yy188; - default: goto yy186; + case '\\': goto yy186; + default: goto yy189; } yy188: + c = marker; + goto yy182; +yy189: + ++c; + yych = *c; + switch (yych) { + case 0x00: + case '\n': + case '\r': goto yy188; + case '\\': goto yy186; + case ']': goto yy191; + default: goto yy189; + } +yy191: yych = *++c; switch (yych) { - case ':': goto yy189; - default: goto yy185; + case ':': goto yy192; + default: goto yy188; } -yy189: +yy192: yych = *++c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy185; - default: goto yy190; + case '\r': goto yy188; + default: goto yy193; } -yy190: +yy193: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy192; - default: goto yy190; + case '\r': goto yy195; + default: goto yy193; } -yy192: +yy195: { return (size_t)( c - start ); } -yy193: +yy196: yych = *++c; switch (yych) { - case ' ': goto yy195; - case '[': goto yy194; - default: goto yy185; + case ' ': goto yy198; + case '[': goto yy197; + default: goto yy188; } -yy194: +yy197: yych = *++c; switch (yych) { - case '^': goto yy184; - default: goto yy185; + case '^': goto yy186; + default: goto yy188; } -yy195: +yy198: ++c; switch ((yych = *c)) { - case '[': goto yy194; - default: goto yy185; + case '[': goto yy197; + default: goto yy188; } } @@ -3752,92 +3767,97 @@ size_t scan_ref_glossary(const char * c) { char yych; yych = *c; switch (yych) { - case '\n': goto yy198; - case ' ': goto yy199; - case '[': goto yy200; - default: goto yy201; + case '\n': goto yy201; + case ' ': goto yy202; + case '[': goto yy203; + default: goto yy204; } -yy198: +yy201: { return 0; } -yy199: +yy202: yych = *(marker = ++c); switch (yych) { - case ' ': goto yy211; - case '[': goto yy212; - default: goto yy198; + case ' ': goto yy215; + case '[': goto yy216; + default: goto yy201; } -yy200: +yy203: yych = *(marker = ++c); switch (yych) { - case '?': goto yy202; - default: goto yy198; + case '?': goto yy205; + default: goto yy201; } -yy201: - yych = *++c; - goto yy198; -yy202: +yy204: yych = *++c; + goto yy201; +yy205: + ++c; + yych = *c; switch (yych) { - case ']': goto yy203; - default: goto yy205; + case 0x00: + case '\n': + case '\r': + case ']': goto yy207; + case '\\': goto yy205; + default: goto yy208; } -yy203: +yy207: c = marker; - goto yy198; -yy204: + goto yy201; +yy208: ++c; yych = *c; -yy205: switch (yych) { case 0x00: case '\n': - case '\r': goto yy203; - case ']': goto yy206; - default: goto yy204; + case '\r': goto yy207; + case '\\': goto yy205; + case ']': goto yy210; + default: goto yy208; } -yy206: +yy210: yych = *++c; switch (yych) { - case ':': goto yy207; - default: goto yy203; + case ':': goto yy211; + default: goto yy207; } -yy207: +yy211: yych = *++c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy203; - default: goto yy208; + case '\r': goto yy207; + default: goto yy212; } -yy208: +yy212: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy210; - default: goto yy208; + case '\r': goto yy214; + default: goto yy212; } -yy210: +yy214: { return (size_t)( c - start ); } -yy211: +yy215: yych = *++c; switch (yych) { - case ' ': goto yy213; - case '[': goto yy212; - default: goto yy203; + case ' ': goto yy217; + case '[': goto yy216; + default: goto yy207; } -yy212: +yy216: yych = *++c; switch (yych) { - case '?': goto yy202; - default: goto yy203; + case '?': goto yy205; + default: goto yy207; } -yy213: +yy217: ++c; switch ((yych = *c)) { - case '[': goto yy212; - default: goto yy203; + case '[': goto yy216; + default: goto yy207; } } @@ -3854,970 +3874,976 @@ size_t scan_ref_link_no_attributes(const char * c) { unsigned int yyaccept = 0; yych = *c; switch (yych) { - case '\n': goto yy216; - case ' ': goto yy217; - case '[': goto yy218; - default: goto yy219; + case '\n': goto yy220; + case ' ': goto yy221; + case '[': goto yy222; + default: goto yy223; } -yy216: +yy220: { return 0; } -yy217: +yy221: yyaccept = 0; yych = *(marker = ++c); switch (yych) { - case ' ': goto yy353; - case '[': goto yy354; - default: goto yy216; + case ' ': goto yy359; + case '[': goto yy227; + default: goto yy220; } -yy218: +yy222: yyaccept = 0; yych = *(marker = ++c); switch (yych) { case 0x00: case '\n': case '\r': - case ']': goto yy216; - default: goto yy220; + case ']': goto yy220; + default: goto yy225; } -yy219: +yy223: yych = *++c; - goto yy216; -yy220: + goto yy220; +yy224: ++c; yych = *c; -yy221: +yy225: switch (yych) { case 0x00: case '\n': - case '\r': goto yy222; - case ']': goto yy223; - default: goto yy220; + case '\r': goto yy226; + case '\\': goto yy227; + case ']': goto yy229; + default: goto yy224; } -yy222: +yy226: c = marker; if (yyaccept == 0) { - goto yy216; + goto yy220; } else { - goto yy236; + goto yy242; } -yy223: +yy227: + ++c; + yych = *c; + switch (yych) { + case 0x00: + case '\n': + case '\r': + case ']': goto yy226; + case '\\': goto yy227; + default: goto yy224; + } +yy229: yych = *++c; switch (yych) { - case ':': goto yy224; - default: goto yy222; + case ':': goto yy230; + default: goto yy226; } -yy224: +yy230: ++c; yych = *c; switch (yych) { - case 0x00: goto yy222; + case 0x00: goto yy226; case '\t': - case ' ': goto yy224; - case '\n': goto yy226; - case '\r': goto yy228; - case '<': goto yy229; - default: goto yy231; + case ' ': goto yy230; + case '\n': goto yy232; + case '\r': goto yy234; + case '<': goto yy235; + default: goto yy237; } -yy226: +yy232: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy222; + case '\r': goto yy226; case '\t': - case ' ': goto yy226; - case '<': goto yy229; - default: goto yy231; + case ' ': goto yy232; + case '<': goto yy235; + default: goto yy237; } -yy228: +yy234: yych = *++c; switch (yych) { case 0x00: - case '\r': goto yy222; + case '\r': goto yy226; case '\t': case '\n': - case ' ': goto yy226; - case '<': goto yy229; - default: goto yy231; + case ' ': goto yy232; + case '<': goto yy235; + default: goto yy237; } -yy229: +yy235: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy233; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': goto yy326; - case '\'': goto yy328; - case '(': goto yy330; - case '>': goto yy231; - default: goto yy229; + case ' ': goto yy239; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': goto yy332; + case '\'': goto yy334; + case '(': goto yy336; + case '>': goto yy237; + default: goto yy235; } -yy231: +yy237: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy233; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': goto yy239; - case '\'': goto yy241; - case '(': goto yy243; - default: goto yy231; + case ' ': goto yy239; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': goto yy245; + case '\'': goto yy247; + case '(': goto yy249; + default: goto yy237; } -yy233: +yy239: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy233; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': goto yy255; - case '\'': goto yy257; - case '(': goto yy259; - default: goto yy222; + case ' ': goto yy239; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': goto yy261; + case '\'': goto yy263; + case '(': goto yy265; + default: goto yy226; } -yy235: +yy241: ++c; -yy236: +yy242: { return (size_t)( c - start ); } -yy237: +yy243: yyaccept = 1; yych = *(marker = ++c); switch (yych) { - case '"': goto yy255; - case '\'': goto yy257; - case '(': goto yy259; - default: goto yy236; + case '"': goto yy261; + case '\'': goto yy263; + case '(': goto yy265; + default: goto yy242; } -yy238: +yy244: yyaccept = 1; yych = *(marker = ++c); switch (yych) { - case '\n': goto yy237; - case '"': goto yy255; - case '\'': goto yy257; - case '(': goto yy259; - default: goto yy236; + case '\n': goto yy243; + case '"': goto yy261; + case '\'': goto yy263; + case '(': goto yy265; + default: goto yy242; } -yy239: +yy245: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy324; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': goto yy312; - case '\'': goto yy302; - case '(': goto yy247; - default: goto yy239; + case ' ': goto yy330; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': goto yy318; + case '\'': goto yy308; + case '(': goto yy253; + default: goto yy245; } -yy241: +yy247: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy322; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': goto yy302; - case '\'': goto yy264; - case '(': goto yy249; - default: goto yy241; + case ' ': goto yy328; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': goto yy308; + case '\'': goto yy270; + case '(': goto yy255; + default: goto yy247; } -yy243: +yy249: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy245; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': goto yy247; - case '\'': goto yy249; - case ')': goto yy251; - default: goto yy243; + case ' ': goto yy251; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': goto yy253; + case '\'': goto yy255; + case ')': goto yy257; + default: goto yy249; } -yy245: +yy251: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy245; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': goto yy292; - case '\'': goto yy276; - case ')': goto yy261; - default: goto yy259; + case ' ': goto yy251; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': goto yy298; + case '\'': goto yy282; + case ')': goto yy267; + default: goto yy265; } -yy247: +yy253: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy314; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': goto yy316; - case '\'': goto yy268; - case ')': goto yy312; - default: goto yy247; + case ' ': goto yy320; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': goto yy322; + case '\'': goto yy274; + case ')': goto yy318; + default: goto yy253; } -yy249: +yy255: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy266; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': goto yy268; - case '\'': goto yy270; - case ')': goto yy264; - default: goto yy249; + case ' ': goto yy272; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': goto yy274; + case '\'': goto yy276; + case ')': goto yy270; + default: goto yy255; } -yy251: +yy257: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy252; - case '\n': goto yy237; - case '\r': goto yy254; - case '"': goto yy239; - case '\'': goto yy241; - case '(': goto yy243; - default: goto yy231; + case ' ': goto yy258; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': goto yy245; + case '\'': goto yy247; + case '(': goto yy249; + default: goto yy237; } -yy252: +yy258: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy252; - case '\n': goto yy237; - case '\r': goto yy254; - case '"': goto yy255; - case '\'': goto yy257; - case '(': goto yy259; - default: goto yy222; + case ' ': goto yy258; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': goto yy261; + case '\'': goto yy263; + case '(': goto yy265; + default: goto yy226; } -yy254: +yy260: yyaccept = 1; yych = *(marker = ++c); switch (yych) { - case '\n': goto yy237; - case '"': goto yy255; - case '\'': goto yy257; - case '(': goto yy259; - default: goto yy236; + case '\n': goto yy243; + case '"': goto yy261; + case '\'': goto yy263; + case '(': goto yy265; + default: goto yy242; } -yy255: +yy261: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy222; - case '"': goto yy261; - default: goto yy255; + case '\r': goto yy226; + case '"': goto yy267; + default: goto yy261; } -yy257: +yy263: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy222; - case '\'': goto yy261; - default: goto yy257; + case '\r': goto yy226; + case '\'': goto yy267; + default: goto yy263; } -yy259: +yy265: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy222; - case ')': goto yy261; - default: goto yy259; + case '\r': goto yy226; + case ')': goto yy267; + default: goto yy265; } -yy261: +yy267: ++c; yych = *c; switch (yych) { case 0x00: - case '\n': goto yy235; + case '\n': goto yy241; case '\t': - case ' ': goto yy261; - case '\r': goto yy263; - default: goto yy222; + case ' ': goto yy267; + case '\r': goto yy269; + default: goto yy226; } -yy263: +yy269: yych = *++c; switch (yych) { - case '\n': goto yy235; - default: goto yy236; - } -yy264: - ++c; - yych = *c; - switch (yych) { - case 0x00: goto yy235; - case '\t': - case ' ': goto yy310; - case '\n': goto yy237; - case '\r': goto yy254; - case '"': goto yy302; - case '\'': goto yy264; - case '(': goto yy249; - default: goto yy241; - } -yy266: - ++c; - yych = *c; - switch (yych) { - case 0x00: goto yy235; - case '\t': - case ' ': goto yy266; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': goto yy278; - case '\'': goto yy280; - case ')': goto yy274; - default: goto yy276; - } -yy268: - ++c; - yych = *c; - switch (yych) { - case 0x00: goto yy235; - case '\t': - case ' ': goto yy296; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': - case '\'': goto yy294; - case ')': goto yy298; - default: goto yy268; + case '\n': goto yy241; + default: goto yy242; } yy270: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy272; - case '\n': goto yy237; - case '\r': goto yy254; - case '"': goto yy268; + case ' ': goto yy316; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': goto yy308; case '\'': goto yy270; - case ')': goto yy264; - default: goto yy249; + case '(': goto yy255; + default: goto yy247; } yy272: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': case ' ': goto yy272; - case '\n': goto yy237; - case '\r': goto yy254; - case '"': goto yy278; - case '\'': goto yy280; - case ')': goto yy274; - default: goto yy276; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': goto yy284; + case '\'': goto yy286; + case ')': goto yy280; + default: goto yy282; } yy274: ++c; yych = *c; switch (yych) { - case 0x00: - case '\n': goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy274; - case '\r': goto yy263; - case '\'': goto yy261; - default: goto yy257; + case ' ': goto yy302; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': + case '\'': goto yy300; + case ')': goto yy304; + default: goto yy274; } yy276: ++c; yych = *c; switch (yych) { - case 0x00: - case '\n': - case '\r': goto yy222; - case '\'': goto yy282; - case ')': goto yy274; - default: goto yy276; + case 0x00: goto yy241; + case '\t': + case ' ': goto yy278; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': goto yy274; + case '\'': goto yy276; + case ')': goto yy270; + default: goto yy255; } yy278: ++c; yych = *c; switch (yych) { - case 0x00: - case '\n': - case '\r': goto yy222; - case '"': goto yy280; - case '\'': goto yy284; - case ')': goto yy286; - default: goto yy278; + case 0x00: goto yy241; + case '\t': + case ' ': goto yy278; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': goto yy284; + case '\'': goto yy286; + case ')': goto yy280; + default: goto yy282; } yy280: ++c; yych = *c; switch (yych) { case 0x00: - case '\n': goto yy235; + case '\n': goto yy241; case '\t': case ' ': goto yy280; - case '\r': goto yy263; - case '\'': goto yy282; - case ')': goto yy274; - default: goto yy276; + case '\r': goto yy269; + case '\'': goto yy267; + default: goto yy263; } yy282: ++c; yych = *c; switch (yych) { case 0x00: - case '\n': goto yy235; - case '\t': - case ' ': goto yy282; - case '\r': goto yy263; - case ')': goto yy261; - default: goto yy259; + case '\n': + case '\r': goto yy226; + case '\'': goto yy288; + case ')': goto yy280; + default: goto yy282; } yy284: ++c; yych = *c; switch (yych) { case 0x00: - case '\n': goto yy235; - case '\t': - case ' ': goto yy284; - case '\r': goto yy263; - case '"': goto yy282; - case ')': goto yy288; - default: goto yy292; + case '\n': + case '\r': goto yy226; + case '"': goto yy286; + case '\'': goto yy290; + case ')': goto yy292; + default: goto yy284; } yy286: ++c; yych = *c; switch (yych) { case 0x00: - case '\n': goto yy235; + case '\n': goto yy241; case '\t': case ' ': goto yy286; - case '\r': goto yy263; - case '"': goto yy274; + case '\r': goto yy269; case '\'': goto yy288; - default: goto yy290; + case ')': goto yy280; + default: goto yy282; } yy288: ++c; yych = *c; switch (yych) { case 0x00: - case '\n': goto yy235; + case '\n': goto yy241; case '\t': case ' ': goto yy288; - case '\r': goto yy263; - case '"': goto yy261; - default: goto yy255; + case '\r': goto yy269; + case ')': goto yy267; + default: goto yy265; } yy290: ++c; yych = *c; switch (yych) { case 0x00: - case '\n': - case '\r': goto yy222; - case '"': goto yy274; - case '\'': goto yy288; - default: goto yy290; + case '\n': goto yy241; + case '\t': + case ' ': goto yy290; + case '\r': goto yy269; + case '"': goto yy288; + case ')': goto yy294; + default: goto yy298; } yy292: ++c; yych = *c; switch (yych) { case 0x00: - case '\n': - case '\r': goto yy222; - case '"': goto yy282; - case ')': goto yy288; - default: goto yy292; + case '\n': goto yy241; + case '\t': + case ' ': goto yy292; + case '\r': goto yy269; + case '"': goto yy280; + case '\'': goto yy294; + default: goto yy296; } yy294: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: + case '\n': goto yy241; case '\t': - case ' ': goto yy308; - case '\n': goto yy237; - case '\r': goto yy254; - case '"': - case '\'': goto yy294; - case ')': goto yy298; - default: goto yy268; + case ' ': goto yy294; + case '\r': goto yy269; + case '"': goto yy267; + default: goto yy261; } yy296: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; - case '\t': - case ' ': goto yy296; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': - case '\'': goto yy306; - case ')': goto yy286; - default: goto yy278; + case 0x00: + case '\n': + case '\r': goto yy226; + case '"': goto yy280; + case '\'': goto yy294; + default: goto yy296; } yy298: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; - case '\t': - case ' ': goto yy300; - case '\n': goto yy237; - case '\r': goto yy254; - case '"': - case '\'': goto yy298; - case '(': goto yy268; - default: goto yy302; + case 0x00: + case '\n': + case '\r': goto yy226; + case '"': goto yy288; + case ')': goto yy294; + default: goto yy298; } yy300: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy300; - case '\n': goto yy237; - case '\r': goto yy254; + case ' ': goto yy314; + case '\n': goto yy243; + case '\r': goto yy260; case '"': - case '\'': goto yy286; - case '(': goto yy278; - default: goto yy290; + case '\'': goto yy300; + case ')': goto yy304; + default: goto yy274; } yy302: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy304; - case '\n': goto yy237; - case '\r': goto yy238; + case ' ': goto yy302; + case '\n': goto yy243; + case '\r': goto yy244; case '"': - case '\'': goto yy298; - case '(': goto yy268; - default: goto yy302; + case '\'': goto yy312; + case ')': goto yy292; + default: goto yy284; } yy304: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy304; - case '\n': goto yy237; - case '\r': goto yy238; + case ' ': goto yy306; + case '\n': goto yy243; + case '\r': goto yy260; case '"': - case '\'': goto yy286; - case '(': goto yy278; - default: goto yy290; + case '\'': goto yy304; + case '(': goto yy274; + default: goto yy308; } yy306: ++c; yych = *c; switch (yych) { - case 0x00: - case '\n': goto yy235; + case 0x00: goto yy241; case '\t': case ' ': goto yy306; - case '\r': goto yy263; - case '"': goto yy280; - case '\'': goto yy284; - case ')': goto yy286; - default: goto yy278; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': + case '\'': goto yy292; + case '(': goto yy284; + default: goto yy296; } yy308: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy308; - case '\n': goto yy237; - case '\r': goto yy254; + case ' ': goto yy310; + case '\n': goto yy243; + case '\r': goto yy244; case '"': - case '\'': goto yy306; - case ')': goto yy286; - default: goto yy278; + case '\'': goto yy304; + case '(': goto yy274; + default: goto yy308; } yy310: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': case ' ': goto yy310; - case '\n': goto yy237; - case '\r': goto yy254; - case '"': goto yy290; - case '\'': goto yy274; - case '(': goto yy276; - default: goto yy257; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': + case '\'': goto yy292; + case '(': goto yy284; + default: goto yy296; } yy312: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: + case '\n': goto yy241; case '\t': - case ' ': goto yy320; - case '\n': goto yy237; - case '\r': goto yy254; - case '"': goto yy312; - case '\'': goto yy302; - case '(': goto yy247; - default: goto yy239; + case ' ': goto yy312; + case '\r': goto yy269; + case '"': goto yy286; + case '\'': goto yy290; + case ')': goto yy292; + default: goto yy284; } yy314: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': case ' ': goto yy314; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': goto yy284; - case '\'': goto yy278; - case ')': goto yy288; - default: goto yy292; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': + case '\'': goto yy312; + case ')': goto yy292; + default: goto yy284; } yy316: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy318; - case '\n': goto yy237; - case '\r': goto yy254; - case '"': goto yy316; - case '\'': goto yy268; - case ')': goto yy312; - default: goto yy247; + case ' ': goto yy316; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': goto yy296; + case '\'': goto yy280; + case '(': goto yy282; + default: goto yy263; } yy318: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy318; - case '\n': goto yy237; - case '\r': goto yy254; - case '"': goto yy284; - case '\'': goto yy278; - case ')': goto yy288; - default: goto yy292; + case ' ': goto yy326; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': goto yy318; + case '\'': goto yy308; + case '(': goto yy253; + default: goto yy245; } yy320: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': case ' ': goto yy320; - case '\n': goto yy237; - case '\r': goto yy254; - case '"': goto yy288; - case '\'': goto yy290; - case '(': goto yy292; - default: goto yy255; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': goto yy290; + case '\'': goto yy284; + case ')': goto yy294; + default: goto yy298; } yy322: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy322; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': goto yy290; + case ' ': goto yy324; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': goto yy322; case '\'': goto yy274; - case '(': goto yy276; - default: goto yy257; + case ')': goto yy318; + default: goto yy253; } yy324: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': case ' ': goto yy324; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': goto yy288; - case '\'': goto yy290; - case '(': goto yy292; - default: goto yy255; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': goto yy290; + case '\'': goto yy284; + case ')': goto yy294; + default: goto yy298; } yy326: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy324; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': goto yy349; - case '\'': goto yy347; - case '(': goto yy332; - case '>': goto yy239; - default: goto yy326; + case ' ': goto yy326; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': goto yy294; + case '\'': goto yy296; + case '(': goto yy298; + default: goto yy261; } yy328: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy322; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': goto yy347; - case '\'': goto yy337; - case '(': goto yy334; - case '>': goto yy241; - default: goto yy328; + case ' ': goto yy328; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': goto yy296; + case '\'': goto yy280; + case '(': goto yy282; + default: goto yy263; } yy330: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy245; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': goto yy332; - case '\'': goto yy334; - case ')': goto yy336; - case '>': goto yy243; - default: goto yy330; + case ' ': goto yy330; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': goto yy294; + case '\'': goto yy296; + case '(': goto yy298; + default: goto yy261; } yy332: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy314; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': goto yy351; - case '\'': goto yy339; - case ')': goto yy349; - case '>': goto yy247; + case ' ': goto yy330; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': goto yy355; + case '\'': goto yy353; + case '(': goto yy338; + case '>': goto yy245; default: goto yy332; } yy334: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy266; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': goto yy339; - case '\'': goto yy341; - case ')': goto yy337; - case '>': goto yy249; + case ' ': goto yy328; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': goto yy353; + case '\'': goto yy343; + case '(': goto yy340; + case '>': goto yy247; default: goto yy334; } yy336: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy252; - case '\n': goto yy237; - case '\r': goto yy254; - case '"': goto yy326; - case '\'': goto yy328; - case '(': goto yy330; - case '>': goto yy231; - default: goto yy229; + case ' ': goto yy251; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': goto yy338; + case '\'': goto yy340; + case ')': goto yy342; + case '>': goto yy249; + default: goto yy336; } -yy337: +yy338: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy310; - case '\n': goto yy237; - case '\r': goto yy254; - case '"': goto yy347; - case '\'': goto yy337; - case '(': goto yy334; - case '>': goto yy241; - default: goto yy328; + case ' ': goto yy320; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': goto yy357; + case '\'': goto yy345; + case ')': goto yy355; + case '>': goto yy253; + default: goto yy338; } -yy339: +yy340: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy296; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': - case '\'': goto yy343; - case ')': goto yy345; - case '>': goto yy268; - default: goto yy339; + case ' ': goto yy272; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': goto yy345; + case '\'': goto yy347; + case ')': goto yy343; + case '>': goto yy255; + default: goto yy340; } -yy341: +yy342: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy272; - case '\n': goto yy237; - case '\r': goto yy254; - case '"': goto yy339; - case '\'': goto yy341; - case ')': goto yy337; - case '>': goto yy249; - default: goto yy334; + case ' ': goto yy258; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': goto yy332; + case '\'': goto yy334; + case '(': goto yy336; + case '>': goto yy237; + default: goto yy235; } yy343: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy308; - case '\n': goto yy237; - case '\r': goto yy254; - case '"': + case ' ': goto yy316; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': goto yy353; case '\'': goto yy343; - case ')': goto yy345; - case '>': goto yy268; - default: goto yy339; + case '(': goto yy340; + case '>': goto yy247; + default: goto yy334; } yy345: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy300; - case '\n': goto yy237; - case '\r': goto yy254; + case ' ': goto yy302; + case '\n': goto yy243; + case '\r': goto yy244; case '"': - case '\'': goto yy345; - case '(': goto yy339; - case '>': goto yy302; - default: goto yy347; + case '\'': goto yy349; + case ')': goto yy351; + case '>': goto yy274; + default: goto yy345; } yy347: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy304; - case '\n': goto yy237; - case '\r': goto yy238; - case '"': - case '\'': goto yy345; - case '(': goto yy339; - case '>': goto yy302; - default: goto yy347; + case ' ': goto yy278; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': goto yy345; + case '\'': goto yy347; + case ')': goto yy343; + case '>': goto yy255; + default: goto yy340; } yy349: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy320; - case '\n': goto yy237; - case '\r': goto yy254; - case '"': goto yy349; - case '\'': goto yy347; - case '(': goto yy332; - case '>': goto yy239; - default: goto yy326; + case ' ': goto yy314; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': + case '\'': goto yy349; + case ')': goto yy351; + case '>': goto yy274; + default: goto yy345; } yy351: ++c; yych = *c; switch (yych) { - case 0x00: goto yy235; + case 0x00: goto yy241; case '\t': - case ' ': goto yy318; - case '\n': goto yy237; - case '\r': goto yy254; - case '"': goto yy351; - case '\'': goto yy339; - case ')': goto yy349; - case '>': goto yy247; - default: goto yy332; + case ' ': goto yy306; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': + case '\'': goto yy351; + case '(': goto yy345; + case '>': goto yy308; + default: goto yy353; } yy353: - yych = *++c; + ++c; + yych = *c; switch (yych) { - case ' ': goto yy355; - case '[': goto yy354; - default: goto yy222; + case 0x00: goto yy241; + case '\t': + case ' ': goto yy310; + case '\n': goto yy243; + case '\r': goto yy244; + case '"': + case '\'': goto yy351; + case '(': goto yy345; + case '>': goto yy308; + default: goto yy353; + } +yy355: + ++c; + yych = *c; + switch (yych) { + case 0x00: goto yy241; + case '\t': + case ' ': goto yy326; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': goto yy355; + case '\'': goto yy353; + case '(': goto yy338; + case '>': goto yy245; + default: goto yy332; + } +yy357: + ++c; + yych = *c; + switch (yych) { + case 0x00: goto yy241; + case '\t': + case ' ': goto yy324; + case '\n': goto yy243; + case '\r': goto yy260; + case '"': goto yy357; + case '\'': goto yy345; + case ')': goto yy355; + case '>': goto yy253; + default: goto yy338; } -yy354: +yy359: yych = *++c; switch (yych) { - case ']': goto yy222; - default: goto yy221; + case ' ': goto yy360; + case '[': goto yy227; + default: goto yy226; } -yy355: +yy360: ++c; switch ((yych = *c)) { - case '[': goto yy354; - default: goto yy222; + case '[': goto yy227; + default: goto yy226; } } @@ -4833,89 +4859,95 @@ size_t scan_ref_link(const char * c) { char yych; yych = *c; switch (yych) { - case '\n': goto yy358; - case ' ': goto yy359; - case '[': goto yy360; - default: goto yy361; + case '\n': goto yy363; + case ' ': goto yy364; + case '[': goto yy365; + default: goto yy366; } -yy358: +yy363: { return 0; } -yy359: +yy364: yych = *(marker = ++c); switch (yych) { - case ' ': goto yy370; - case '[': goto yy371; - default: goto yy358; + case ' ': goto yy377; + case '[': goto yy370; + default: goto yy363; } -yy360: +yy365: yych = *(marker = ++c); switch (yych) { case 0x00: case '\n': case '\r': - case ']': goto yy358; - default: goto yy362; + case ']': goto yy363; + default: goto yy368; } -yy361: +yy366: yych = *++c; - goto yy358; -yy362: + goto yy363; +yy367: ++c; yych = *c; -yy363: +yy368: switch (yych) { case 0x00: case '\n': - case '\r': goto yy364; - case ']': goto yy365; - default: goto yy362; + case '\r': goto yy369; + case '\\': goto yy370; + case ']': goto yy372; + default: goto yy367; } -yy364: +yy369: c = marker; - goto yy358; -yy365: + goto yy363; +yy370: + ++c; + yych = *c; + switch (yych) { + case 0x00: + case '\n': + case '\r': + case ']': goto yy369; + case '\\': goto yy370; + default: goto yy367; + } +yy372: yych = *++c; switch (yych) { - case ':': goto yy366; - default: goto yy364; + case ':': goto yy373; + default: goto yy369; } -yy366: +yy373: yych = *++c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy364; - default: goto yy367; + case '\r': goto yy369; + default: goto yy374; } -yy367: +yy374: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy369; - default: goto yy367; + case '\r': goto yy376; + default: goto yy374; } -yy369: +yy376: { return (size_t)( c - start ); } -yy370: - yych = *++c; - switch (yych) { - case ' ': goto yy372; - case '[': goto yy371; - default: goto yy364; - } -yy371: +yy377: yych = *++c; switch (yych) { - case ']': goto yy364; - default: goto yy363; + case ' ': goto yy378; + case '[': goto yy370; + default: goto yy369; } -yy372: +yy378: ++c; switch ((yych = *c)) { - case '[': goto yy371; - default: goto yy364; + case '[': goto yy370; + default: goto yy369; } } @@ -4931,17 +4963,17 @@ size_t scan_html(const char * c) { char yych; yych = *c; switch (yych) { - case '\n': goto yy375; - case '<': goto yy376; - default: goto yy377; + case '\n': goto yy381; + case '<': goto yy382; + default: goto yy383; } -yy375: +yy381: { return 0; } -yy376: +yy382: yych = *(marker = ++c); switch (yych) { - case '!': goto yy378; - case '/': goto yy380; + case '!': goto yy384; + case '/': goto yy386; case 'A': case 'B': case 'C': @@ -4993,22 +5025,22 @@ size_t scan_html(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy381; - default: goto yy375; + case 'z': goto yy387; + default: goto yy381; } -yy377: +yy383: yych = *++c; - goto yy375; -yy378: + goto yy381; +yy384: yych = *++c; switch (yych) { - case '-': goto yy409; - default: goto yy379; + case '-': goto yy415; + default: goto yy385; } -yy379: +yy385: c = marker; - goto yy375; -yy380: + goto yy381; +yy386: yych = *++c; switch (yych) { case 'A': @@ -5062,17 +5094,17 @@ size_t scan_html(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy405; - default: goto yy379; + case 'z': goto yy411; + default: goto yy385; } -yy381: +yy387: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy385; - case '\n': goto yy387; - case '\r': goto yy389; + case ' ': goto yy391; + case '\n': goto yy393; + case '\r': goto yy395; case '-': case '0': case '1': @@ -5083,11 +5115,11 @@ size_t scan_html(const char * c) { case '6': case '7': case '8': - case '9': goto yy381; - case '/': goto yy394; + case '9': goto yy387; + case '/': goto yy400; case ':': - case '_': goto yy390; - case '>': goto yy392; + case '_': goto yy396; + case '>': goto yy398; case 'A': case 'B': case 'C': @@ -5139,17 +5171,17 @@ size_t scan_html(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy383; - default: goto yy379; + case 'z': goto yy389; + default: goto yy385; } -yy383: +yy389: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy385; - case '\n': goto yy387; - case '\r': goto yy389; + case ' ': goto yy391; + case '\n': goto yy393; + case '\r': goto yy395; case '-': case '0': case '1': @@ -5212,24 +5244,24 @@ size_t scan_html(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy383; + case 'z': goto yy389; case '.': case ':': - case '_': goto yy390; - case '/': goto yy394; - case '=': goto yy395; - case '>': goto yy392; - default: goto yy379; + case '_': goto yy396; + case '/': goto yy400; + case '=': goto yy401; + case '>': goto yy398; + default: goto yy385; } -yy385: +yy391: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy385; - case '\n': goto yy387; - case '\r': goto yy389; - case '/': goto yy394; + case ' ': goto yy391; + case '\n': goto yy393; + case '\r': goto yy395; + case '/': goto yy400; case ':': case 'A': case 'B': @@ -5283,16 +5315,16 @@ size_t scan_html(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy390; - case '>': goto yy392; - default: goto yy379; + case 'z': goto yy396; + case '>': goto yy398; + default: goto yy385; } -yy387: +yy393: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy387; + case ' ': goto yy393; case ':': case 'A': case 'B': @@ -5346,16 +5378,16 @@ size_t scan_html(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy390; - default: goto yy379; + case 'z': goto yy396; + default: goto yy385; } -yy389: +yy395: ++c; yych = *c; switch (yych) { case '\t': case '\n': - case ' ': goto yy387; + case ' ': goto yy393; case ':': case 'A': case 'B': @@ -5409,10 +5441,10 @@ size_t scan_html(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy390; - default: goto yy379; + case 'z': goto yy396; + default: goto yy385; } -yy390: +yy396: ++c; yych = *c; switch (yych) { @@ -5481,27 +5513,27 @@ size_t scan_html(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy390; - case '=': goto yy395; - default: goto yy379; + case 'z': goto yy396; + case '=': goto yy401; + default: goto yy385; } -yy392: +yy398: ++c; { return (size_t)( c - start ); } -yy394: +yy400: yych = *++c; switch (yych) { - case '>': goto yy392; - default: goto yy379; + case '>': goto yy398; + default: goto yy385; } -yy395: +yy401: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy395; - case '"': goto yy397; - case '\'': goto yy399; + case ' ': goto yy401; + case '"': goto yy403; + case '\'': goto yy405; case '.': case '0': case '1': @@ -5564,37 +5596,37 @@ size_t scan_html(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy401; - default: goto yy379; + case 'z': goto yy407; + default: goto yy385; } -yy397: +yy403: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy379; - case '"': goto yy385; - default: goto yy397; + case '\r': goto yy385; + case '"': goto yy391; + default: goto yy403; } -yy399: +yy405: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy379; - case '\'': goto yy385; - default: goto yy399; + case '\r': goto yy385; + case '\'': goto yy391; + default: goto yy405; } -yy401: +yy407: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy385; - case '\n': goto yy387; - case '\r': goto yy389; + case ' ': goto yy391; + case '\n': goto yy393; + case '\r': goto yy395; case '.': case '0': case '1': @@ -5605,11 +5637,11 @@ size_t scan_html(const char * c) { case '6': case '7': case '8': - case '9': goto yy401; - case '/': goto yy394; + case '9': goto yy407; + case '/': goto yy400; case ':': - case '_': goto yy390; - case '>': goto yy392; + case '_': goto yy396; + case '>': goto yy398; case 'A': case 'B': case 'C': @@ -5661,20 +5693,20 @@ size_t scan_html(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy403; - default: goto yy379; + case 'z': goto yy409; + default: goto yy385; } -yy403: +yy409: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy385; - case '\n': goto yy387; - case '\r': goto yy389; + case ' ': goto yy391; + case '\n': goto yy393; + case '\r': goto yy395; case '-': case ':': - case '_': goto yy390; + case '_': goto yy396; case '.': case '0': case '1': @@ -5737,18 +5769,18 @@ size_t scan_html(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy403; - case '/': goto yy394; - case '=': goto yy395; - case '>': goto yy392; - default: goto yy379; + case 'z': goto yy409; + case '/': goto yy400; + case '=': goto yy401; + case '>': goto yy398; + default: goto yy385; } -yy405: +yy411: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy407; + case ' ': goto yy413; case '-': case '0': case '1': @@ -5811,58 +5843,58 @@ size_t scan_html(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy405; - case '>': goto yy392; - default: goto yy379; + case 'z': goto yy411; + case '>': goto yy398; + default: goto yy385; } -yy407: +yy413: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy407; - case '>': goto yy392; - default: goto yy379; + case ' ': goto yy413; + case '>': goto yy398; + default: goto yy385; } -yy409: +yy415: yych = *++c; switch (yych) { - case '-': goto yy410; - default: goto yy379; + case '-': goto yy416; + default: goto yy385; } -yy410: +yy416: yych = *++c; switch (yych) { - case '-': goto yy379; - default: goto yy412; + case '-': goto yy385; + default: goto yy418; } -yy411: +yy417: ++c; yych = *c; -yy412: +yy418: switch (yych) { case 0x00: - case '>': goto yy379; - case '-': goto yy413; - default: goto yy411; + case '>': goto yy385; + case '-': goto yy419; + default: goto yy417; } -yy413: +yy419: ++c; yych = *c; switch (yych) { case 0x00: - case '>': goto yy379; - case '-': goto yy414; - default: goto yy411; + case '>': goto yy385; + case '-': goto yy420; + default: goto yy417; } -yy414: +yy420: ++c; yych = *c; switch (yych) { - case 0x00: goto yy379; - case '-': goto yy414; - case '>': goto yy392; - default: goto yy411; + case 0x00: goto yy385; + case '-': goto yy420; + case '>': goto yy398; + default: goto yy417; } } @@ -5878,71 +5910,71 @@ size_t scan_html_comment(const char * c) { char yych; yych = *c; switch (yych) { - case '\n': goto yy418; - case '<': goto yy419; - default: goto yy420; + case '\n': goto yy424; + case '<': goto yy425; + default: goto yy426; } -yy418: +yy424: { return 0; } -yy419: +yy425: yych = *(marker = ++c); switch (yych) { - case '!': goto yy421; - default: goto yy418; + case '!': goto yy427; + default: goto yy424; } -yy420: +yy426: yych = *++c; - goto yy418; -yy421: + goto yy424; +yy427: yych = *++c; switch (yych) { - case '-': goto yy423; - default: goto yy422; + case '-': goto yy429; + default: goto yy428; } -yy422: +yy428: c = marker; - goto yy418; -yy423: + goto yy424; +yy429: yych = *++c; switch (yych) { - case '-': goto yy424; - default: goto yy422; + case '-': goto yy430; + default: goto yy428; } -yy424: +yy430: yych = *++c; switch (yych) { - case '-': goto yy422; - default: goto yy426; + case '-': goto yy428; + default: goto yy432; } -yy425: +yy431: ++c; yych = *c; -yy426: +yy432: switch (yych) { case 0x00: - case '>': goto yy422; - case '-': goto yy427; - default: goto yy425; + case '>': goto yy428; + case '-': goto yy433; + default: goto yy431; } -yy427: +yy433: ++c; yych = *c; switch (yych) { case 0x00: - case '>': goto yy422; - case '-': goto yy428; - default: goto yy425; + case '>': goto yy428; + case '-': goto yy434; + default: goto yy431; } -yy428: +yy434: ++c; yych = *c; switch (yych) { - case 0x00: goto yy422; - case '-': goto yy428; - case '>': goto yy430; - default: goto yy425; + case 0x00: goto yy428; + case '-': goto yy434; + case '>': goto yy436; + default: goto yy431; } -yy430: +yy436: ++c; { return (size_t)( c - start ); } } @@ -5959,130 +5991,130 @@ size_t scan_html_block(const char * c) { char yych; yych = *c; switch (yych) { - case '\n': goto yy434; - case '<': goto yy435; - default: goto yy436; + case '\n': goto yy440; + case '<': goto yy441; + default: goto yy442; } -yy434: +yy440: { return 0; } -yy435: +yy441: yych = *(marker = ++c); switch (yych) { - case '/': goto yy437; + case '/': goto yy443; case 'A': - case 'a': goto yy440; + case 'a': goto yy446; case 'B': - case 'b': goto yy441; + case 'b': goto yy447; case 'C': - case 'c': goto yy442; + case 'c': goto yy448; case 'D': - case 'd': goto yy443; + case 'd': goto yy449; case 'F': - case 'f': goto yy444; + case 'f': goto yy450; case 'H': - case 'h': goto yy445; + case 'h': goto yy451; case 'I': - case 'i': goto yy446; + case 'i': goto yy452; case 'L': - case 'l': goto yy447; + case 'l': goto yy453; case 'M': - case 'm': goto yy448; + case 'm': goto yy454; case 'N': - case 'n': goto yy449; + case 'n': goto yy455; case 'O': - case 'o': goto yy450; + case 'o': goto yy456; case 'P': - case 'p': goto yy439; + case 'p': goto yy445; case 'S': - case 's': goto yy451; + case 's': goto yy457; case 'T': - case 't': goto yy452; + case 't': goto yy458; case 'U': - case 'u': goto yy453; + case 'u': goto yy459; case 'V': - case 'v': goto yy454; - default: goto yy434; + case 'v': goto yy460; + default: goto yy440; } -yy436: +yy442: yych = *++c; - goto yy434; -yy437: + goto yy440; +yy443: yych = *++c; switch (yych) { case 'A': - case 'a': goto yy440; + case 'a': goto yy446; case 'B': - case 'b': goto yy441; + case 'b': goto yy447; case 'C': - case 'c': goto yy442; + case 'c': goto yy448; case 'D': - case 'd': goto yy443; + case 'd': goto yy449; case 'F': - case 'f': goto yy444; + case 'f': goto yy450; case 'H': - case 'h': goto yy445; + case 'h': goto yy451; case 'I': - case 'i': goto yy446; + case 'i': goto yy452; case 'L': - case 'l': goto yy447; + case 'l': goto yy453; case 'M': - case 'm': goto yy448; + case 'm': goto yy454; case 'N': - case 'n': goto yy449; + case 'n': goto yy455; case 'O': - case 'o': goto yy450; + case 'o': goto yy456; case 'P': - case 'p': goto yy439; + case 'p': goto yy445; case 'S': - case 's': goto yy451; + case 's': goto yy457; case 'T': - case 't': goto yy452; + case 't': goto yy458; case 'U': - case 'u': goto yy453; + case 'u': goto yy459; case 'V': - case 'v': goto yy454; - default: goto yy438; + case 'v': goto yy460; + default: goto yy444; } -yy438: +yy444: c = marker; - goto yy434; -yy439: + goto yy440; +yy445: yych = *++c; switch (yych) { - case '/': goto yy466; - case '>': goto yy467; + case '/': goto yy472; + case '>': goto yy473; case 'R': - case 'r': goto yy586; - default: goto yy460; + case 'r': goto yy592; + default: goto yy466; } -yy440: +yy446: yych = *++c; switch (yych) { case 'D': - case 'd': goto yy575; + case 'd': goto yy581; case 'R': - case 'r': goto yy574; + case 'r': goto yy580; case 'S': - case 's': goto yy573; - default: goto yy438; + case 's': goto yy579; + default: goto yy444; } -yy441: +yy447: yych = *++c; switch (yych) { case 'L': - case 'l': goto yy565; - default: goto yy438; + case 'l': goto yy571; + default: goto yy444; } -yy442: +yy448: yych = *++c; switch (yych) { case 'A': - case 'a': goto yy558; + case 'a': goto yy564; case 'E': - case 'e': goto yy557; - default: goto yy438; + case 'e': goto yy563; + default: goto yy444; } -yy443: +yy449: yych = *++c; switch (yych) { case 'D': @@ -6090,23 +6122,23 @@ size_t scan_html_block(const char * c) { case 'T': case 'd': case 'l': - case 't': goto yy458; + case 't': goto yy464; case 'I': - case 'i': goto yy556; - default: goto yy438; + case 'i': goto yy562; + default: goto yy444; } -yy444: +yy450: yych = *++c; switch (yych) { case 'I': - case 'i': goto yy532; + case 'i': goto yy538; case 'O': - case 'o': goto yy531; + case 'o': goto yy537; case 'R': - case 'r': goto yy530; - default: goto yy438; + case 'r': goto yy536; + default: goto yy444; } -yy445: +yy451: yych = *++c; switch (yych) { case '1': @@ -6116,122 +6148,122 @@ size_t scan_html_block(const char * c) { case '5': case '6': case 'R': - case 'r': goto yy458; + case 'r': goto yy464; case 'E': - case 'e': goto yy523; + case 'e': goto yy529; case 'G': - case 'g': goto yy522; - default: goto yy438; + case 'g': goto yy528; + default: goto yy444; } -yy446: +yy452: yych = *++c; switch (yych) { case 'S': - case 's': goto yy517; - default: goto yy438; + case 's': goto yy523; + default: goto yy444; } -yy447: +yy453: yych = *++c; switch (yych) { case 'I': - case 'i': goto yy458; - default: goto yy438; + case 'i': goto yy464; + default: goto yy444; } -yy448: +yy454: yych = *++c; switch (yych) { case 'A': - case 'a': goto yy514; + case 'a': goto yy520; case 'E': - case 'e': goto yy513; - default: goto yy438; + case 'e': goto yy519; + default: goto yy444; } -yy449: +yy455: yych = *++c; switch (yych) { case 'A': - case 'a': goto yy502; + case 'a': goto yy508; case 'O': - case 'o': goto yy501; - default: goto yy438; + case 'o': goto yy507; + default: goto yy444; } -yy450: +yy456: yych = *++c; switch (yych) { case 'L': - case 'l': goto yy458; + case 'l': goto yy464; case 'U': - case 'u': goto yy497; - default: goto yy438; + case 'u': goto yy503; + default: goto yy444; } -yy451: +yy457: yych = *++c; switch (yych) { case 'E': - case 'e': goto yy492; - default: goto yy438; + case 'e': goto yy498; + default: goto yy444; } -yy452: +yy458: yych = *++c; switch (yych) { case 'A': - case 'a': goto yy482; + case 'a': goto yy488; case 'B': - case 'b': goto yy481; + case 'b': goto yy487; case 'D': case 'R': case 'd': - case 'r': goto yy458; + case 'r': goto yy464; case 'F': - case 'f': goto yy480; + case 'f': goto yy486; case 'H': - case 'h': goto yy479; - default: goto yy438; + case 'h': goto yy485; + default: goto yy444; } -yy453: +yy459: yych = *++c; switch (yych) { case 'L': - case 'l': goto yy458; - default: goto yy438; + case 'l': goto yy464; + default: goto yy444; } -yy454: +yy460: yych = *++c; switch (yych) { case 'I': - case 'i': goto yy455; - default: goto yy438; + case 'i': goto yy461; + default: goto yy444; } -yy455: +yy461: yych = *++c; switch (yych) { case 'D': - case 'd': goto yy456; - default: goto yy438; + case 'd': goto yy462; + default: goto yy444; } -yy456: +yy462: yych = *++c; switch (yych) { case 'E': - case 'e': goto yy457; - default: goto yy438; + case 'e': goto yy463; + default: goto yy444; } -yy457: +yy463: yych = *++c; switch (yych) { case 'O': - case 'o': goto yy458; - default: goto yy438; + case 'o': goto yy464; + default: goto yy444; } -yy458: +yy464: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy459; - case '\n': goto yy461; - case '\r': goto yy463; - case '/': goto yy466; + case ' ': goto yy465; + case '\n': goto yy467; + case '\r': goto yy469; + case '/': goto yy472; case ':': case 'A': case 'B': @@ -6285,19 +6317,19 @@ size_t scan_html_block(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy464; - case '>': goto yy467; - default: goto yy438; + case 'z': goto yy470; + case '>': goto yy473; + default: goto yy444; } -yy459: +yy465: ++c; yych = *c; -yy460: +yy466: switch (yych) { case '\t': - case ' ': goto yy459; - case '\n': goto yy461; - case '\r': goto yy463; + case ' ': goto yy465; + case '\n': goto yy467; + case '\r': goto yy469; case ':': case 'A': case 'B': @@ -6351,15 +6383,15 @@ size_t scan_html_block(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy464; - default: goto yy438; + case 'z': goto yy470; + default: goto yy444; } -yy461: +yy467: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy461; + case ' ': goto yy467; case ':': case 'A': case 'B': @@ -6413,16 +6445,16 @@ size_t scan_html_block(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy464; - default: goto yy438; + case 'z': goto yy470; + default: goto yy444; } -yy463: +yy469: ++c; yych = *c; switch (yych) { case '\t': case '\n': - case ' ': goto yy461; + case ' ': goto yy467; case ':': case 'A': case 'B': @@ -6476,13 +6508,13 @@ size_t scan_html_block(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy464; - default: goto yy438; + case 'z': goto yy470; + default: goto yy444; } -yy464: +yy470: ++c; yych = *c; -yy465: +yy471: switch (yych) { case '-': case '.': @@ -6549,27 +6581,27 @@ size_t scan_html_block(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy464; - case '=': goto yy469; - default: goto yy438; + case 'z': goto yy470; + case '=': goto yy475; + default: goto yy444; } -yy466: +yy472: yych = *++c; switch (yych) { - case '>': goto yy467; - default: goto yy438; + case '>': goto yy473; + default: goto yy444; } -yy467: +yy473: ++c; { return (size_t)( c - start ); } -yy469: +yy475: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy469; - case '"': goto yy471; - case '\'': goto yy473; + case ' ': goto yy475; + case '"': goto yy477; + case '\'': goto yy479; case '.': case '0': case '1': @@ -6632,37 +6664,37 @@ size_t scan_html_block(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy475; - default: goto yy438; + case 'z': goto yy481; + default: goto yy444; } -yy471: +yy477: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy438; - case '"': goto yy458; - default: goto yy471; + case '\r': goto yy444; + case '"': goto yy464; + default: goto yy477; } -yy473: +yy479: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy438; - case '\'': goto yy458; - default: goto yy473; + case '\r': goto yy444; + case '\'': goto yy464; + default: goto yy479; } -yy475: +yy481: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy459; - case '\n': goto yy461; - case '\r': goto yy463; + case ' ': goto yy465; + case '\n': goto yy467; + case '\r': goto yy469; case '.': case '0': case '1': @@ -6673,11 +6705,11 @@ size_t scan_html_block(const char * c) { case '6': case '7': case '8': - case '9': goto yy475; - case '/': goto yy466; + case '9': goto yy481; + case '/': goto yy472; case ':': - case '_': goto yy464; - case '>': goto yy467; + case '_': goto yy470; + case '>': goto yy473; case 'A': case 'B': case 'C': @@ -6729,20 +6761,20 @@ size_t scan_html_block(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy477; - default: goto yy438; + case 'z': goto yy483; + default: goto yy444; } -yy477: +yy483: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy459; - case '\n': goto yy461; - case '\r': goto yy463; + case ' ': goto yy465; + case '\n': goto yy467; + case '\r': goto yy469; case '-': case ':': - case '_': goto yy464; + case '_': goto yy470; case '.': case '0': case '1': @@ -6805,99 +6837,99 @@ size_t scan_html_block(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy477; - case '/': goto yy466; - case '=': goto yy469; - case '>': goto yy467; - default: goto yy438; + case 'z': goto yy483; + case '/': goto yy472; + case '=': goto yy475; + case '>': goto yy473; + default: goto yy444; } -yy479: +yy485: yych = *++c; switch (yych) { - case '/': goto yy466; - case '>': goto yy467; + case '/': goto yy472; + case '>': goto yy473; case 'E': - case 'e': goto yy489; - default: goto yy460; + case 'e': goto yy495; + default: goto yy466; } -yy480: +yy486: yych = *++c; switch (yych) { case 'O': - case 'o': goto yy487; - default: goto yy438; + case 'o': goto yy493; + default: goto yy444; } -yy481: +yy487: yych = *++c; switch (yych) { case 'O': - case 'o': goto yy485; - default: goto yy438; + case 'o': goto yy491; + default: goto yy444; } -yy482: +yy488: yych = *++c; switch (yych) { case 'B': - case 'b': goto yy483; - default: goto yy438; + case 'b': goto yy489; + default: goto yy444; } -yy483: +yy489: yych = *++c; switch (yych) { case 'L': - case 'l': goto yy484; - default: goto yy438; + case 'l': goto yy490; + default: goto yy444; } -yy484: +yy490: yych = *++c; switch (yych) { case 'E': - case 'e': goto yy458; - default: goto yy438; + case 'e': goto yy464; + default: goto yy444; } -yy485: +yy491: yych = *++c; switch (yych) { case 'D': - case 'd': goto yy486; - default: goto yy438; + case 'd': goto yy492; + default: goto yy444; } -yy486: +yy492: yych = *++c; switch (yych) { case 'Y': - case 'y': goto yy458; - default: goto yy438; + case 'y': goto yy464; + default: goto yy444; } -yy487: +yy493: yych = *++c; switch (yych) { case 'O': - case 'o': goto yy488; - default: goto yy438; + case 'o': goto yy494; + default: goto yy444; } -yy488: +yy494: yych = *++c; switch (yych) { case 'T': - case 't': goto yy458; - default: goto yy438; + case 't': goto yy464; + default: goto yy444; } -yy489: +yy495: yych = *++c; switch (yych) { case 'A': - case 'a': goto yy490; - default: goto yy465; + case 'a': goto yy496; + default: goto yy471; } -yy490: +yy496: yych = *++c; switch (yych) { case 'D': - case 'd': goto yy491; - default: goto yy465; + case 'd': goto yy497; + default: goto yy471; } -yy491: +yy497: yych = *++c; switch (yych) { case '-': @@ -6911,686 +6943,686 @@ size_t scan_html_block(const char * c) { case '6': case '7': case '8': - case '9': goto yy464; - case '/': goto yy466; - case '=': goto yy469; - case '>': goto yy467; - default: goto yy460; + case '9': goto yy470; + case '/': goto yy472; + case '=': goto yy475; + case '>': goto yy473; + default: goto yy466; } -yy492: +yy498: yych = *++c; switch (yych) { case 'C': - case 'c': goto yy493; - default: goto yy438; + case 'c': goto yy499; + default: goto yy444; } -yy493: +yy499: yych = *++c; switch (yych) { case 'T': - case 't': goto yy494; - default: goto yy438; + case 't': goto yy500; + default: goto yy444; } -yy494: +yy500: yych = *++c; switch (yych) { case 'I': - case 'i': goto yy495; - default: goto yy438; + case 'i': goto yy501; + default: goto yy444; } -yy495: +yy501: yych = *++c; switch (yych) { case 'O': - case 'o': goto yy496; - default: goto yy438; + case 'o': goto yy502; + default: goto yy444; } -yy496: +yy502: yych = *++c; switch (yych) { case 'N': - case 'n': goto yy458; - default: goto yy438; + case 'n': goto yy464; + default: goto yy444; } -yy497: +yy503: yych = *++c; switch (yych) { case 'T': - case 't': goto yy498; - default: goto yy438; + case 't': goto yy504; + default: goto yy444; } -yy498: +yy504: yych = *++c; switch (yych) { case 'P': - case 'p': goto yy499; - default: goto yy438; + case 'p': goto yy505; + default: goto yy444; } -yy499: +yy505: yych = *++c; switch (yych) { case 'U': - case 'u': goto yy500; - default: goto yy438; + case 'u': goto yy506; + default: goto yy444; } -yy500: +yy506: yych = *++c; switch (yych) { case 'T': - case 't': goto yy458; - default: goto yy438; + case 't': goto yy464; + default: goto yy444; } -yy501: +yy507: yych = *++c; switch (yych) { case 'F': - case 'f': goto yy503; + case 'f': goto yy509; case 'S': - case 's': goto yy504; - default: goto yy438; + case 's': goto yy510; + default: goto yy444; } -yy502: +yy508: yych = *++c; switch (yych) { case 'V': - case 'v': goto yy458; - default: goto yy438; + case 'v': goto yy464; + default: goto yy444; } -yy503: +yy509: yych = *++c; switch (yych) { case 'R': - case 'r': goto yy509; - default: goto yy438; + case 'r': goto yy515; + default: goto yy444; } -yy504: +yy510: yych = *++c; switch (yych) { case 'C': - case 'c': goto yy505; - default: goto yy438; + case 'c': goto yy511; + default: goto yy444; } -yy505: +yy511: yych = *++c; switch (yych) { case 'R': - case 'r': goto yy506; - default: goto yy438; + case 'r': goto yy512; + default: goto yy444; } -yy506: +yy512: yych = *++c; switch (yych) { case 'I': - case 'i': goto yy507; - default: goto yy438; + case 'i': goto yy513; + default: goto yy444; } -yy507: +yy513: yych = *++c; switch (yych) { case 'P': - case 'p': goto yy508; - default: goto yy438; + case 'p': goto yy514; + default: goto yy444; } -yy508: +yy514: yych = *++c; switch (yych) { case 'T': - case 't': goto yy458; - default: goto yy438; + case 't': goto yy464; + default: goto yy444; } -yy509: +yy515: yych = *++c; switch (yych) { case 'A': - case 'a': goto yy510; - default: goto yy438; + case 'a': goto yy516; + default: goto yy444; } -yy510: +yy516: yych = *++c; switch (yych) { case 'M': - case 'm': goto yy511; - default: goto yy438; + case 'm': goto yy517; + default: goto yy444; } -yy511: +yy517: yych = *++c; switch (yych) { case 'E': - case 'e': goto yy512; - default: goto yy438; + case 'e': goto yy518; + default: goto yy444; } -yy512: +yy518: yych = *++c; switch (yych) { case 'S': - case 's': goto yy458; - default: goto yy438; + case 's': goto yy464; + default: goto yy444; } -yy513: +yy519: yych = *++c; switch (yych) { case 'N': - case 'n': goto yy516; - default: goto yy438; + case 'n': goto yy522; + default: goto yy444; } -yy514: +yy520: yych = *++c; switch (yych) { case 'I': - case 'i': goto yy515; - default: goto yy438; + case 'i': goto yy521; + default: goto yy444; } -yy515: +yy521: yych = *++c; switch (yych) { case 'N': - case 'n': goto yy458; - default: goto yy438; + case 'n': goto yy464; + default: goto yy444; } -yy516: +yy522: yych = *++c; switch (yych) { case 'U': - case 'u': goto yy458; - default: goto yy438; + case 'u': goto yy464; + default: goto yy444; } -yy517: +yy523: yych = *++c; switch (yych) { case 'I': - case 'i': goto yy518; - default: goto yy438; + case 'i': goto yy524; + default: goto yy444; } -yy518: +yy524: yych = *++c; switch (yych) { case 'N': - case 'n': goto yy519; - default: goto yy438; + case 'n': goto yy525; + default: goto yy444; } -yy519: +yy525: yych = *++c; switch (yych) { case 'D': - case 'd': goto yy520; - default: goto yy438; + case 'd': goto yy526; + default: goto yy444; } -yy520: +yy526: yych = *++c; switch (yych) { case 'E': - case 'e': goto yy521; - default: goto yy438; + case 'e': goto yy527; + default: goto yy444; } -yy521: +yy527: yych = *++c; switch (yych) { case 'X': - case 'x': goto yy458; - default: goto yy438; + case 'x': goto yy464; + default: goto yy444; } -yy522: +yy528: yych = *++c; switch (yych) { case 'R': - case 'r': goto yy527; - default: goto yy438; + case 'r': goto yy533; + default: goto yy444; } -yy523: +yy529: yych = *++c; switch (yych) { case 'A': - case 'a': goto yy524; - default: goto yy438; + case 'a': goto yy530; + default: goto yy444; } -yy524: +yy530: yych = *++c; switch (yych) { case 'D': - case 'd': goto yy525; - default: goto yy438; + case 'd': goto yy531; + default: goto yy444; } -yy525: +yy531: yych = *++c; switch (yych) { case 'E': - case 'e': goto yy526; - default: goto yy438; + case 'e': goto yy532; + default: goto yy444; } -yy526: +yy532: yych = *++c; switch (yych) { case 'R': - case 'r': goto yy458; - default: goto yy438; + case 'r': goto yy464; + default: goto yy444; } -yy527: +yy533: yych = *++c; switch (yych) { case 'O': - case 'o': goto yy528; - default: goto yy438; + case 'o': goto yy534; + default: goto yy444; } -yy528: +yy534: yych = *++c; switch (yych) { case 'U': - case 'u': goto yy529; - default: goto yy438; + case 'u': goto yy535; + default: goto yy444; } -yy529: +yy535: yych = *++c; switch (yych) { case 'P': - case 'p': goto yy458; - default: goto yy438; + case 'p': goto yy464; + default: goto yy444; } -yy530: +yy536: yych = *++c; switch (yych) { case 'A': - case 'a': goto yy551; - default: goto yy438; + case 'a': goto yy557; + default: goto yy444; } -yy531: +yy537: yych = *++c; switch (yych) { case 'O': - case 'o': goto yy547; + case 'o': goto yy553; case 'R': - case 'r': goto yy548; - default: goto yy438; + case 'r': goto yy554; + default: goto yy444; } -yy532: +yy538: yych = *++c; switch (yych) { case 'E': - case 'e': goto yy533; + case 'e': goto yy539; case 'G': - case 'g': goto yy534; - default: goto yy438; + case 'g': goto yy540; + default: goto yy444; } -yy533: +yy539: yych = *++c; switch (yych) { case 'L': - case 'l': goto yy543; - default: goto yy438; + case 'l': goto yy549; + default: goto yy444; } -yy534: +yy540: yych = *++c; switch (yych) { case 'C': - case 'c': goto yy536; + case 'c': goto yy542; case 'U': - case 'u': goto yy535; - default: goto yy438; + case 'u': goto yy541; + default: goto yy444; } -yy535: +yy541: yych = *++c; switch (yych) { case 'R': - case 'r': goto yy542; - default: goto yy438; + case 'r': goto yy548; + default: goto yy444; } -yy536: +yy542: yych = *++c; switch (yych) { case 'A': - case 'a': goto yy537; - default: goto yy438; + case 'a': goto yy543; + default: goto yy444; } -yy537: +yy543: yych = *++c; switch (yych) { case 'P': - case 'p': goto yy538; - default: goto yy438; + case 'p': goto yy544; + default: goto yy444; } -yy538: +yy544: yych = *++c; switch (yych) { case 'T': - case 't': goto yy539; - default: goto yy438; + case 't': goto yy545; + default: goto yy444; } -yy539: +yy545: yych = *++c; switch (yych) { case 'I': - case 'i': goto yy540; - default: goto yy438; + case 'i': goto yy546; + default: goto yy444; } -yy540: +yy546: yych = *++c; switch (yych) { case 'O': - case 'o': goto yy541; - default: goto yy438; + case 'o': goto yy547; + default: goto yy444; } -yy541: +yy547: yych = *++c; switch (yych) { case 'N': - case 'n': goto yy458; - default: goto yy438; + case 'n': goto yy464; + default: goto yy444; } -yy542: +yy548: yych = *++c; switch (yych) { case 'E': - case 'e': goto yy458; - default: goto yy438; + case 'e': goto yy464; + default: goto yy444; } -yy543: +yy549: yych = *++c; switch (yych) { case 'D': - case 'd': goto yy544; - default: goto yy438; + case 'd': goto yy550; + default: goto yy444; } -yy544: +yy550: yych = *++c; switch (yych) { case 'S': - case 's': goto yy545; - default: goto yy438; + case 's': goto yy551; + default: goto yy444; } -yy545: +yy551: yych = *++c; switch (yych) { case 'E': - case 'e': goto yy546; - default: goto yy438; + case 'e': goto yy552; + default: goto yy444; } -yy546: +yy552: yych = *++c; switch (yych) { case 'T': - case 't': goto yy458; - default: goto yy438; + case 't': goto yy464; + default: goto yy444; } -yy547: +yy553: yych = *++c; switch (yych) { case 'T': - case 't': goto yy549; - default: goto yy438; + case 't': goto yy555; + default: goto yy444; } -yy548: +yy554: yych = *++c; switch (yych) { case 'M': - case 'm': goto yy458; - default: goto yy438; + case 'm': goto yy464; + default: goto yy444; } -yy549: +yy555: yych = *++c; switch (yych) { case 'E': - case 'e': goto yy550; - default: goto yy438; + case 'e': goto yy556; + default: goto yy444; } -yy550: +yy556: yych = *++c; switch (yych) { case 'R': - case 'r': goto yy458; - default: goto yy438; + case 'r': goto yy464; + default: goto yy444; } -yy551: +yy557: yych = *++c; switch (yych) { case 'M': - case 'm': goto yy552; - default: goto yy438; + case 'm': goto yy558; + default: goto yy444; } -yy552: +yy558: yych = *++c; switch (yych) { case 'E': - case 'e': goto yy553; - default: goto yy438; + case 'e': goto yy559; + default: goto yy444; } -yy553: +yy559: yych = *++c; switch (yych) { case 'S': - case 's': goto yy554; - default: goto yy438; + case 's': goto yy560; + default: goto yy444; } -yy554: +yy560: yych = *++c; switch (yych) { case 'E': - case 'e': goto yy555; - default: goto yy438; + case 'e': goto yy561; + default: goto yy444; } -yy555: +yy561: yych = *++c; switch (yych) { case 'T': - case 't': goto yy458; - default: goto yy438; + case 't': goto yy464; + default: goto yy444; } -yy556: +yy562: yych = *++c; switch (yych) { case 'R': case 'V': case 'r': - case 'v': goto yy458; - default: goto yy438; + case 'v': goto yy464; + default: goto yy444; } -yy557: +yy563: yych = *++c; switch (yych) { case 'N': - case 'n': goto yy562; - default: goto yy438; + case 'n': goto yy568; + default: goto yy444; } -yy558: +yy564: yych = *++c; switch (yych) { case 'N': - case 'n': goto yy559; - default: goto yy438; + case 'n': goto yy565; + default: goto yy444; } -yy559: +yy565: yych = *++c; switch (yych) { case 'V': - case 'v': goto yy560; - default: goto yy438; + case 'v': goto yy566; + default: goto yy444; } -yy560: +yy566: yych = *++c; switch (yych) { case 'A': - case 'a': goto yy561; - default: goto yy438; + case 'a': goto yy567; + default: goto yy444; } -yy561: +yy567: yych = *++c; switch (yych) { case 'S': - case 's': goto yy458; - default: goto yy438; + case 's': goto yy464; + default: goto yy444; } -yy562: +yy568: yych = *++c; switch (yych) { case 'T': - case 't': goto yy563; - default: goto yy438; + case 't': goto yy569; + default: goto yy444; } -yy563: +yy569: yych = *++c; switch (yych) { case 'E': - case 'e': goto yy564; - default: goto yy438; + case 'e': goto yy570; + default: goto yy444; } -yy564: +yy570: yych = *++c; switch (yych) { case 'R': - case 'r': goto yy458; - default: goto yy438; + case 'r': goto yy464; + default: goto yy444; } -yy565: +yy571: yych = *++c; switch (yych) { case 'O': - case 'o': goto yy566; - default: goto yy438; + case 'o': goto yy572; + default: goto yy444; } -yy566: +yy572: yych = *++c; switch (yych) { case 'C': - case 'c': goto yy567; - default: goto yy438; + case 'c': goto yy573; + default: goto yy444; } -yy567: +yy573: yych = *++c; switch (yych) { case 'K': - case 'k': goto yy568; - default: goto yy438; + case 'k': goto yy574; + default: goto yy444; } -yy568: +yy574: yych = *++c; switch (yych) { case 'Q': - case 'q': goto yy569; - default: goto yy438; + case 'q': goto yy575; + default: goto yy444; } -yy569: +yy575: yych = *++c; switch (yych) { case 'U': - case 'u': goto yy570; - default: goto yy438; + case 'u': goto yy576; + default: goto yy444; } -yy570: +yy576: yych = *++c; switch (yych) { case 'O': - case 'o': goto yy571; - default: goto yy438; + case 'o': goto yy577; + default: goto yy444; } -yy571: +yy577: yych = *++c; switch (yych) { case 'T': - case 't': goto yy572; - default: goto yy438; + case 't': goto yy578; + default: goto yy444; } -yy572: +yy578: yych = *++c; switch (yych) { case 'E': - case 'e': goto yy458; - default: goto yy438; + case 'e': goto yy464; + default: goto yy444; } -yy573: +yy579: yych = *++c; switch (yych) { case 'I': - case 'i': goto yy584; - default: goto yy438; + case 'i': goto yy590; + default: goto yy444; } -yy574: +yy580: yych = *++c; switch (yych) { case 'T': - case 't': goto yy580; - default: goto yy438; + case 't': goto yy586; + default: goto yy444; } -yy575: +yy581: yych = *++c; switch (yych) { case 'D': - case 'd': goto yy576; - default: goto yy438; + case 'd': goto yy582; + default: goto yy444; } -yy576: +yy582: yych = *++c; switch (yych) { case 'R': - case 'r': goto yy577; - default: goto yy438; + case 'r': goto yy583; + default: goto yy444; } -yy577: +yy583: yych = *++c; switch (yych) { case 'E': - case 'e': goto yy578; - default: goto yy438; + case 'e': goto yy584; + default: goto yy444; } -yy578: +yy584: yych = *++c; switch (yych) { case 'S': - case 's': goto yy579; - default: goto yy438; + case 's': goto yy585; + default: goto yy444; } -yy579: +yy585: yych = *++c; switch (yych) { case 'S': - case 's': goto yy458; - default: goto yy438; + case 's': goto yy464; + default: goto yy444; } -yy580: +yy586: yych = *++c; switch (yych) { case 'I': - case 'i': goto yy581; - default: goto yy438; + case 'i': goto yy587; + default: goto yy444; } -yy581: +yy587: yych = *++c; switch (yych) { case 'C': - case 'c': goto yy582; - default: goto yy438; + case 'c': goto yy588; + default: goto yy444; } -yy582: +yy588: yych = *++c; switch (yych) { case 'L': - case 'l': goto yy583; - default: goto yy438; + case 'l': goto yy589; + default: goto yy444; } -yy583: +yy589: yych = *++c; switch (yych) { case 'E': - case 'e': goto yy458; - default: goto yy438; + case 'e': goto yy464; + default: goto yy444; } -yy584: +yy590: yych = *++c; switch (yych) { case 'D': - case 'd': goto yy585; - default: goto yy438; + case 'd': goto yy591; + default: goto yy444; } -yy585: +yy591: yych = *++c; switch (yych) { case 'E': - case 'e': goto yy458; - default: goto yy438; + case 'e': goto yy464; + default: goto yy444; } -yy586: +yy592: ++c; switch ((yych = *c)) { case 'E': - case 'e': goto yy491; - default: goto yy465; + case 'e': goto yy497; + default: goto yy471; } } @@ -7606,17 +7638,17 @@ size_t scan_html_line(const char * c) { char yych; yych = *c; switch (yych) { - case '\n': goto yy589; - case '<': goto yy590; - default: goto yy591; + case '\n': goto yy595; + case '<': goto yy596; + default: goto yy597; } -yy589: +yy595: { return 0; } -yy590: +yy596: yych = *(marker = ++c); switch (yych) { - case '!': goto yy592; - case '/': goto yy594; + case '!': goto yy598; + case '/': goto yy600; case 'A': case 'B': case 'C': @@ -7668,22 +7700,22 @@ size_t scan_html_line(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy595; - default: goto yy589; + case 'z': goto yy601; + default: goto yy595; } -yy591: +yy597: yych = *++c; - goto yy589; -yy592: + goto yy595; +yy598: yych = *++c; switch (yych) { - case '-': goto yy626; - default: goto yy593; + case '-': goto yy632; + default: goto yy599; } -yy593: +yy599: c = marker; - goto yy589; -yy594: + goto yy595; +yy600: yych = *++c; switch (yych) { case 'A': @@ -7737,17 +7769,17 @@ size_t scan_html_line(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy622; - default: goto yy593; + case 'z': goto yy628; + default: goto yy599; } -yy595: +yy601: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy599; - case '\n': goto yy601; - case '\r': goto yy603; + case ' ': goto yy605; + case '\n': goto yy607; + case '\r': goto yy609; case '-': case '0': case '1': @@ -7758,11 +7790,11 @@ size_t scan_html_line(const char * c) { case '6': case '7': case '8': - case '9': goto yy595; - case '/': goto yy608; + case '9': goto yy601; + case '/': goto yy614; case ':': - case '_': goto yy604; - case '>': goto yy606; + case '_': goto yy610; + case '>': goto yy612; case 'A': case 'B': case 'C': @@ -7814,17 +7846,17 @@ size_t scan_html_line(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy597; - default: goto yy593; + case 'z': goto yy603; + default: goto yy599; } -yy597: +yy603: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy599; - case '\n': goto yy601; - case '\r': goto yy603; + case ' ': goto yy605; + case '\n': goto yy607; + case '\r': goto yy609; case '-': case '0': case '1': @@ -7887,24 +7919,24 @@ size_t scan_html_line(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy597; + case 'z': goto yy603; case '.': case ':': - case '_': goto yy604; - case '/': goto yy608; - case '=': goto yy612; - case '>': goto yy606; - default: goto yy593; + case '_': goto yy610; + case '/': goto yy614; + case '=': goto yy618; + case '>': goto yy612; + default: goto yy599; } -yy599: +yy605: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy599; - case '\n': goto yy601; - case '\r': goto yy603; - case '/': goto yy608; + case ' ': goto yy605; + case '\n': goto yy607; + case '\r': goto yy609; + case '/': goto yy614; case ':': case 'A': case 'B': @@ -7958,16 +7990,16 @@ size_t scan_html_line(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy604; - case '>': goto yy606; - default: goto yy593; + case 'z': goto yy610; + case '>': goto yy612; + default: goto yy599; } -yy601: +yy607: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy601; + case ' ': goto yy607; case ':': case 'A': case 'B': @@ -8021,16 +8053,16 @@ size_t scan_html_line(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy604; - default: goto yy593; + case 'z': goto yy610; + default: goto yy599; } -yy603: +yy609: ++c; yych = *c; switch (yych) { case '\t': case '\n': - case ' ': goto yy601; + case ' ': goto yy607; case ':': case 'A': case 'B': @@ -8084,10 +8116,10 @@ size_t scan_html_line(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy604; - default: goto yy593; + case 'z': goto yy610; + default: goto yy599; } -yy604: +yy610: ++c; yych = *c; switch (yych) { @@ -8156,44 +8188,44 @@ size_t scan_html_line(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy604; - case '=': goto yy612; - default: goto yy593; + case 'z': goto yy610; + case '=': goto yy618; + default: goto yy599; } -yy606: +yy612: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy606; - case '\n': goto yy609; - case '\r': goto yy611; - default: goto yy593; + case ' ': goto yy612; + case '\n': goto yy615; + case '\r': goto yy617; + default: goto yy599; } -yy608: +yy614: yych = *++c; switch (yych) { - case '>': goto yy606; - default: goto yy593; + case '>': goto yy612; + default: goto yy599; } -yy609: +yy615: ++c; -yy610: +yy616: { return (size_t)( c - start ); } -yy611: +yy617: yych = *++c; switch (yych) { - case '\n': goto yy609; - default: goto yy610; + case '\n': goto yy615; + default: goto yy616; } -yy612: +yy618: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy612; - case '"': goto yy614; - case '\'': goto yy616; + case ' ': goto yy618; + case '"': goto yy620; + case '\'': goto yy622; case '.': case '0': case '1': @@ -8256,37 +8288,37 @@ size_t scan_html_line(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy618; - default: goto yy593; + case 'z': goto yy624; + default: goto yy599; } -yy614: +yy620: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy593; - case '"': goto yy599; - default: goto yy614; + case '\r': goto yy599; + case '"': goto yy605; + default: goto yy620; } -yy616: +yy622: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy593; - case '\'': goto yy599; - default: goto yy616; + case '\r': goto yy599; + case '\'': goto yy605; + default: goto yy622; } -yy618: +yy624: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy599; - case '\n': goto yy601; - case '\r': goto yy603; + case ' ': goto yy605; + case '\n': goto yy607; + case '\r': goto yy609; case '.': case '0': case '1': @@ -8297,11 +8329,11 @@ size_t scan_html_line(const char * c) { case '6': case '7': case '8': - case '9': goto yy618; - case '/': goto yy608; + case '9': goto yy624; + case '/': goto yy614; case ':': - case '_': goto yy604; - case '>': goto yy606; + case '_': goto yy610; + case '>': goto yy612; case 'A': case 'B': case 'C': @@ -8353,20 +8385,20 @@ size_t scan_html_line(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy620; - default: goto yy593; + case 'z': goto yy626; + default: goto yy599; } -yy620: +yy626: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy599; - case '\n': goto yy601; - case '\r': goto yy603; + case ' ': goto yy605; + case '\n': goto yy607; + case '\r': goto yy609; case '-': case ':': - case '_': goto yy604; + case '_': goto yy610; case '.': case '0': case '1': @@ -8429,18 +8461,18 @@ size_t scan_html_line(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy620; - case '/': goto yy608; - case '=': goto yy612; - case '>': goto yy606; - default: goto yy593; + case 'z': goto yy626; + case '/': goto yy614; + case '=': goto yy618; + case '>': goto yy612; + default: goto yy599; } -yy622: +yy628: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy624; + case ' ': goto yy630; case '-': case '0': case '1': @@ -8503,58 +8535,58 @@ size_t scan_html_line(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy622; - case '>': goto yy606; - default: goto yy593; + case 'z': goto yy628; + case '>': goto yy612; + default: goto yy599; } -yy624: +yy630: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy624; - case '>': goto yy606; - default: goto yy593; + case ' ': goto yy630; + case '>': goto yy612; + default: goto yy599; } -yy626: +yy632: yych = *++c; switch (yych) { - case '-': goto yy627; - default: goto yy593; + case '-': goto yy633; + default: goto yy599; } -yy627: +yy633: yych = *++c; switch (yych) { - case '-': goto yy593; - default: goto yy629; + case '-': goto yy599; + default: goto yy635; } -yy628: +yy634: ++c; yych = *c; -yy629: +yy635: switch (yych) { case 0x00: - case '>': goto yy593; - case '-': goto yy630; - default: goto yy628; + case '>': goto yy599; + case '-': goto yy636; + default: goto yy634; } -yy630: +yy636: ++c; yych = *c; switch (yych) { case 0x00: - case '>': goto yy593; - case '-': goto yy631; - default: goto yy628; + case '>': goto yy599; + case '-': goto yy637; + default: goto yy634; } -yy631: +yy637: ++c; yych = *c; switch (yych) { - case 0x00: goto yy593; - case '-': goto yy631; - case '>': goto yy606; - default: goto yy628; + case 0x00: goto yy599; + case '-': goto yy637; + case '>': goto yy612; + default: goto yy634; } } @@ -8570,108 +8602,108 @@ size_t scan_fence_start(const char * c) { char yych; yych = *c; switch (yych) { - case '\n': goto yy635; - case ' ': goto yy636; + case '\n': goto yy641; + case ' ': goto yy642; case '`': - case '~': goto yy637; - default: goto yy638; + case '~': goto yy643; + default: goto yy644; } -yy635: +yy641: { return 0; } -yy636: +yy642: yych = *(marker = ++c); switch (yych) { - case ' ': goto yy650; + case ' ': goto yy656; case '`': - case '~': goto yy651; - default: goto yy635; + case '~': goto yy657; + default: goto yy641; } -yy637: +yy643: yych = *(marker = ++c); switch (yych) { case '`': - case '~': goto yy639; - default: goto yy635; + case '~': goto yy645; + default: goto yy641; } -yy638: +yy644: yych = *++c; - goto yy635; -yy639: + goto yy641; +yy645: yych = *++c; switch (yych) { case '`': - case '~': goto yy641; - default: goto yy640; + case '~': goto yy647; + default: goto yy646; } -yy640: +yy646: c = marker; - goto yy635; -yy641: + goto yy641; +yy647: ++c; yych = *c; switch (yych) { case 0x00: case '\n': case '\r': - case '\'': goto yy640; - case '`': goto yy641; - case '~': goto yy645; - default: goto yy643; + case '\'': goto yy646; + case '`': goto yy647; + case '~': goto yy651; + default: goto yy649; } -yy643: +yy649: ++c; yych = *c; switch (yych) { case 0x00: - case '\n': goto yy647; - case '\r': goto yy649; + case '\n': goto yy653; + case '\r': goto yy655; case '\'': - case '`': goto yy640; - default: goto yy643; + case '`': goto yy646; + default: goto yy649; } -yy645: +yy651: ++c; yych = *c; switch (yych) { case 0x00: - case '\n': goto yy647; - case '\r': goto yy649; - case '\'': goto yy640; - case '`': goto yy641; - case '~': goto yy645; - default: goto yy643; + case '\n': goto yy653; + case '\r': goto yy655; + case '\'': goto yy646; + case '`': goto yy647; + case '~': goto yy651; + default: goto yy649; } -yy647: +yy653: ++c; -yy648: +yy654: { return (size_t)( c - start ); } -yy649: +yy655: yych = *++c; switch (yych) { - case '\n': goto yy647; - default: goto yy648; + case '\n': goto yy653; + default: goto yy654; } -yy650: +yy656: yych = *++c; switch (yych) { - case ' ': goto yy652; + case ' ': goto yy658; case '`': - case '~': goto yy651; - default: goto yy640; + case '~': goto yy657; + default: goto yy646; } -yy651: +yy657: yych = *++c; switch (yych) { case '`': - case '~': goto yy639; - default: goto yy640; + case '~': goto yy645; + default: goto yy646; } -yy652: +yy658: ++c; switch ((yych = *c)) { case '`': - case '~': goto yy651; - default: goto yy640; + case '~': goto yy657; + default: goto yy646; } } @@ -8687,97 +8719,97 @@ size_t scan_fence_end(const char * c) { char yych; yych = *c; switch (yych) { - case '\n': goto yy655; - case ' ': goto yy656; + case '\n': goto yy661; + case ' ': goto yy662; case '`': - case '~': goto yy657; - default: goto yy658; + case '~': goto yy663; + default: goto yy664; } -yy655: +yy661: { return 0; } -yy656: +yy662: yych = *(marker = ++c); switch (yych) { - case ' ': goto yy668; + case ' ': goto yy674; case '`': - case '~': goto yy669; - default: goto yy655; + case '~': goto yy675; + default: goto yy661; } -yy657: +yy663: yych = *(marker = ++c); switch (yych) { case '`': - case '~': goto yy659; - default: goto yy655; + case '~': goto yy665; + default: goto yy661; } -yy658: +yy664: yych = *++c; - goto yy655; -yy659: + goto yy661; +yy665: yych = *++c; switch (yych) { case '`': - case '~': goto yy661; - default: goto yy660; + case '~': goto yy667; + default: goto yy666; } -yy660: +yy666: c = marker; - goto yy655; -yy661: + goto yy661; +yy667: ++c; yych = *c; switch (yych) { case 0x00: - case '\n': goto yy665; + case '\n': goto yy671; case '\t': - case ' ': goto yy663; - case '\r': goto yy667; + case ' ': goto yy669; + case '\r': goto yy673; case '`': - case '~': goto yy661; - default: goto yy660; + case '~': goto yy667; + default: goto yy666; } -yy663: +yy669: ++c; yych = *c; switch (yych) { case 0x00: - case '\n': goto yy665; + case '\n': goto yy671; case '\t': - case ' ': goto yy663; - case '\r': goto yy667; - default: goto yy660; + case ' ': goto yy669; + case '\r': goto yy673; + default: goto yy666; } -yy665: +yy671: ++c; -yy666: +yy672: { return (size_t)( c - start ); } -yy667: +yy673: yych = *++c; switch (yych) { - case '\n': goto yy665; - default: goto yy666; + case '\n': goto yy671; + default: goto yy672; } -yy668: +yy674: yych = *++c; switch (yych) { - case ' ': goto yy670; + case ' ': goto yy676; case '`': - case '~': goto yy669; - default: goto yy660; + case '~': goto yy675; + default: goto yy666; } -yy669: +yy675: yych = *++c; switch (yych) { case '`': - case '~': goto yy659; - default: goto yy660; + case '~': goto yy665; + default: goto yy666; } -yy670: +yy676: ++c; switch ((yych = *c)) { case '`': - case '~': goto yy669; - default: goto yy660; + case '~': goto yy675; + default: goto yy666; } } @@ -8793,7 +8825,7 @@ size_t scan_meta_line(const char * c) { char yych; yych = *c; switch (yych) { - case '\n': goto yy673; + case '\n': goto yy679; case '0': case '1': case '2': @@ -8855,12 +8887,12 @@ size_t scan_meta_line(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy674; - default: goto yy675; + case 'z': goto yy680; + default: goto yy681; } -yy673: +yy679: { return 0; } -yy674: +yy680: yych = *(marker = ++c); switch (yych) { case '\t': @@ -8930,16 +8962,16 @@ size_t scan_meta_line(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy677; - default: goto yy673; + case 'z': goto yy683; + default: goto yy679; } -yy675: +yy681: yych = *++c; - goto yy673; -yy676: + goto yy679; +yy682: ++c; yych = *c; -yy677: +yy683: switch (yych) { case '\t': case ' ': @@ -9007,39 +9039,39 @@ size_t scan_meta_line(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy676; - case ':': goto yy679; - default: goto yy678; + case 'z': goto yy682; + case ':': goto yy685; + default: goto yy684; } -yy678: +yy684: c = marker; - goto yy673; -yy679: + goto yy679; +yy685: yych = *++c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy678; - default: goto yy680; + case '\r': goto yy684; + default: goto yy686; } -yy680: +yy686: ++c; yych = *c; switch (yych) { case 0x00: - case '\n': goto yy682; - case '\r': goto yy684; - default: goto yy680; + case '\n': goto yy688; + case '\r': goto yy690; + default: goto yy686; } -yy682: +yy688: ++c; -yy683: +yy689: { return (size_t)( c - start ); } -yy684: +yy690: ++c; switch ((yych = *c)) { - case '\n': goto yy682; - default: goto yy683; + case '\n': goto yy688; + default: goto yy689; } } @@ -9054,7 +9086,7 @@ size_t scan_meta_key(const char * c) { char yych; yych = *c; switch (yych) { - case '\n': goto yy687; + case '\n': goto yy693; case '0': case '1': case '2': @@ -9116,24 +9148,24 @@ size_t scan_meta_key(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy688; - default: goto yy690; + case 'z': goto yy694; + default: goto yy696; } -yy687: +yy693: { return 0; } -yy688: +yy694: ++c; yych = *c; - goto yy692; -yy689: + goto yy698; +yy695: { return (size_t)( c - start ); } -yy690: +yy696: yych = *++c; - goto yy687; -yy691: + goto yy693; +yy697: ++c; yych = *c; -yy692: +yy698: switch (yych) { case '\t': case ' ': @@ -9201,8 +9233,8 @@ size_t scan_meta_key(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy691; - default: goto yy689; + case 'z': goto yy697; + default: goto yy695; } } @@ -9218,71 +9250,71 @@ size_t scan_definition(const char * c) { char yych; yych = *c; switch (yych) { - case '\n': goto yy695; - case ' ': goto yy696; - case ':': goto yy697; - default: goto yy698; + case '\n': goto yy701; + case ' ': goto yy702; + case ':': goto yy703; + default: goto yy704; } -yy695: +yy701: { return 0; } -yy696: +yy702: yych = *(marker = ++c); switch (yych) { - case ' ': goto yy703; - case ':': goto yy705; - default: goto yy695; + case ' ': goto yy709; + case ':': goto yy711; + default: goto yy701; } -yy697: +yy703: yych = *++c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy695; - default: goto yy700; + case '\r': goto yy701; + default: goto yy706; } -yy698: +yy704: yych = *++c; - goto yy695; -yy699: + goto yy701; +yy705: ++c; yych = *c; -yy700: +yy706: switch (yych) { case 0x00: case '\n': - case '\r': goto yy701; + case '\r': goto yy707; case '\t': - case ' ': goto yy699; - default: goto yy702; + case ' ': goto yy705; + default: goto yy708; } -yy701: +yy707: { return (size_t)( c - start ); } -yy702: +yy708: yych = *++c; - goto yy701; -yy703: + goto yy707; +yy709: yych = *++c; switch (yych) { - case ' ': goto yy706; - case ':': goto yy705; - default: goto yy704; + case ' ': goto yy712; + case ':': goto yy711; + default: goto yy710; } -yy704: +yy710: c = marker; - goto yy695; -yy705: + goto yy701; +yy711: yych = *++c; switch (yych) { case 0x00: case '\n': - case '\r': goto yy704; - default: goto yy700; + case '\r': goto yy710; + default: goto yy706; } -yy706: +yy712: ++c; switch ((yych = *c)) { - case ':': goto yy705; - default: goto yy704; + case ':': goto yy711; + default: goto yy710; } } @@ -9303,14 +9335,14 @@ size_t scan_table_separator(const char * c) { case '+': case '-': case ':': - case '=': goto yy711; - case '\n': goto yy709; - case '|': goto yy710; - default: goto yy712; + case '=': goto yy717; + case '\n': goto yy715; + case '|': goto yy716; + default: goto yy718; } -yy709: +yy715: { return 0; } -yy710: +yy716: yych = *(marker = ++c); switch (yych) { case 0x00: @@ -9322,10 +9354,10 @@ size_t scan_table_separator(const char * c) { case '-': case ':': case '=': - case '|': goto yy722; - default: goto yy709; + case '|': goto yy728; + default: goto yy715; } -yy711: +yy717: yych = *(marker = ++c); switch (yych) { case '\t': @@ -9333,33 +9365,33 @@ size_t scan_table_separator(const char * c) { case '+': case '-': case ':': - case '=': goto yy716; - case '|': goto yy713; - default: goto yy709; + case '=': goto yy722; + case '|': goto yy719; + default: goto yy715; } -yy712: +yy718: yych = *++c; - goto yy709; -yy713: + goto yy715; +yy719: ++c; yych = *c; switch (yych) { case 0x00: - case '\n': goto yy718; + case '\n': goto yy724; case '\t': case ' ': case '+': case '-': case ':': case '=': - case '|': goto yy713; - case '\r': goto yy720; - default: goto yy715; + case '|': goto yy719; + case '\r': goto yy726; + default: goto yy721; } -yy715: +yy721: c = marker; - goto yy709; -yy716: + goto yy715; +yy722: ++c; yych = *c; switch (yych) { @@ -9368,36 +9400,36 @@ size_t scan_table_separator(const char * c) { case '+': case '-': case ':': - case '=': goto yy716; - case '|': goto yy713; - default: goto yy715; + case '=': goto yy722; + case '|': goto yy719; + default: goto yy721; } -yy718: +yy724: ++c; -yy719: +yy725: { return (size_t)( c - start ); } -yy720: +yy726: yych = *++c; switch (yych) { - case '\n': goto yy718; - default: goto yy719; + case '\n': goto yy724; + default: goto yy725; } -yy721: +yy727: ++c; yych = *c; -yy722: +yy728: switch (yych) { case 0x00: - case '\n': goto yy718; + case '\n': goto yy724; case '\t': case ' ': case '+': case '-': case ':': case '=': - case '|': goto yy721; - case '\r': goto yy720; - default: goto yy715; + case '|': goto yy727; + case '\r': goto yy726; + default: goto yy721; } } @@ -9413,234 +9445,234 @@ size_t scan_alignment_string(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy726; - case '\n': goto yy725; + case ' ': goto yy732; + case '\n': goto yy731; case '-': - case '=': goto yy728; - case ':': goto yy727; - default: goto yy729; + case '=': goto yy734; + case ':': goto yy733; + default: goto yy735; } -yy725: +yy731: { return 0; } -yy726: +yy732: yych = *(marker = ++c); switch (yych) { case '\t': - case ' ': goto yy768; + case ' ': goto yy774; case '-': - case '=': goto yy732; - case ':': goto yy767; - default: goto yy725; + case '=': goto yy738; + case ':': goto yy773; + default: goto yy731; } -yy727: +yy733: yych = *(marker = ++c); switch (yych) { case '-': - case '=': goto yy744; - default: goto yy725; + case '=': goto yy750; + default: goto yy731; } -yy728: +yy734: yych = *(marker = ++c); switch (yych) { case '-': - case '=': goto yy732; - case ':': goto yy730; - default: goto yy725; + case '=': goto yy738; + case ':': goto yy736; + default: goto yy731; } -yy729: +yy735: yych = *++c; - goto yy725; -yy730: + goto yy731; +yy736: yych = *++c; switch (yych) { - case '+': goto yy739; - default: goto yy735; + case '+': goto yy745; + default: goto yy741; } -yy731: +yy737: c = marker; - goto yy725; -yy732: + goto yy731; +yy738: ++c; yych = *c; switch (yych) { case '-': - case '=': goto yy732; - case ':': goto yy730; - default: goto yy731; + case '=': goto yy738; + case ':': goto yy736; + default: goto yy737; } -yy734: +yy740: ++c; yych = *c; -yy735: +yy741: switch (yych) { case 0x00: case '\n': - case '|': goto yy736; + case '|': goto yy742; case '\t': - case ' ': goto yy734; - case '\r': goto yy738; - default: goto yy731; + case ' ': goto yy740; + case '\r': goto yy744; + default: goto yy737; } -yy736: +yy742: ++c; -yy737: +yy743: { return ALIGN_RIGHT; } -yy738: +yy744: yych = *++c; switch (yych) { - case '\n': goto yy736; - default: goto yy737; + case '\n': goto yy742; + default: goto yy743; } -yy739: +yy745: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '|': goto yy741; + case '|': goto yy747; case '\t': - case ' ': goto yy739; - case '\r': goto yy743; - default: goto yy731; + case ' ': goto yy745; + case '\r': goto yy749; + default: goto yy737; } -yy741: +yy747: ++c; -yy742: +yy748: { return ALIGN_WRAP | ALIGN_RIGHT; } -yy743: +yy749: yych = *++c; switch (yych) { - case '\n': goto yy741; - default: goto yy742; + case '\n': goto yy747; + default: goto yy748; } -yy744: +yy750: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '|': goto yy748; + case '|': goto yy754; case '\t': - case ' ': goto yy746; - case '\r': goto yy750; - case '+': goto yy752; + case ' ': goto yy752; + case '\r': goto yy756; + case '+': goto yy758; case '-': - case '=': goto yy744; - case ':': goto yy751; - default: goto yy731; + case '=': goto yy750; + case ':': goto yy757; + default: goto yy737; } -yy746: +yy752: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '|': goto yy748; + case '|': goto yy754; case '\t': - case ' ': goto yy746; - case '\r': goto yy750; - default: goto yy731; + case ' ': goto yy752; + case '\r': goto yy756; + default: goto yy737; } -yy748: +yy754: ++c; -yy749: +yy755: { return ALIGN_LEFT; } -yy750: +yy756: yych = *++c; switch (yych) { - case '\n': goto yy748; - default: goto yy749; + case '\n': goto yy754; + default: goto yy755; } -yy751: +yy757: yych = *++c; switch (yych) { - case '+': goto yy757; - default: goto yy760; + case '+': goto yy763; + default: goto yy766; } -yy752: +yy758: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '|': goto yy754; + case '|': goto yy760; case '\t': - case ' ': goto yy752; - case '\r': goto yy756; - default: goto yy731; + case ' ': goto yy758; + case '\r': goto yy762; + default: goto yy737; } -yy754: +yy760: ++c; -yy755: +yy761: { return ALIGN_WRAP | ALIGN_LEFT; } -yy756: +yy762: yych = *++c; switch (yych) { - case '\n': goto yy754; - default: goto yy755; + case '\n': goto yy760; + default: goto yy761; } -yy757: +yy763: ++c; yych = *c; switch (yych) { case 0x00: case '\n': - case '|': goto yy764; + case '|': goto yy770; case '\t': - case ' ': goto yy757; - case '\r': goto yy766; - default: goto yy731; + case ' ': goto yy763; + case '\r': goto yy772; + default: goto yy737; } -yy759: +yy765: ++c; yych = *c; -yy760: +yy766: switch (yych) { case 0x00: case '\n': - case '|': goto yy761; + case '|': goto yy767; case '\t': - case ' ': goto yy759; - case '\r': goto yy763; - default: goto yy731; + case ' ': goto yy765; + case '\r': goto yy769; + default: goto yy737; } -yy761: +yy767: ++c; -yy762: +yy768: { return ALIGN_CENTER; } -yy763: +yy769: yych = *++c; switch (yych) { - case '\n': goto yy761; - default: goto yy762; + case '\n': goto yy767; + default: goto yy768; } -yy764: +yy770: ++c; -yy765: +yy771: { return ALIGN_WRAP | ALIGN_CENTER; } -yy766: +yy772: yych = *++c; switch (yych) { - case '\n': goto yy764; - default: goto yy765; + case '\n': goto yy770; + default: goto yy771; } -yy767: +yy773: yych = *++c; switch (yych) { case '-': - case '=': goto yy744; - default: goto yy731; + case '=': goto yy750; + default: goto yy737; } -yy768: +yy774: ++c; yych = *c; switch (yych) { case '\t': - case ' ': goto yy768; + case ' ': goto yy774; case '-': - case '=': goto yy732; - case ':': goto yy767; - default: goto yy731; + case '=': goto yy738; + case ':': goto yy773; + default: goto yy737; } } @@ -9658,49 +9690,49 @@ size_t scan_destination(const char * c) { case 0x00: case '\t': case '\r': - case ' ': goto yy776; - case '\n': goto yy772; - case '<': goto yy773; - default: goto yy775; + case ' ': goto yy782; + case '\n': goto yy778; + case '<': goto yy779; + default: goto yy781; } -yy772: +yy778: { return 0; } -yy773: +yy779: ++c; yych = *c; - goto yy780; -yy774: + goto yy786; +yy780: { return (size_t)( c - start ); } -yy775: +yy781: yych = *++c; - goto yy778; -yy776: + goto yy784; +yy782: yych = *++c; - goto yy772; -yy777: + goto yy778; +yy783: ++c; yych = *c; -yy778: +yy784: switch (yych) { case 0x00: case '\t': case '\n': case '\r': - case ' ': goto yy774; - default: goto yy777; + case ' ': goto yy780; + default: goto yy783; } -yy779: +yy785: ++c; yych = *c; -yy780: +yy786: switch (yych) { case 0x00: case '\t': case '\n': case '\r': - case ' ': goto yy774; - case '>': goto yy777; - default: goto yy779; + case ' ': goto yy780; + case '>': goto yy783; + default: goto yy785; } } @@ -9716,79 +9748,79 @@ size_t scan_title(const char * c) { char yych; yych = *c; switch (yych) { - case '\n': goto yy783; - case '"': goto yy784; - case '\'': goto yy785; - case '(': goto yy786; - default: goto yy787; + case '\n': goto yy789; + case '"': goto yy790; + case '\'': goto yy791; + case '(': goto yy792; + default: goto yy793; } -yy783: +yy789: { return 0; } -yy784: +yy790: yych = *(marker = ++c); switch (yych) { case 0x00: case '\n': - case '\r': goto yy783; - default: goto yy796; + case '\r': goto yy789; + default: goto yy802; } -yy785: +yy791: yych = *(marker = ++c); switch (yych) { case 0x00: case '\n': - case '\r': goto yy783; - default: goto yy794; + case '\r': goto yy789; + default: goto yy800; } -yy786: +yy792: yych = *(marker = ++c); switch (yych) { case 0x00: case '\n': - case '\r': goto yy783; - default: goto yy789; + case '\r': goto yy789; + default: goto yy795; } -yy787: +yy793: yych = *++c; - goto yy783; -yy788: + goto yy789; +yy794: ++c; yych = *c; -yy789: +yy795: switch (yych) { case 0x00: case '\n': - case '\r': goto yy790; - case ')': goto yy791; - default: goto yy788; + case '\r': goto yy796; + case ')': goto yy797; + default: goto yy794; } -yy790: +yy796: c = marker; - goto yy783; -yy791: + goto yy789; +yy797: ++c; { return (size_t)( c - start ); } -yy793: +yy799: ++c; yych = *c; -yy794: +yy800: switch (yych) { case 0x00: case '\n': - case '\r': goto yy790; - case '\'': goto yy791; - default: goto yy793; + case '\r': goto yy796; + case '\'': goto yy797; + default: goto yy799; } -yy795: +yy801: ++c; yych = *c; -yy796: +yy802: switch (yych) { case 0x00: case '\n': - case '\r': goto yy790; - case '"': goto yy791; - default: goto yy795; + case '\r': goto yy796; + case '"': goto yy797; + default: goto yy801; } } @@ -9803,106 +9835,106 @@ size_t scan_setext(const char * c) { char yych; yych = *c; switch (yych) { - case '\n': goto yy799; - case ' ': goto yy800; - case '-': goto yy802; - case '=': goto yy801; - default: goto yy803; + case '\n': goto yy805; + case ' ': goto yy806; + case '-': goto yy808; + case '=': goto yy807; + default: goto yy809; } -yy799: +yy805: { return 0; } -yy800: +yy806: yych = *(marker = ++c); switch (yych) { - case ' ': goto yy815; - case '-': goto yy816; - case '=': goto yy817; - default: goto yy799; + case ' ': goto yy821; + case '-': goto yy822; + case '=': goto yy823; + default: goto yy805; } -yy801: +yy807: yych = *(marker = ++c); switch (yych) { - case '=': goto yy810; - default: goto yy799; + case '=': goto yy816; + default: goto yy805; } -yy802: +yy808: yych = *(marker = ++c); switch (yych) { - case '-': goto yy804; - default: goto yy799; + case '-': goto yy810; + default: goto yy805; } -yy803: +yy809: yych = *++c; - goto yy799; -yy804: + goto yy805; +yy810: ++c; yych = *c; switch (yych) { case 0x00: - case '\n': goto yy807; - case '\r': goto yy809; - case '-': goto yy804; - default: goto yy806; + case '\n': goto yy813; + case '\r': goto yy815; + case '-': goto yy810; + default: goto yy812; } -yy806: +yy812: c = marker; - goto yy799; -yy807: + goto yy805; +yy813: ++c; -yy808: +yy814: { return (size_t)( c - start ); } -yy809: +yy815: yych = *++c; switch (yych) { - case '\n': goto yy807; - default: goto yy808; + case '\n': goto yy813; + default: goto yy814; } -yy810: +yy816: ++c; yych = *c; switch (yych) { case 0x00: - case '\n': goto yy812; - case '\r': goto yy814; - case '=': goto yy810; - default: goto yy806; + case '\n': goto yy818; + case '\r': goto yy820; + case '=': goto yy816; + default: goto yy812; } -yy812: +yy818: ++c; -yy813: +yy819: { return (size_t)( c - start ); } -yy814: +yy820: yych = *++c; switch (yych) { - case '\n': goto yy812; - default: goto yy813; + case '\n': goto yy818; + default: goto yy819; } -yy815: +yy821: yych = *++c; switch (yych) { - case ' ': goto yy818; - case '-': goto yy816; - case '=': goto yy817; - default: goto yy806; + case ' ': goto yy824; + case '-': goto yy822; + case '=': goto yy823; + default: goto yy812; } -yy816: +yy822: yych = *++c; switch (yych) { - case '-': goto yy804; - default: goto yy806; + case '-': goto yy810; + default: goto yy812; } -yy817: +yy823: yych = *++c; switch (yych) { - case '=': goto yy810; - default: goto yy806; + case '=': goto yy816; + default: goto yy812; } -yy818: +yy824: ++c; switch ((yych = *c)) { - case '-': goto yy816; - case '=': goto yy817; - default: goto yy806; + case '-': goto yy822; + case '=': goto yy823; + default: goto yy812; } } diff --git a/Sources/libMultiMarkdown/scanners.re b/Sources/libMultiMarkdown/scanners.re index ef4bcc35..22f47b60 100644 --- a/Sources/libMultiMarkdown/scanners.re +++ b/Sources/libMultiMarkdown/scanners.re @@ -86,7 +86,7 @@ attributes = (attr)+; title = (quoted_d | quoted_s | quoted_p); - label = [^\]\n\r\x00]+; + label = [^\]\n\r\x00]* [^\]\n\r\x00\\]; finish_line = [^\n\r\x00]+; ref_abbr = non_indent '[>' label ']' ':' finish_line; From 1510e3c935527e84eaa14e2aab8010bfac7ef094 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 13:51:21 -0400 Subject: [PATCH 05/29] FIXED: Update test code --- Sources/libMultiMarkdown/aho-corasick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/libMultiMarkdown/aho-corasick.c b/Sources/libMultiMarkdown/aho-corasick.c index ecd9ac4f..f94bd60c 100644 --- a/Sources/libMultiMarkdown/aho-corasick.c +++ b/Sources/libMultiMarkdown/aho-corasick.c @@ -515,7 +515,7 @@ void Test_aho_trie_search(CuTest* tc) { ac_trie_prepare(a); - match * m = ac_trie_search(a, "this is a bar that serves food.", 31); + match * m = ac_trie_search(a, "this is a bar that serves food.", 0, 31); match_free(m); trie_free(a); From c609cddaa4f3d71f96639e11b82037f16565acea Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 13:51:44 -0400 Subject: [PATCH 06/29] FIXED: Fix potential crash in attribute parsing --- Sources/libMultiMarkdown/writer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/libMultiMarkdown/writer.c b/Sources/libMultiMarkdown/writer.c index 853d355a..fc8e27b7 100644 --- a/Sources/libMultiMarkdown/writer.c +++ b/Sources/libMultiMarkdown/writer.c @@ -532,7 +532,7 @@ attr * parse_attributes(char * source) { size_t scan_len; size_t pos = 0; - while (scan_attr(&source[pos])) { + while (source[pos] != '\0' && scan_attr(&source[pos])) { pos += scan_spnl(&source[pos]); // Get key @@ -556,7 +556,7 @@ attr * parse_attributes(char * source) { attributes = a; } - free(value); // We stored a copy + free(value); // We stored a modified copy } return attributes; From 5cd846fe7540b30ceba1084d422294f2156f19a2 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 14:56:44 -0400 Subject: [PATCH 07/29] FIXED: Fix bug in Aho-Corasick implementation --- Sources/libMultiMarkdown/aho-corasick.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/libMultiMarkdown/aho-corasick.c b/Sources/libMultiMarkdown/aho-corasick.c index f94bd60c..60c057ee 100644 --- a/Sources/libMultiMarkdown/aho-corasick.c +++ b/Sources/libMultiMarkdown/aho-corasick.c @@ -373,13 +373,13 @@ match * ac_trie_search(trie * a, const char * source, size_t start, size_t len) size_t temp_state; // Character being compared - int test_value; + unsigned char test_value; size_t counter = start; size_t stop = start + len; while ((counter < stop) && (source[counter] != '\0')) { // Read next character - test_value = (int)source[counter++]; + test_value = (unsigned char)source[counter++]; // Check for path that allows us to match next character while (state != 0 && a->node[state].child[test_value] == 0) { From aa85f66b11ff94515f6118083b695ff653f69d0f Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 15:59:45 -0400 Subject: [PATCH 08/29] FIXED: Fix bug with Setext header starting with ':' --- Sources/libMultiMarkdown/mmd.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Sources/libMultiMarkdown/mmd.c b/Sources/libMultiMarkdown/mmd.c index 53325997..cc0150c4 100644 --- a/Sources/libMultiMarkdown/mmd.c +++ b/Sources/libMultiMarkdown/mmd.c @@ -1739,6 +1739,21 @@ void strip_line_tokens_from_block(mmd_engine * e, token * block) { // Advance to next line l = l->next; break; + case BLOCK_DEFINITION: + // Sometimes these get created unintentionally inside other blocks + // Process inside it, then treat it like a line to be stripped + + // Change to plain line + l->child->type = LINE_PLAIN; + strip_line_tokens_from_block(e, l); + + // Move children to parent + token_append_child(block, l->child); + l->child = NULL; + if (children == NULL) + children = l; + l = l->next; + break; case LINE_TABLE_SEPARATOR: case LINE_TABLE: if (block->type == BLOCK_TABLE_HEADER) { @@ -1751,7 +1766,8 @@ void strip_line_tokens_from_block(mmd_engine * e, token * block) { goto handle_line; } default: - //fprintf(stderr, "Unspecified line type %d inside block type %d\n", l->type, block->type); + // token_describe(block, e->dstr->str); + // fprintf(stderr, "Unspecified line type %d inside block type %d\n", l->type, block->type); // This is a block, need to remove it from chain and // Add to parent temp = l->next; From 58546dd603a469019b7fabd37f4947ff6569968b Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 16:13:21 -0400 Subject: [PATCH 09/29] FIXED: Fix potential bug in storing items to hash --- Sources/libMultiMarkdown/writer.c | 104 ++++++++++++++++++------------ 1 file changed, 62 insertions(+), 42 deletions(-) diff --git a/Sources/libMultiMarkdown/writer.c b/Sources/libMultiMarkdown/writer.c index fc8e27b7..7aa4bff5 100644 --- a/Sources/libMultiMarkdown/writer.c +++ b/Sources/libMultiMarkdown/writer.c @@ -612,21 +612,25 @@ void store_link(scratch_pad * scratch, link * l) { link * temp_link; // Add link via `clean_text`? - HASH_FIND_STR(scratch->link_hash, l->clean_text, temp_link); - - if (!temp_link) { - // Only add if another link is not found with clean_text - temp_link = link_shallow_copy(l); - HASH_ADD_KEYPTR(hh, scratch->link_hash, l->clean_text, strlen(l->clean_text), temp_link); + if (l->clean_text && l->clean_text[0] != '\0') { + HASH_FIND_STR(scratch->link_hash, l->clean_text, temp_link); + + if (!temp_link) { + // Only add if another link is not found with clean_text + temp_link = link_shallow_copy(l); + HASH_ADD_KEYPTR(hh, scratch->link_hash, l->clean_text, strlen(l->clean_text), temp_link); + } } // Add link via `label_text`? - HASH_FIND_STR(scratch->link_hash, l->label_text, temp_link); + if (l->label_text && l->label_text[0] != '\0') { + HASH_FIND_STR(scratch->link_hash, l->label_text, temp_link); - if (!temp_link) { - // Only add if another link is not found with label_text - temp_link = link_shallow_copy(l); - HASH_ADD_KEYPTR(hh, scratch->link_hash, l->label_text, strlen(l->label_text), temp_link); + if (!temp_link) { + // Only add if another link is not found with label_text + temp_link = link_shallow_copy(l); + HASH_ADD_KEYPTR(hh, scratch->link_hash, l->label_text, strlen(l->label_text), temp_link); + } } } @@ -663,19 +667,23 @@ void store_footnote(scratch_pad * scratch, footnote * f) { fn_holder * temp_holder; // Store by `clean_text`? - HASH_FIND_STR(scratch->footnote_hash, f->clean_text, temp_holder); + if (f->clean_text && f->clean_text[0] != '\0') { + HASH_FIND_STR(scratch->footnote_hash, f->clean_text, temp_holder); - if (!temp_holder) { - temp_holder = fn_holder_new(f); - HASH_ADD_KEYPTR(hh, scratch->footnote_hash, f->clean_text, strlen(f->clean_text), temp_holder); + if (!temp_holder) { + temp_holder = fn_holder_new(f); + HASH_ADD_KEYPTR(hh, scratch->footnote_hash, f->clean_text, strlen(f->clean_text), temp_holder); + } } // Store by `label_text`? - HASH_FIND_STR(scratch->footnote_hash, f->label_text, temp_holder); + if (f->label_text && f->label_text[0] != '\0') { + HASH_FIND_STR(scratch->footnote_hash, f->label_text, temp_holder); - if (!temp_holder) { - temp_holder = fn_holder_new(f); - HASH_ADD_KEYPTR(hh, scratch->footnote_hash, f->label_text, strlen(f->label_text), temp_holder); + if (!temp_holder) { + temp_holder = fn_holder_new(f); + HASH_ADD_KEYPTR(hh, scratch->footnote_hash, f->label_text, strlen(f->label_text), temp_holder); + } } } @@ -684,19 +692,23 @@ void store_citation(scratch_pad * scratch, footnote * f) { fn_holder * temp_holder; // Store by `clean_text`? - HASH_FIND_STR(scratch->citation_hash, f->clean_text, temp_holder); + if (f->clean_text && f->clean_text[0] != '\0') { + HASH_FIND_STR(scratch->citation_hash, f->clean_text, temp_holder); - if (!temp_holder) { - temp_holder = fn_holder_new(f); - HASH_ADD_KEYPTR(hh, scratch->citation_hash, f->clean_text, strlen(f->clean_text), temp_holder); + if (!temp_holder) { + temp_holder = fn_holder_new(f); + HASH_ADD_KEYPTR(hh, scratch->citation_hash, f->clean_text, strlen(f->clean_text), temp_holder); + } } // Store by `label_text`? - HASH_FIND_STR(scratch->citation_hash, f->label_text, temp_holder); + if (f->label_text && f->label_text[0] != '\0') { + HASH_FIND_STR(scratch->citation_hash, f->label_text, temp_holder); - if (!temp_holder) { - temp_holder = fn_holder_new(f); - HASH_ADD_KEYPTR(hh, scratch->citation_hash, f->label_text, strlen(f->label_text), temp_holder); + if (!temp_holder) { + temp_holder = fn_holder_new(f); + HASH_ADD_KEYPTR(hh, scratch->citation_hash, f->label_text, strlen(f->label_text), temp_holder); + } } } @@ -705,19 +717,23 @@ void store_glossary(scratch_pad * scratch, footnote * f) { fn_holder * temp_holder; // Store by `clean_text`? - HASH_FIND_STR(scratch->glossary_hash, f->clean_text, temp_holder); + if (f->clean_text && f->clean_text[0] != '\0') { + HASH_FIND_STR(scratch->glossary_hash, f->clean_text, temp_holder); - if (!temp_holder) { - temp_holder = fn_holder_new(f); - HASH_ADD_KEYPTR(hh, scratch->glossary_hash, f->clean_text, strlen(f->clean_text), temp_holder); + if (!temp_holder) { + temp_holder = fn_holder_new(f); + HASH_ADD_KEYPTR(hh, scratch->glossary_hash, f->clean_text, strlen(f->clean_text), temp_holder); + } } // Store by `label_text`? - HASH_FIND_STR(scratch->glossary_hash, f->label_text, temp_holder); + if (f->label_text && f->label_text[0] != '\0') { + HASH_FIND_STR(scratch->glossary_hash, f->label_text, temp_holder); - if (!temp_holder) { - temp_holder = fn_holder_new(f); - HASH_ADD_KEYPTR(hh, scratch->glossary_hash, f->label_text, strlen(f->label_text), temp_holder); + if (!temp_holder) { + temp_holder = fn_holder_new(f); + HASH_ADD_KEYPTR(hh, scratch->glossary_hash, f->label_text, strlen(f->label_text), temp_holder); + } } } @@ -726,10 +742,12 @@ void store_metadata(scratch_pad * scratch, meta * m) { meta * temp; // Store by `key` - HASH_FIND_STR(scratch->meta_hash, m->key, temp); + if (m->key && m->key[0] != '\0') { + HASH_FIND_STR(scratch->meta_hash, m->key, temp); - if (!temp) { - HASH_ADD_KEYPTR(hh, scratch->meta_hash, m->key, strlen(m->key), m); + if (!temp) { + HASH_ADD_KEYPTR(hh, scratch->meta_hash, m->key, strlen(m->key), m); + } } } @@ -738,11 +756,13 @@ void store_abbreviation(scratch_pad * scratch, footnote * f) { fn_holder * temp_holder; // Store by `label_text` - HASH_FIND_STR(scratch->abbreviation_hash, f->label_text, temp_holder); + if (f->label_text && f->label_text[0] != '\0') { + HASH_FIND_STR(scratch->abbreviation_hash, f->label_text, temp_holder); - if (!temp_holder) { - temp_holder = fn_holder_new(f); - HASH_ADD_KEYPTR(hh, scratch->abbreviation_hash, f->label_text, strlen(f->label_text), temp_holder); + if (!temp_holder) { + temp_holder = fn_holder_new(f); + HASH_ADD_KEYPTR(hh, scratch->abbreviation_hash, f->label_text, strlen(f->label_text), temp_holder); + } } } From 079c928ffc4fd86999f82363a3612e7a5d4dd6e8 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 16:23:35 -0400 Subject: [PATCH 10/29] FIXED: Fix signedness bug in Aho-Corasick --- Sources/libMultiMarkdown/aho-corasick.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/libMultiMarkdown/aho-corasick.c b/Sources/libMultiMarkdown/aho-corasick.c index 60c057ee..9633e76d 100644 --- a/Sources/libMultiMarkdown/aho-corasick.c +++ b/Sources/libMultiMarkdown/aho-corasick.c @@ -195,13 +195,13 @@ size_t trie_node_search(trie * a, size_t s, const char * query) { return s; } - if (a->node[s].child[(int)query[0]] == 0) { + if (a->node[s].child[(unsigned char)query[0]] == 0) { // Failed to match return -1; } // Partial match, keep going - return trie_node_search(a, a->node[s].child[(int)query[0]], query + 1); + return trie_node_search(a, a->node[s].child[(unsigned char)query[0]], query + 1); } From 119313e6d7ae24980a9e141a464052e8b8a14c2d Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 17:43:03 -0400 Subject: [PATCH 11/29] FIXED: Fix edge case with URL definitions --- Sources/libMultiMarkdown/writer.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Sources/libMultiMarkdown/writer.c b/Sources/libMultiMarkdown/writer.c index 7aa4bff5..69261b3b 100644 --- a/Sources/libMultiMarkdown/writer.c +++ b/Sources/libMultiMarkdown/writer.c @@ -851,12 +851,15 @@ char * destination_accept(const char * source, token ** remainder, bool validate // Grab destination string url = my_strndup(&source[start], scan_len); - // Advance remainder - while ((*remainder)->start < start + scan_len) + // Advance remainder to end of destination + while ((*remainder)->next && + (*remainder)->next->start < start + scan_len) { *remainder = (*remainder)->next; + } - - t = (*remainder)->prev; + t = (*remainder); // We need to remember this for below + // Move remainder beyond destination + *remainder = (*remainder)->next; // Is there a space in a URL concatenated with a title or attribute? // e.g. [foo]: http://foo.bar/ class="foo" From 05c22a23a47fb0153e787c53fb8c04068f6929a0 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 17:43:17 -0400 Subject: [PATCH 12/29] FIXED: Keep ':' in false positive definitions --- Sources/libMultiMarkdown/mmd.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Sources/libMultiMarkdown/mmd.c b/Sources/libMultiMarkdown/mmd.c index cc0150c4..35a61845 100644 --- a/Sources/libMultiMarkdown/mmd.c +++ b/Sources/libMultiMarkdown/mmd.c @@ -1748,6 +1748,11 @@ void strip_line_tokens_from_block(mmd_engine * e, token * block) { strip_line_tokens_from_block(e, l); // Move children to parent + // Add ':' back + if (e->dstr->str[l->child->start - 1] == ':') { + temp = token_new(COLON, l->child->start - 1, 1); + token_append_child(block, temp); + } token_append_child(block, l->child); l->child = NULL; if (children == NULL) From eba3d44cd607bc414b0563e90af1b4a92b0dbe86 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 17:43:43 -0400 Subject: [PATCH 13/29] CHANGED: Update Definition List test suite --- tests/MMD6Tests/Definition Lists.fodt | 3 +++ tests/MMD6Tests/Definition Lists.html | 3 +++ tests/MMD6Tests/Definition Lists.htmlc | 2 ++ tests/MMD6Tests/Definition Lists.tex | 3 +++ tests/MMD6Tests/Definition Lists.text | 1 + 5 files changed, 12 insertions(+) diff --git a/tests/MMD6Tests/Definition Lists.fodt b/tests/MMD6Tests/Definition Lists.fodt index 9e439dbd..60d786e7 100644 --- a/tests/MMD6Tests/Definition Lists.fodt +++ b/tests/MMD6Tests/Definition Lists.fodt @@ -299,6 +299,9 @@ bar foo baz* bat foo + +:foo + diff --git a/tests/MMD6Tests/Definition Lists.html b/tests/MMD6Tests/Definition Lists.html index 76ea0bc0..4419ca23 100644 --- a/tests/MMD6Tests/Definition Lists.html +++ b/tests/MMD6Tests/Definition Lists.html @@ -32,6 +32,9 @@

foo

+

:foo +

+ diff --git a/tests/MMD6Tests/Definition Lists.htmlc b/tests/MMD6Tests/Definition Lists.htmlc index 24e00b83..65bb395a 100644 --- a/tests/MMD6Tests/Definition Lists.htmlc +++ b/tests/MMD6Tests/Definition Lists.htmlc @@ -21,3 +21,5 @@ bar foo : baz bat

foo

+ +

:foo

diff --git a/tests/MMD6Tests/Definition Lists.tex b/tests/MMD6Tests/Definition Lists.tex index 12256ed3..8e663e9c 100644 --- a/tests/MMD6Tests/Definition Lists.tex +++ b/tests/MMD6Tests/Definition Lists.tex @@ -34,5 +34,8 @@ foo +:foo + + \input{mmd6-article-footer} \end{document} diff --git a/tests/MMD6Tests/Definition Lists.text b/tests/MMD6Tests/Definition Lists.text index 7f46a57c..7a012065 100644 --- a/tests/MMD6Tests/Definition Lists.text +++ b/tests/MMD6Tests/Definition Lists.text @@ -22,3 +22,4 @@ foo foo +:foo From 6eda50d349c501fc3bf92578b6be99cb8314f5f0 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 18:44:41 -0400 Subject: [PATCH 14/29] FIXED: Fix NULL pointer dereference --- Sources/libMultiMarkdown/writer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/libMultiMarkdown/writer.c b/Sources/libMultiMarkdown/writer.c index 69261b3b..997d578f 100644 --- a/Sources/libMultiMarkdown/writer.c +++ b/Sources/libMultiMarkdown/writer.c @@ -1349,7 +1349,7 @@ token * manual_label_from_header(token * h, const char * source) { break; case PAIR_BRACKET: label = walker; - while(walker->type == PAIR_BRACKET) { + while(walker && walker->type == PAIR_BRACKET) { walker = walker->prev; count++; } From eafc70407b8dacfa77062bbb90a8bdcbc5cba012 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 18:44:54 -0400 Subject: [PATCH 15/29] FIXED: Fix edge case with superscripts --- Sources/libMultiMarkdown/mmd.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Sources/libMultiMarkdown/mmd.c b/Sources/libMultiMarkdown/mmd.c index 35a61845..295dd581 100644 --- a/Sources/libMultiMarkdown/mmd.c +++ b/Sources/libMultiMarkdown/mmd.c @@ -1316,12 +1316,17 @@ void mmd_assign_ambidextrous_tokens_in_block(mmd_engine * e, token * block, cons t->can_close = 0; // Shift next token right and move those characters as child node - if ((t->next != NULL) && ((t->next->type == TEXT_PLAIN) || (t->next->type == TEXT_NUMBER_POSS_LIST))) { - t->next->start += t->len - 1; - t->next->len -= t->len - 1; + // It's possible that one (or more?) tokens are entirely subsumed. + while (t->next && t->next->start + t->next->len < offset) { + tokens_prune(t->next, t->next); + } - t->child = token_new(TEXT_PLAIN, t->start + 1, t->len - 1); + if ((t->next != NULL) && ((t->next->type == TEXT_PLAIN) || (t->next->type == TEXT_NUMBER_POSS_LIST))) { + t->next->len = t->next->start + t->next->len - offset; + t->next->start = offset; } + + t->child = token_new(TEXT_PLAIN, t->start + 1, t->len - 1); } } From 98270238538516eddf3a36c113556d5a752b88b1 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 18:52:02 -0400 Subject: [PATCH 16/29] FIXED: Fix crash with empty definition --- Sources/libMultiMarkdown/writer.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Sources/libMultiMarkdown/writer.c b/Sources/libMultiMarkdown/writer.c index 997d578f..895a4f42 100644 --- a/Sources/libMultiMarkdown/writer.c +++ b/Sources/libMultiMarkdown/writer.c @@ -1273,8 +1273,11 @@ void process_definition_block(mmd_engine * e, token * block) { // Adjust the properties free(f->label_text); f->label_text = f->clean_text; - f->clean_text = clean_string_from_range(e->dstr->str, f->content->child->next->next->start, block->start + block->len - f->content->child->next->next->start, false); - + if (f->content->child->next->next) { + f->clean_text = clean_string_from_range(e->dstr->str, f->content->child->next->next->start, block->start + block->len - f->content->child->next->next->start, false); + } else { + f->clean_text = NULL; + } stack_push(e->abbreviation_stack, f); break; case BLOCK_DEF_CITATION: From 439e322d5ace5eb431e3c6525486019a7823cd21 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 19:12:21 -0400 Subject: [PATCH 17/29] FIXED: Fix bug with ATX Headers without newline --- Sources/libMultiMarkdown/mmd.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Sources/libMultiMarkdown/mmd.c b/Sources/libMultiMarkdown/mmd.c index 295dd581..ee3026f4 100644 --- a/Sources/libMultiMarkdown/mmd.c +++ b/Sources/libMultiMarkdown/mmd.c @@ -813,8 +813,13 @@ token * mmd_tokenize_string(mmd_engine * e, const char * str, size_t len, bool s token_append_child(line, t); } } + } else if (type == 0 && stop > last_stop) { + // Source text ends without newline + t = token_new(TEXT_PLAIN, (size_t)(last_stop - str), (size_t)(stop - last_stop)); + token_append_child(line, t); } + switch (type) { case 0: // 0 means we finished with input From 955624d449cc4f46eb72d2594904c99873666d15 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 20:10:55 -0400 Subject: [PATCH 18/29] FIXED: Limit lines treated as ATX headers --- Sources/libMultiMarkdown/mmd.c | 34 +++++++++------- Sources/libMultiMarkdown/scanners.c | 58 +++++++++++++++++++++++++++- Sources/libMultiMarkdown/scanners.h | 1 + Sources/libMultiMarkdown/scanners.re | 11 ++++++ 4 files changed, 88 insertions(+), 16 deletions(-) diff --git a/Sources/libMultiMarkdown/mmd.c b/Sources/libMultiMarkdown/mmd.c index ee3026f4..0046deb4 100644 --- a/Sources/libMultiMarkdown/mmd.c +++ b/Sources/libMultiMarkdown/mmd.c @@ -402,22 +402,26 @@ void mmd_assign_line_type(mmd_engine * e, token * line) { case HASH4: case HASH5: case HASH6: - line->type = (line->child->type - HASH1) + LINE_ATX_1; - line->child->type = (line->type - LINE_ATX_1) + MARKER_H1; - - // Strip trailing whitespace from '#' sequence - line->child->len = line->child->type - MARKER_H1 + 1; - - // Strip trailing '#' sequence if present - if (line->child->tail->type == TEXT_NL) { - if ((line->child->tail->prev->type >= HASH1) && - (line->child->tail->prev->type <= HASH6)) - line->child->tail->prev->type = TEXT_EMPTY; + if (scan_atx(&source[line->child->start])) { + line->type = (line->child->type - HASH1) + LINE_ATX_1; + line->child->type = (line->type - LINE_ATX_1) + MARKER_H1; + + // Strip trailing whitespace from '#' sequence + line->child->len = line->child->type - MARKER_H1 + 1; + + // Strip trailing '#' sequence if present + if (line->child->tail->type == TEXT_NL) { + if ((line->child->tail->prev->type >= HASH1) && + (line->child->tail->prev->type <= HASH6)) + line->child->tail->prev->type = TEXT_EMPTY; + } else { + token_describe(line->child->tail, NULL); + if ((line->child->tail->type >= HASH1) && + (line->child->tail->type <= HASH6)) + line->child->tail->type = TEXT_EMPTY; + } } else { - token_describe(line->child->tail, NULL); - if ((line->child->tail->type >= HASH1) && - (line->child->tail->type <= HASH6)) - line->child->tail->type = TEXT_EMPTY; + line->type = LINE_PLAIN; } break; case TEXT_NUMBER_POSS_LIST: diff --git a/Sources/libMultiMarkdown/scanners.c b/Sources/libMultiMarkdown/scanners.c index e2ac3d1c..fe334c8a 100644 --- a/Sources/libMultiMarkdown/scanners.c +++ b/Sources/libMultiMarkdown/scanners.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.14.3 on Tue Mar 14 12:15:24 2017 */ +/* Generated by re2c 0.14.3 on Tue Mar 14 20:07:08 2017 */ /** MultiMarkdown 6 -- Lightweight markup processor to produce HTML, LaTeX, and more. @@ -9940,6 +9940,62 @@ size_t scan_setext(const char * c) { } +size_t scan_atx(const char * c) { + const char * marker = NULL; + const char * start = c; + + +{ + char yych; + yych = *c; + switch (yych) { + case '\n': goto yy827; + case '#': goto yy828; + default: goto yy829; + } +yy827: + { return 0; } +yy828: + yych = *(marker = ++c); + switch (yych) { + case '\t': + case ' ': goto yy830; + case '#': goto yy833; + default: goto yy827; + } +yy829: + yych = *++c; + goto yy827; +yy830: + ++c; + yych = *c; + switch (yych) { + case 0x00: + case '\n': + case '\r': goto yy832; + case '\t': + case ' ': goto yy830; + default: goto yy835; + } +yy832: + c = marker; + goto yy827; +yy833: + ++c; + yych = *c; + switch (yych) { + case '\t': + case ' ': goto yy830; + case '#': goto yy833; + default: goto yy832; + } +yy835: + ++c; + { return (size_t)( c - start ); } +} + +} + #ifdef TEST void Test_scan_url(CuTest* tc) { diff --git a/Sources/libMultiMarkdown/scanners.h b/Sources/libMultiMarkdown/scanners.h index c0460854..cb6591c8 100644 --- a/Sources/libMultiMarkdown/scanners.h +++ b/Sources/libMultiMarkdown/scanners.h @@ -72,6 +72,7 @@ enum alignments { size_t scan_alignment_string(const char * c); size_t scan_attr(const char * c); size_t scan_attributes(const char * c); +size_t scan_atx(const char * c); size_t scan_definition(const char * c); size_t scan_destination(const char * c); size_t scan_email(const char * c); diff --git a/Sources/libMultiMarkdown/scanners.re b/Sources/libMultiMarkdown/scanners.re index 22f47b60..e891d56d 100644 --- a/Sources/libMultiMarkdown/scanners.re +++ b/Sources/libMultiMarkdown/scanners.re @@ -158,6 +158,7 @@ setext_2 = non_indent '-'{2,} nl_eof; + atx = '#'+ [ \t]+ [^ \t\n\r\x00]; */ @@ -460,6 +461,16 @@ size_t scan_setext(const char * c) { */ } +size_t scan_atx(const char * c) { + const char * marker = NULL; + const char * start = c; + +/*!re2c + atx { return (size_t)( c - start ); } + .? { return 0; } +*/ +} + #ifdef TEST void Test_scan_url(CuTest* tc) { From 0ea87af748f597e700b19ce2d989b8b051cce5c3 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 23:41:14 -0400 Subject: [PATCH 19/29] FIXED: Fix bug with leading spaces in abbreviation references --- Sources/libMultiMarkdown/writer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Sources/libMultiMarkdown/writer.c b/Sources/libMultiMarkdown/writer.c index 895a4f42..d547eb5d 100644 --- a/Sources/libMultiMarkdown/writer.c +++ b/Sources/libMultiMarkdown/writer.c @@ -1267,8 +1267,12 @@ void process_definition_block(mmd_engine * e, token * block) { case BLOCK_DEF_ABBREVIATION: // Strip leading '>'' from term f = footnote_new(e->dstr->str, label, block->child, false); - if (f && f->clean_text) + if (f && f->clean_text) { memmove(f->clean_text, &(f->clean_text)[1],strlen(f->clean_text)); + while (char_is_whitespace((f->clean_text)[0])) { + memmove(f->clean_text, &(f->clean_text)[1],strlen(f->clean_text)); + } + } // Adjust the properties free(f->label_text); From 11f1f0e137a67abdcc99893608ea15675e76ada8 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Tue, 14 Mar 2017 23:50:26 -0400 Subject: [PATCH 20/29] FIXED: Fix potential bug in Aho-Corasick search: --- Sources/libMultiMarkdown/aho-corasick.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Sources/libMultiMarkdown/aho-corasick.c b/Sources/libMultiMarkdown/aho-corasick.c index 9633e76d..fb3255f6 100644 --- a/Sources/libMultiMarkdown/aho-corasick.c +++ b/Sources/libMultiMarkdown/aho-corasick.c @@ -331,6 +331,7 @@ match * match_new(size_t start, size_t len, unsigned short match_type) { m->len = len; m->match_type = match_type; m->next = NULL; + m->prev = NULL; } return m; @@ -483,7 +484,8 @@ void match_set_filter_leftmost_longest(match * header) { } } - while (m->prev->len && + while (m->prev && + m->prev->len && m->prev->start >= m->start) { // We are "lefter" than previous n = m->prev; From 340352cb372bc94b1339aaa2f8d1aba10e2acc5e Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Wed, 15 Mar 2017 00:33:18 -0400 Subject: [PATCH 21/29] FIXED: Include non-breaking space (ASCII 160) in re2c patterns --- Sources/libMultiMarkdown/lexer.c | 768 ++++++++++++++------------- Sources/libMultiMarkdown/lexer.re | 16 +- Sources/libMultiMarkdown/scanners.c | 571 +++++++++++++------- Sources/libMultiMarkdown/scanners.re | 18 +- 4 files changed, 786 insertions(+), 587 deletions(-) diff --git a/Sources/libMultiMarkdown/lexer.c b/Sources/libMultiMarkdown/lexer.c index d2c41cc7..19520d1d 100644 --- a/Sources/libMultiMarkdown/lexer.c +++ b/Sources/libMultiMarkdown/lexer.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.14.3 on Tue Mar 14 10:21:05 2017 */ +/* Generated by re2c 0.14.3 on Wed Mar 15 00:32:21 2017 */ /** MultiMarkdown 6 -- Lightweight markup processor to produce HTML, LaTeX, and more. @@ -61,12 +61,11 @@ // Basic scanner struct -#define YYCTYPE char +#define YYCTYPE unsigned char #define YYCURSOR s->cur #define YYMARKER s->ptr #define YYCTXMARKER s->ctx - int scan(Scanner * s, const char * stop) { scan: @@ -85,19 +84,19 @@ int scan(Scanner * s, const char * stop) { yych = *YYCURSOR; switch (yych) { case '\t': goto yy45; - case '\n': goto yy53; - case '\r': goto yy55; + case '\n': goto yy54; + case '\r': goto yy56; case ' ': goto yy47; case '!': goto yy18; case '"': goto yy28; - case '#': goto yy48; + case '#': goto yy49; case '$': goto yy41; - case '%': goto yy50; + case '%': goto yy51; case '&': goto yy35; case '\'': goto yy30; case '(': goto yy20; case ')': goto yy22; - case '*': goto yy56; + case '*': goto yy57; case '+': goto yy4; case '-': goto yy6; case '.': goto yy32; @@ -111,7 +110,7 @@ int scan(Scanner * s, const char * stop) { case '6': case '7': case '8': - case '9': goto yy52; + case '9': goto yy53; case ':': goto yy33; case '<': goto yy8; case '=': goto yy12; @@ -120,24 +119,25 @@ int scan(Scanner * s, const char * stop) { case '\\': goto yy39; case ']': goto yy16; case '^': goto yy43; - case '_': goto yy58; - case '`': goto yy60; + case '_': goto yy59; + case '`': goto yy61; case '{': goto yy2; - case '|': goto yy62; + case '|': goto yy63; case '}': goto yy26; case '~': goto yy10; - default: goto yy64; + case 0xA0: goto yy48; + default: goto yy65; } yy2: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); switch (yych) { - case '+': goto yy266; - case '-': goto yy265; - case '=': goto yy262; - case '>': goto yy264; - case '{': goto yy260; - case '~': goto yy263; + case '+': goto yy267; + case '-': goto yy266; + case '=': goto yy263; + case '>': goto yy265; + case '{': goto yy261; + case '~': goto yy264; default: goto yy3; } yy3: @@ -146,7 +146,7 @@ int scan(Scanner * s, const char * stop) { yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); switch (yych) { - case '+': goto yy257; + case '+': goto yy258; default: goto yy5; } yy5: @@ -154,7 +154,7 @@ int scan(Scanner * s, const char * stop) { yy6: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '-': goto yy251; + case '-': goto yy252; default: goto yy7; } yy7: @@ -163,7 +163,7 @@ int scan(Scanner * s, const char * stop) { yyaccept = 2; yych = *(YYMARKER = ++YYCURSOR); switch (yych) { - case '<': goto yy248; + case '<': goto yy249; default: goto yy9; } yy9: @@ -172,8 +172,8 @@ int scan(Scanner * s, const char * stop) { yyaccept = 3; yych = *(YYMARKER = ++YYCURSOR); switch (yych) { - case '>': goto yy244; - case '~': goto yy243; + case '>': goto yy245; + case '~': goto yy244; default: goto yy11; } yy11: @@ -182,7 +182,7 @@ int scan(Scanner * s, const char * stop) { yyaccept = 4; yych = *(YYMARKER = ++YYCURSOR); switch (yych) { - case '=': goto yy240; + case '=': goto yy241; default: goto yy13; } yy13: @@ -190,11 +190,11 @@ int scan(Scanner * s, const char * stop) { yy14: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '#': goto yy236; - case '%': goto yy230; - case '>': goto yy238; - case '?': goto yy232; - case '^': goto yy234; + case '#': goto yy237; + case '%': goto yy231; + case '>': goto yy239; + case '?': goto yy233; + case '^': goto yy235; default: goto yy15; } yy15: @@ -205,7 +205,7 @@ int scan(Scanner * s, const char * stop) { yy18: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '[': goto yy228; + case '[': goto yy229; default: goto yy19; } yy19: @@ -222,7 +222,7 @@ int scan(Scanner * s, const char * stop) { yy26: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '}': goto yy226; + case '}': goto yy227; default: goto yy27; } yy27: @@ -233,7 +233,7 @@ int scan(Scanner * s, const char * stop) { yy30: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '\'': goto yy224; + case '\'': goto yy225; default: goto yy31; } yy31: @@ -242,8 +242,8 @@ int scan(Scanner * s, const char * stop) { yyaccept = 5; yych = *(YYMARKER = ++YYCURSOR); switch (yych) { - case ' ': goto yy216; - case '.': goto yy217; + case ' ': goto yy217; + case '.': goto yy218; default: goto yy19; } yy33: @@ -254,7 +254,7 @@ int scan(Scanner * s, const char * stop) { yych = *(YYMARKER = ++YYCURSOR); switch (yych) { case 'A': - case 'a': goto yy211; + case 'a': goto yy212; default: goto yy36; } yy36: @@ -265,41 +265,41 @@ int scan(Scanner * s, const char * stop) { yy39: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '\n': goto yy134; - case '\r': goto yy136; - case ' ': goto yy139; - case '!': goto yy199; - case '"': goto yy189; - case '#': goto yy169; - case '$': goto yy167; - case '%': goto yy165; - case '&': goto yy153; - case '\'': goto yy187; - case '(': goto yy181; - case ')': goto yy179; - case '*': goto yy145; - case '+': goto yy163; - case ',': goto yy195; - case '-': goto yy161; - case '.': goto yy201; - case '/': goto yy149; - case ':': goto yy191; - case ';': goto yy193; - case '<': goto yy157; - case '=': goto yy159; - case '>': goto yy155; - case '?': goto yy197; - case '@': goto yy151; - case '[': goto yy173; - case '\\': goto yy137; - case ']': goto yy171; - case '^': goto yy147; - case '_': goto yy143; - case '`': goto yy185; - case '{': goto yy177; - case '|': goto yy141; - case '}': goto yy175; - case '~': goto yy183; + case '\n': goto yy135; + case '\r': goto yy137; + case ' ': goto yy140; + case '!': goto yy200; + case '"': goto yy190; + case '#': goto yy170; + case '$': goto yy168; + case '%': goto yy166; + case '&': goto yy154; + case '\'': goto yy188; + case '(': goto yy182; + case ')': goto yy180; + case '*': goto yy146; + case '+': goto yy164; + case ',': goto yy196; + case '-': goto yy162; + case '.': goto yy202; + case '/': goto yy150; + case ':': goto yy192; + case ';': goto yy194; + case '<': goto yy158; + case '=': goto yy160; + case '>': goto yy156; + case '?': goto yy198; + case '@': goto yy152; + case '[': goto yy174; + case '\\': goto yy138; + case ']': goto yy172; + case '^': goto yy148; + case '_': goto yy144; + case '`': goto yy186; + case '{': goto yy178; + case '|': goto yy142; + case '}': goto yy176; + case '~': goto yy184; default: goto yy40; } yy40: @@ -307,7 +307,7 @@ int scan(Scanner * s, const char * stop) { yy41: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '$': goto yy132; + case '$': goto yy133; default: goto yy42; } yy42: @@ -322,13 +322,23 @@ int scan(Scanner * s, const char * stop) { YYCTXMARKER = YYCURSOR + 1; yych = *++YYCURSOR; switch (yych) { - case '\t': goto yy119; - case '\n': goto yy53; - case '\r': goto yy123; - case ' ': goto yy121; + case '\t': goto yy120; + case '\n': goto yy54; + case '\r': goto yy132; + case ' ': + case 0xA0: goto yy122; default: goto yy19; } yy48: + YYCTXMARKER = YYCURSOR + 1; + yych = *++YYCURSOR; + switch (yych) { + case '\t': goto yy120; + case ' ': + case 0xA0: goto yy122; + default: goto yy19; + } +yy49: YYCTXMARKER = YYCURSOR + 1; yyaccept = 7; yych = *(YYMARKER = ++YYCURSOR); @@ -336,20 +346,21 @@ int scan(Scanner * s, const char * stop) { case '\t': case '\n': case '\r': - case ' ': goto yy80; - case '#': goto yy78; - default: goto yy49; + case ' ': + case 0xA0: goto yy81; + case '#': goto yy79; + default: goto yy50; } -yy49: - { return TEXT_HASH; } yy50: + { return TEXT_HASH; } +yy51: ++YYCURSOR; { return TEXT_PERCENT; } -yy52: +yy53: yyaccept = 5; yych = *(YYMARKER = ++YYCURSOR); switch (yych) { - case '.': goto yy69; + case '.': goto yy70; case '0': case '1': case '2': @@ -359,67 +370,68 @@ int scan(Scanner * s, const char * stop) { case '6': case '7': case '8': - case '9': goto yy71; + case '9': goto yy72; default: goto yy19; } -yy53: - ++YYCURSOR; yy54: - { return TEXT_NL; } + ++YYCURSOR; yy55: + { return TEXT_NL; } +yy56: yych = *++YYCURSOR; switch (yych) { - case '\n': goto yy53; - default: goto yy54; + case '\n': goto yy54; + default: goto yy55; } -yy56: +yy57: ++YYCURSOR; { return STAR; } -yy58: +yy59: ++YYCURSOR; { return UL; } -yy60: +yy61: ++YYCURSOR; yych = *YYCURSOR; - goto yy68; -yy61: - { return BACKTICK; } + goto yy69; yy62: + { return BACKTICK; } +yy63: ++YYCURSOR; yych = *YYCURSOR; - goto yy66; -yy63: - { return PIPE; } + goto yy67; yy64: + { return PIPE; } +yy65: yych = *++YYCURSOR; goto yy19; -yy65: +yy66: ++YYCURSOR; yych = *YYCURSOR; -yy66: +yy67: switch (yych) { - case '|': goto yy65; - default: goto yy63; + case '|': goto yy66; + default: goto yy64; } -yy67: +yy68: ++YYCURSOR; yych = *YYCURSOR; -yy68: +yy69: switch (yych) { - case '`': goto yy67; - default: goto yy61; + case '`': goto yy68; + default: goto yy62; } -yy69: +yy70: YYCTXMARKER = YYCURSOR + 1; yych = *++YYCURSOR; switch (yych) { case '\t': - case ' ': goto yy76; - case '\n': goto yy73; - case '\r': goto yy75; - default: goto yy70; + case ' ': + case 0xA0: goto yy77; + case '\n': goto yy74; + case '\r': goto yy76; + default: goto yy71; } -yy70: +yy71: YYCURSOR = YYMARKER; switch (yyaccept) { case 0: goto yy3; @@ -429,15 +441,15 @@ int scan(Scanner * s, const char * stop) { case 4: goto yy13; case 5: goto yy19; case 6: goto yy36; - case 7: goto yy49; + case 7: goto yy50; case 8: goto yy129; - default: goto yy261; + default: goto yy262; } -yy71: +yy72: ++YYCURSOR; yych = *YYCURSOR; switch (yych) { - case '.': goto yy69; + case '.': goto yy70; case '0': case '1': case '2': @@ -447,253 +459,261 @@ int scan(Scanner * s, const char * stop) { case '6': case '7': case '8': - case '9': goto yy71; - default: goto yy70; + case '9': goto yy72; + default: goto yy71; } -yy73: - ++YYCURSOR; yy74: + ++YYCURSOR; +yy75: YYCURSOR = YYCTXMARKER; { return TEXT_NUMBER_POSS_LIST; } -yy75: +yy76: yych = *++YYCURSOR; switch (yych) { - case '\n': goto yy73; - default: goto yy74; + case '\n': goto yy74; + default: goto yy75; } -yy76: +yy77: ++YYCURSOR; yych = *YYCURSOR; switch (yych) { case '\t': - case ' ': goto yy76; - default: goto yy74; + case ' ': + case 0xA0: goto yy77; + default: goto yy75; } -yy78: +yy79: YYCTXMARKER = YYCURSOR + 1; yych = *++YYCURSOR; switch (yych) { case '\t': case '\n': case '\r': - case ' ': goto yy86; - case '#': goto yy91; - default: goto yy70; + case ' ': + case 0xA0: goto yy87; + case '#': goto yy92; + default: goto yy71; } -yy79: +yy80: ++YYCURSOR; yych = *YYCURSOR; -yy80: +yy81: switch (yych) { case '\t': - case ' ': goto yy79; - case '\n': goto yy82; - case '\r': goto yy84; - default: goto yy81; + case ' ': + case 0xA0: goto yy80; + case '\n': goto yy83; + case '\r': goto yy85; + default: goto yy82; } -yy81: - { return HASH1; } yy82: - ++YYCURSOR; + { return HASH1; } yy83: + ++YYCURSOR; +yy84: YYCURSOR = YYCTXMARKER; { return HASH1; } -yy84: +yy85: yych = *++YYCURSOR; switch (yych) { - case '\n': goto yy82; - default: goto yy83; + case '\n': goto yy83; + default: goto yy84; } -yy85: +yy86: ++YYCURSOR; yych = *YYCURSOR; -yy86: +yy87: switch (yych) { case '\t': - case ' ': goto yy85; - case '\n': goto yy88; - case '\r': goto yy90; - default: goto yy87; + case ' ': + case 0xA0: goto yy86; + case '\n': goto yy89; + case '\r': goto yy91; + default: goto yy88; } -yy87: - { return HASH2; } yy88: - ++YYCURSOR; + { return HASH2; } yy89: + ++YYCURSOR; +yy90: YYCURSOR = YYCTXMARKER; { return HASH2; } -yy90: +yy91: yych = *++YYCURSOR; switch (yych) { - case '\n': goto yy88; - default: goto yy89; + case '\n': goto yy89; + default: goto yy90; } -yy91: +yy92: YYCTXMARKER = YYCURSOR + 1; yych = *++YYCURSOR; switch (yych) { case '\t': case '\n': case '\r': - case ' ': goto yy94; - case '#': goto yy92; - default: goto yy70; + case ' ': + case 0xA0: goto yy95; + case '#': goto yy93; + default: goto yy71; } -yy92: +yy93: YYCTXMARKER = YYCURSOR + 1; yych = *++YYCURSOR; switch (yych) { case '\t': case '\n': case '\r': - case ' ': goto yy100; - case '#': goto yy105; - default: goto yy70; + case ' ': + case 0xA0: goto yy101; + case '#': goto yy106; + default: goto yy71; } -yy93: +yy94: ++YYCURSOR; yych = *YYCURSOR; -yy94: +yy95: switch (yych) { case '\t': - case ' ': goto yy93; - case '\n': goto yy96; - case '\r': goto yy98; - default: goto yy95; + case ' ': + case 0xA0: goto yy94; + case '\n': goto yy97; + case '\r': goto yy99; + default: goto yy96; } -yy95: - { return HASH3; } yy96: - ++YYCURSOR; + { return HASH3; } yy97: + ++YYCURSOR; +yy98: YYCURSOR = YYCTXMARKER; { return HASH3; } -yy98: +yy99: yych = *++YYCURSOR; switch (yych) { - case '\n': goto yy96; - default: goto yy97; + case '\n': goto yy97; + default: goto yy98; } -yy99: +yy100: ++YYCURSOR; yych = *YYCURSOR; -yy100: +yy101: switch (yych) { case '\t': - case ' ': goto yy99; - case '\n': goto yy102; - case '\r': goto yy104; - default: goto yy101; + case ' ': + case 0xA0: goto yy100; + case '\n': goto yy103; + case '\r': goto yy105; + default: goto yy102; } -yy101: - { return HASH4; } yy102: - ++YYCURSOR; + { return HASH4; } yy103: + ++YYCURSOR; +yy104: YYCURSOR = YYCTXMARKER; { return HASH4; } -yy104: +yy105: yych = *++YYCURSOR; switch (yych) { - case '\n': goto yy102; - default: goto yy103; + case '\n': goto yy103; + default: goto yy104; } -yy105: +yy106: YYCTXMARKER = YYCURSOR + 1; yych = *++YYCURSOR; switch (yych) { case '\t': case '\n': case '\r': - case ' ': goto yy108; - case '#': goto yy106; - default: goto yy70; + case ' ': + case 0xA0: goto yy109; + case '#': goto yy107; + default: goto yy71; } -yy106: +yy107: YYCTXMARKER = YYCURSOR + 1; yych = *++YYCURSOR; switch (yych) { case '\t': case '\n': case '\r': - case ' ': goto yy114; - default: goto yy70; + case ' ': + case 0xA0: goto yy115; + default: goto yy71; } -yy107: +yy108: ++YYCURSOR; yych = *YYCURSOR; -yy108: +yy109: switch (yych) { case '\t': - case ' ': goto yy107; - case '\n': goto yy110; - case '\r': goto yy112; - default: goto yy109; + case ' ': + case 0xA0: goto yy108; + case '\n': goto yy111; + case '\r': goto yy113; + default: goto yy110; } -yy109: - { return HASH5; } yy110: - ++YYCURSOR; + { return HASH5; } yy111: + ++YYCURSOR; +yy112: YYCURSOR = YYCTXMARKER; { return HASH5; } -yy112: +yy113: yych = *++YYCURSOR; switch (yych) { - case '\n': goto yy110; - default: goto yy111; + case '\n': goto yy111; + default: goto yy112; } -yy113: +yy114: ++YYCURSOR; yych = *YYCURSOR; -yy114: +yy115: switch (yych) { case '\t': - case ' ': goto yy113; - case '\n': goto yy116; - case '\r': goto yy118; - default: goto yy115; + case ' ': + case 0xA0: goto yy114; + case '\n': goto yy117; + case '\r': goto yy119; + default: goto yy116; } -yy115: - { return HASH6; } yy116: - ++YYCURSOR; + { return HASH6; } yy117: + ++YYCURSOR; +yy118: YYCURSOR = YYCTXMARKER; { return HASH6; } -yy118: +yy119: yych = *++YYCURSOR; switch (yych) { - case '\n': goto yy116; - default: goto yy117; + case '\n': goto yy117; + default: goto yy118; } -yy119: +yy120: ++YYCURSOR; YYCURSOR = YYCTXMARKER; { return NON_INDENT_SPACE; } -yy121: +yy122: ++YYCURSOR; switch ((yych = *YYCURSOR)) { case '\n': goto yy125; case '\r': goto yy127; - case ' ': goto yy124; - default: goto yy122; + case ' ': + case 0xA0: goto yy124; + default: goto yy123; } -yy122: - { return NON_INDENT_SPACE; } yy123: - yych = *++YYCURSOR; - switch (yych) { - case '\n': goto yy53; - default: goto yy54; - } + { return NON_INDENT_SPACE; } yy124: yych = *++YYCURSOR; switch (yych) { case '\n': goto yy125; case '\r': goto yy127; - case ' ': goto yy128; - default: goto yy122; + case ' ': + case 0xA0: goto yy128; + default: goto yy123; } yy125: ++YYCURSOR; @@ -711,7 +731,8 @@ int scan(Scanner * s, const char * stop) { switch (yych) { case '\n': goto yy125; case '\r': goto yy127; - case ' ': goto yy130; + case ' ': + case 0xA0: goto yy130; default: goto yy129; } yy129: @@ -722,351 +743,358 @@ int scan(Scanner * s, const char * stop) { switch (yych) { case '\n': goto yy125; case '\r': goto yy127; - case ' ': goto yy130; - default: goto yy70; + case ' ': + case 0xA0: goto yy130; + default: goto yy71; } yy132: + yych = *++YYCURSOR; + switch (yych) { + case '\n': goto yy54; + default: goto yy55; + } +yy133: ++YYCURSOR; { return MATH_DOLLAR_DOUBLE; } -yy134: - ++YYCURSOR; yy135: - { return TEXT_LINEBREAK; } + ++YYCURSOR; yy136: + { return TEXT_LINEBREAK; } +yy137: yych = *++YYCURSOR; switch (yych) { - case '\n': goto yy134; - default: goto yy135; + case '\n': goto yy135; + default: goto yy136; } -yy137: +yy138: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '(': goto yy203; - case ')': goto yy205; - case '[': goto yy207; - case ']': goto yy209; - default: goto yy138; + case '(': goto yy204; + case ')': goto yy206; + case '[': goto yy208; + case ']': goto yy210; + default: goto yy139; } -yy138: - { return ESCAPED_CHARACTER; } yy139: + { return ESCAPED_CHARACTER; } +yy140: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy141: +yy142: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy143: +yy144: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy145: +yy146: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy147: +yy148: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy149: +yy150: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy151: +yy152: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy153: +yy154: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy155: +yy156: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy157: +yy158: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy159: +yy160: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy161: +yy162: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy163: +yy164: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy165: +yy166: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy167: +yy168: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy169: +yy170: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy171: +yy172: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy173: +yy174: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy175: +yy176: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy177: +yy178: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy179: +yy180: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy181: +yy182: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy183: +yy184: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy185: +yy186: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy187: +yy188: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy189: +yy190: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy191: +yy192: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy193: +yy194: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy195: +yy196: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy197: +yy198: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy199: +yy200: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy201: +yy202: ++YYCURSOR; { return ESCAPED_CHARACTER; } -yy203: +yy204: ++YYCURSOR; { return MATH_PAREN_OPEN; } -yy205: +yy206: ++YYCURSOR; { return MATH_PAREN_CLOSE; } -yy207: +yy208: ++YYCURSOR; { return MATH_BRACKET_OPEN; } -yy209: +yy210: ++YYCURSOR; { return MATH_BRACKET_CLOSE; } -yy211: +yy212: yych = *++YYCURSOR; switch (yych) { case 'M': - case 'm': goto yy212; - default: goto yy70; + case 'm': goto yy213; + default: goto yy71; } -yy212: +yy213: yych = *++YYCURSOR; switch (yych) { case 'P': - case 'p': goto yy213; - default: goto yy70; + case 'p': goto yy214; + default: goto yy71; } -yy213: +yy214: yych = *++YYCURSOR; switch (yych) { - case ';': goto yy214; - default: goto yy70; + case ';': goto yy215; + default: goto yy71; } -yy214: +yy215: ++YYCURSOR; { return AMPERSAND_LONG; } -yy216: +yy217: yych = *++YYCURSOR; switch (yych) { - case '.': goto yy220; - default: goto yy70; + case '.': goto yy221; + default: goto yy71; } -yy217: +yy218: yych = *++YYCURSOR; switch (yych) { - case '.': goto yy218; - default: goto yy70; + case '.': goto yy219; + default: goto yy71; } -yy218: +yy219: ++YYCURSOR; { return ELLIPSIS; } -yy220: +yy221: yych = *++YYCURSOR; switch (yych) { - case ' ': goto yy221; - default: goto yy70; + case ' ': goto yy222; + default: goto yy71; } -yy221: +yy222: yych = *++YYCURSOR; switch (yych) { - case '.': goto yy222; - default: goto yy70; + case '.': goto yy223; + default: goto yy71; } -yy222: +yy223: ++YYCURSOR; { return ELLIPSIS; } -yy224: +yy225: ++YYCURSOR; { return QUOTE_RIGHT_ALT; } -yy226: +yy227: ++YYCURSOR; { return BRACE_DOUBLE_RIGHT; } -yy228: +yy229: ++YYCURSOR; { return BRACKET_IMAGE_LEFT; } -yy230: +yy231: ++YYCURSOR; { return BRACKET_VARIABLE_LEFT; } -yy232: +yy233: ++YYCURSOR; { return BRACKET_GLOSSARY_LEFT; } -yy234: +yy235: ++YYCURSOR; { return BRACKET_FOOTNOTE_LEFT; } -yy236: +yy237: ++YYCURSOR; { return BRACKET_CITATION_LEFT; } -yy238: +yy239: ++YYCURSOR; { return BRACKET_ABBREVIATION_LEFT; } -yy240: +yy241: yych = *++YYCURSOR; switch (yych) { - case '}': goto yy241; - default: goto yy70; + case '}': goto yy242; + default: goto yy71; } -yy241: +yy242: ++YYCURSOR; { return CRITIC_HI_CLOSE; } -yy243: +yy244: yych = *++YYCURSOR; switch (yych) { - case '}': goto yy246; - default: goto yy70; + case '}': goto yy247; + default: goto yy71; } -yy244: +yy245: ++YYCURSOR; { return CRITIC_SUB_DIV; } -yy246: +yy247: ++YYCURSOR; { return CRITIC_SUB_CLOSE; } -yy248: +yy249: yych = *++YYCURSOR; switch (yych) { - case '}': goto yy249; - default: goto yy70; + case '}': goto yy250; + default: goto yy71; } -yy249: +yy250: ++YYCURSOR; { return CRITIC_COM_CLOSE; } -yy251: +yy252: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '-': goto yy255; - case '}': goto yy253; - default: goto yy252; + case '-': goto yy256; + case '}': goto yy254; + default: goto yy253; } -yy252: - { return DASH_N; } yy253: + { return DASH_N; } +yy254: ++YYCURSOR; { return CRITIC_DEL_CLOSE; } -yy255: +yy256: ++YYCURSOR; { return DASH_M; } -yy257: +yy258: yych = *++YYCURSOR; switch (yych) { - case '}': goto yy258; - default: goto yy70; + case '}': goto yy259; + default: goto yy71; } -yy258: +yy259: ++YYCURSOR; { return CRITIC_ADD_CLOSE; } -yy260: +yy261: yyaccept = 9; yych = *(YYMARKER = ++YYCURSOR); switch (yych) { - case 'T': goto yy277; - default: goto yy261; + case 'T': goto yy278; + default: goto yy262; } -yy261: - { return BRACE_DOUBLE_LEFT; } yy262: - yych = *++YYCURSOR; - switch (yych) { - case '=': goto yy275; - default: goto yy70; - } + { return BRACE_DOUBLE_LEFT; } yy263: yych = *++YYCURSOR; switch (yych) { - case '~': goto yy273; - default: goto yy70; + case '=': goto yy276; + default: goto yy71; } yy264: yych = *++YYCURSOR; switch (yych) { - case '>': goto yy271; - default: goto yy70; + case '~': goto yy274; + default: goto yy71; } yy265: yych = *++YYCURSOR; switch (yych) { - case '-': goto yy269; - default: goto yy70; + case '>': goto yy272; + default: goto yy71; } yy266: yych = *++YYCURSOR; switch (yych) { - case '+': goto yy267; - default: goto yy70; + case '-': goto yy270; + default: goto yy71; } yy267: + yych = *++YYCURSOR; + switch (yych) { + case '+': goto yy268; + default: goto yy71; + } +yy268: ++YYCURSOR; { return CRITIC_ADD_OPEN; } -yy269: +yy270: ++YYCURSOR; { return CRITIC_DEL_OPEN; } -yy271: +yy272: ++YYCURSOR; { return CRITIC_COM_OPEN; } -yy273: +yy274: ++YYCURSOR; { return CRITIC_SUB_OPEN; } -yy275: +yy276: ++YYCURSOR; { return CRITIC_HI_OPEN; } -yy277: - yych = *++YYCURSOR; - switch (yych) { - case 'O': goto yy278; - default: goto yy70; - } yy278: yych = *++YYCURSOR; switch (yych) { - case 'C': goto yy279; - default: goto yy70; + case 'O': goto yy279; + default: goto yy71; } yy279: yych = *++YYCURSOR; switch (yych) { - case '}': goto yy280; - default: goto yy70; + case 'C': goto yy280; + default: goto yy71; } yy280: yych = *++YYCURSOR; switch (yych) { case '}': goto yy281; - default: goto yy70; + default: goto yy71; } yy281: + yych = *++YYCURSOR; + switch (yych) { + case '}': goto yy282; + default: goto yy71; + } +yy282: ++YYCURSOR; { return TOC; } } diff --git a/Sources/libMultiMarkdown/lexer.re b/Sources/libMultiMarkdown/lexer.re index cba2e0a9..998169f9 100644 --- a/Sources/libMultiMarkdown/lexer.re +++ b/Sources/libMultiMarkdown/lexer.re @@ -60,12 +60,11 @@ // Basic scanner struct -#define YYCTYPE char +#define YYCTYPE unsigned char #define YYCURSOR s->cur #define YYMARKER s->ptr #define YYCTXMARKER s->ctx - int scan(Scanner * s, const char * stop) { scan: @@ -80,15 +79,16 @@ int scan(Scanner * s, const char * stop) { re2c:yyfill:enable = 0; NL = "\r\n" | '\n' | '\r'; - SP = [ \t]+; + WS = [ \t\240]; // Whitespace from char_lookup.c + SP = WS+; - SPNL = [ \t]* NL; + SPNL = WS* NL; INDENT_TAB = '\t'; - INDENT_SPACE = ' '{4}; - NON_INDENT_SPACE = ' '{2,3}; + INDENT_SPACE = [ \240]{4}; + NON_INDENT_SPACE = [ \240]{2,3}; - TEXT_LINEBREAK = ' '{2,} NL; + TEXT_LINEBREAK = [ \240]{2,} NL; // The order of these seems to matter @@ -226,7 +226,7 @@ int scan(Scanner * s, const char * stop) { ' '? NL { return TEXT_NL; } NON_INDENT_SPACE { return NON_INDENT_SPACE; } - ' ' / '\t' { return NON_INDENT_SPACE; } + [ \240] / '\t' { return NON_INDENT_SPACE; } "*" { return STAR; } "+" { return PLUS; } diff --git a/Sources/libMultiMarkdown/scanners.c b/Sources/libMultiMarkdown/scanners.c index fe334c8a..2d46d5ad 100644 --- a/Sources/libMultiMarkdown/scanners.c +++ b/Sources/libMultiMarkdown/scanners.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.14.3 on Tue Mar 14 20:07:08 2017 */ +/* Generated by re2c 0.14.3 on Wed Mar 15 00:32:22 2017 */ /** MultiMarkdown 6 -- Lightweight markup processor to produce HTML, LaTeX, and more. @@ -66,12 +66,13 @@ size_t scan_spnl(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\t': - case ' ': goto yy3; + case ' ': + case 0xA0: goto yy3; case '\n': goto yy4; case '\r': goto yy6; default: goto yy7; @@ -87,7 +88,8 @@ size_t scan_spnl(const char * c) { yy5: switch (yych) { case '\t': - case ' ': goto yy4; + case ' ': + case 0xA0: goto yy4; default: goto yy2; } yy6: @@ -111,7 +113,8 @@ size_t scan_spnl(const char * c) { yy11: switch (yych) { case '\t': - case ' ': goto yy10; + case ' ': + case 0xA0: goto yy10; case '\n': goto yy4; case '\r': goto yy9; default: goto yy2; @@ -126,7 +129,7 @@ size_t scan_key(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy14; @@ -281,7 +284,7 @@ size_t scan_value(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy22; @@ -488,11 +491,12 @@ size_t scan_attr(const char * c) { { - char yych; + unsigned char yych; yych = *(marker = c); switch (yych) { case '\t': - case ' ': goto yy39; + case ' ': + case 0xA0: goto yy39; case '\n': goto yy40; case '\r': goto yy43; case ':': @@ -613,7 +617,8 @@ size_t scan_attr(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy60; + case 'z': + case 0xA0: goto yy60; default: goto yy38; } yy40: @@ -622,7 +627,8 @@ size_t scan_attr(const char * c) { yy41: switch (yych) { case '\t': - case ' ': goto yy40; + case ' ': + case 0xA0: goto yy40; case ':': case 'A': case 'B': @@ -687,7 +693,8 @@ size_t scan_attr(const char * c) { switch (yych) { case '\t': case '\n': - case ' ': goto yy40; + case ' ': + case 0xA0: goto yy40; case ':': case 'A': case 'B': @@ -897,7 +904,8 @@ size_t scan_attr(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy48; + case ' ': + case 0xA0: goto yy48; case '"': goto yy50; case '\'': goto yy52; case '.': @@ -1071,7 +1079,8 @@ size_t scan_attr(const char * c) { yy60: switch (yych) { case '\t': - case ' ': goto yy59; + case ' ': + case 0xA0: goto yy59; case '\n': goto yy40; case '\r': goto yy58; case ':': @@ -1141,12 +1150,13 @@ size_t scan_attributes(const char * c) { { - char yych; + unsigned char yych; unsigned int yyaccept = 0; yych = *(marker = c); switch (yych) { case '\t': - case ' ': goto yy64; + case ' ': + case 0xA0: goto yy64; case '\n': goto yy65; case '\r': goto yy68; case ':': @@ -1268,7 +1278,8 @@ size_t scan_attributes(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy83; + case 'z': + case 0xA0: goto yy83; default: goto yy63; } yy65: @@ -1276,7 +1287,8 @@ size_t scan_attributes(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy65; + case ' ': + case 0xA0: goto yy65; case ':': case 'A': case 'B': @@ -1346,7 +1358,8 @@ size_t scan_attributes(const char * c) { switch (yych) { case '\t': case '\n': - case ' ': goto yy65; + case ' ': + case 0xA0: goto yy65; case ':': case 'A': case 'B': @@ -1557,7 +1570,8 @@ size_t scan_attributes(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy73; + case ' ': + case 0xA0: goto yy73; case '"': goto yy75; case '\'': goto yy77; case '.': @@ -1651,7 +1665,8 @@ size_t scan_attributes(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy82; + case ' ': + case 0xA0: goto yy82; case '\n': goto yy65; case '\r': goto yy84; case '.': @@ -1729,7 +1744,8 @@ size_t scan_attributes(const char * c) { yy83: switch (yych) { case '\t': - case ' ': goto yy82; + case ' ': + case 0xA0: goto yy82; case '\n': goto yy65; case '\r': goto yy84; case ':': @@ -1794,7 +1810,8 @@ size_t scan_attributes(const char * c) { switch (yych) { case '\t': case '\n': - case ' ': goto yy65; + case ' ': + case 0xA0: goto yy65; case ':': case 'A': case 'B': @@ -1857,7 +1874,8 @@ size_t scan_attributes(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy82; + case ' ': + case 0xA0: goto yy82; case '\n': goto yy65; case '\r': goto yy84; case '-': @@ -1935,7 +1953,8 @@ size_t scan_attributes(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy82; + case ' ': + case 0xA0: goto yy82; case '\n': goto yy65; case '\r': goto yy84; case ':': @@ -2005,7 +2024,7 @@ size_t scan_email(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy90; @@ -2249,7 +2268,8 @@ size_t scan_email(const char * c) { case '\n': case '\r': case ' ': - case '>': goto yy95; + case '>': + case 0xA0: goto yy95; default: goto yy98; } yy95: @@ -2343,7 +2363,8 @@ size_t scan_email(const char * c) { case '\n': case '\r': case ' ': - case '>': goto yy100; + case '>': + case 0xA0: goto yy100; default: goto yy98; } yy100: @@ -2399,7 +2420,7 @@ size_t scan_url(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy109; @@ -2810,7 +2831,8 @@ size_t scan_url(const char * c) { case '\n': case '\r': case ' ': - case '>': goto yy115; + case '>': + case 0xA0: goto yy115; default: goto yy121; } yy119: @@ -2901,7 +2923,8 @@ size_t scan_url(const char * c) { case '\n': case '\r': case ' ': - case '>': goto yy123; + case '>': + case 0xA0: goto yy123; default: goto yy121; } yy123: @@ -2920,7 +2943,8 @@ size_t scan_url(const char * c) { case '\n': case '\r': case ' ': - case '>': goto yy115; + case '>': + case 0xA0: goto yy115; default: goto yy126; } yy126: @@ -2932,7 +2956,8 @@ size_t scan_url(const char * c) { case '\n': case '\r': case ' ': - case '>': goto yy128; + case '>': + case 0xA0: goto yy128; default: goto yy126; } yy128: @@ -3253,7 +3278,8 @@ size_t scan_url(const char * c) { case '\n': case '\r': case ' ': - case '>': goto yy115; + case '>': + case 0xA0: goto yy115; case '!': case '$': case '%': @@ -3337,7 +3363,8 @@ size_t scan_url(const char * c) { case '\n': case '\r': case ' ': - case '>': goto yy128; + case '>': + case 0xA0: goto yy128; case '!': case '$': case '%': @@ -3420,7 +3447,8 @@ size_t scan_url(const char * c) { case '\n': case '\r': case ' ': - case '>': goto yy128; + case '>': + case 0xA0: goto yy128; default: goto yy140; } yy140: @@ -3432,7 +3460,8 @@ size_t scan_url(const char * c) { case '\n': case '\r': case ' ': - case '>': goto yy123; + case '>': + case 0xA0: goto yy123; default: goto yy140; } } @@ -3446,11 +3475,12 @@ size_t scan_ref_abbreviation(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy144; - case ' ': goto yy145; + case ' ': + case 0xA0: goto yy145; case '[': goto yy146; default: goto yy147; } @@ -3459,7 +3489,8 @@ size_t scan_ref_abbreviation(const char * c) { yy145: yych = *(marker = ++c); switch (yych) { - case ' ': goto yy158; + case ' ': + case 0xA0: goto yy158; case '[': goto yy159; default: goto yy144; } @@ -3525,7 +3556,8 @@ size_t scan_ref_abbreviation(const char * c) { yy158: yych = *++c; switch (yych) { - case ' ': goto yy160; + case ' ': + case 0xA0: goto yy160; case '[': goto yy159; default: goto yy150; } @@ -3552,11 +3584,12 @@ size_t scan_ref_citation(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy163; - case ' ': goto yy164; + case ' ': + case 0xA0: goto yy164; case '[': goto yy165; default: goto yy166; } @@ -3565,7 +3598,8 @@ size_t scan_ref_citation(const char * c) { yy164: yych = *(marker = ++c); switch (yych) { - case ' ': goto yy177; + case ' ': + case 0xA0: goto yy177; case '[': goto yy178; default: goto yy163; } @@ -3631,7 +3665,8 @@ size_t scan_ref_citation(const char * c) { yy177: yych = *++c; switch (yych) { - case ' ': goto yy179; + case ' ': + case 0xA0: goto yy179; case '[': goto yy178; default: goto yy169; } @@ -3658,11 +3693,12 @@ size_t scan_ref_foot(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy182; - case ' ': goto yy183; + case ' ': + case 0xA0: goto yy183; case '[': goto yy184; default: goto yy185; } @@ -3671,7 +3707,8 @@ size_t scan_ref_foot(const char * c) { yy183: yych = *(marker = ++c); switch (yych) { - case ' ': goto yy196; + case ' ': + case 0xA0: goto yy196; case '[': goto yy197; default: goto yy182; } @@ -3737,7 +3774,8 @@ size_t scan_ref_foot(const char * c) { yy196: yych = *++c; switch (yych) { - case ' ': goto yy198; + case ' ': + case 0xA0: goto yy198; case '[': goto yy197; default: goto yy188; } @@ -3764,11 +3802,12 @@ size_t scan_ref_glossary(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy201; - case ' ': goto yy202; + case ' ': + case 0xA0: goto yy202; case '[': goto yy203; default: goto yy204; } @@ -3777,7 +3816,8 @@ size_t scan_ref_glossary(const char * c) { yy202: yych = *(marker = ++c); switch (yych) { - case ' ': goto yy215; + case ' ': + case 0xA0: goto yy215; case '[': goto yy216; default: goto yy201; } @@ -3843,7 +3883,8 @@ size_t scan_ref_glossary(const char * c) { yy215: yych = *++c; switch (yych) { - case ' ': goto yy217; + case ' ': + case 0xA0: goto yy217; case '[': goto yy216; default: goto yy207; } @@ -3870,12 +3911,13 @@ size_t scan_ref_link_no_attributes(const char * c) { { - char yych; + unsigned char yych; unsigned int yyaccept = 0; yych = *c; switch (yych) { case '\n': goto yy220; - case ' ': goto yy221; + case ' ': + case 0xA0: goto yy221; case '[': goto yy222; default: goto yy223; } @@ -3885,7 +3927,8 @@ size_t scan_ref_link_no_attributes(const char * c) { yyaccept = 0; yych = *(marker = ++c); switch (yych) { - case ' ': goto yy359; + case ' ': + case 0xA0: goto yy359; case '[': goto yy227; default: goto yy220; } @@ -3944,7 +3987,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy226; case '\t': - case ' ': goto yy230; + case ' ': + case 0xA0: goto yy230; case '\n': goto yy232; case '\r': goto yy234; case '<': goto yy235; @@ -3958,7 +4002,8 @@ size_t scan_ref_link_no_attributes(const char * c) { case '\n': case '\r': goto yy226; case '\t': - case ' ': goto yy232; + case ' ': + case 0xA0: goto yy232; case '<': goto yy235; default: goto yy237; } @@ -3969,7 +4014,8 @@ size_t scan_ref_link_no_attributes(const char * c) { case '\r': goto yy226; case '\t': case '\n': - case ' ': goto yy232; + case ' ': + case 0xA0: goto yy232; case '<': goto yy235; default: goto yy237; } @@ -3979,7 +4025,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy239; + case ' ': + case 0xA0: goto yy239; case '\n': goto yy243; case '\r': goto yy244; case '"': goto yy332; @@ -3994,7 +4041,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy239; + case ' ': + case 0xA0: goto yy239; case '\n': goto yy243; case '\r': goto yy244; case '"': goto yy245; @@ -4008,7 +4056,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy239; + case ' ': + case 0xA0: goto yy239; case '\n': goto yy243; case '\r': goto yy244; case '"': goto yy261; @@ -4045,7 +4094,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy330; + case ' ': + case 0xA0: goto yy330; case '\n': goto yy243; case '\r': goto yy244; case '"': goto yy318; @@ -4059,7 +4109,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy328; + case ' ': + case 0xA0: goto yy328; case '\n': goto yy243; case '\r': goto yy244; case '"': goto yy308; @@ -4073,7 +4124,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy251; + case ' ': + case 0xA0: goto yy251; case '\n': goto yy243; case '\r': goto yy244; case '"': goto yy253; @@ -4087,7 +4139,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy251; + case ' ': + case 0xA0: goto yy251; case '\n': goto yy243; case '\r': goto yy244; case '"': goto yy298; @@ -4101,7 +4154,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy320; + case ' ': + case 0xA0: goto yy320; case '\n': goto yy243; case '\r': goto yy244; case '"': goto yy322; @@ -4115,7 +4169,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy272; + case ' ': + case 0xA0: goto yy272; case '\n': goto yy243; case '\r': goto yy244; case '"': goto yy274; @@ -4129,7 +4184,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy258; + case ' ': + case 0xA0: goto yy258; case '\n': goto yy243; case '\r': goto yy260; case '"': goto yy245; @@ -4143,7 +4199,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy258; + case ' ': + case 0xA0: goto yy258; case '\n': goto yy243; case '\r': goto yy260; case '"': goto yy261; @@ -4198,7 +4255,8 @@ size_t scan_ref_link_no_attributes(const char * c) { case 0x00: case '\n': goto yy241; case '\t': - case ' ': goto yy267; + case ' ': + case 0xA0: goto yy267; case '\r': goto yy269; default: goto yy226; } @@ -4214,7 +4272,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy316; + case ' ': + case 0xA0: goto yy316; case '\n': goto yy243; case '\r': goto yy260; case '"': goto yy308; @@ -4228,7 +4287,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy272; + case ' ': + case 0xA0: goto yy272; case '\n': goto yy243; case '\r': goto yy244; case '"': goto yy284; @@ -4242,7 +4302,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy302; + case ' ': + case 0xA0: goto yy302; case '\n': goto yy243; case '\r': goto yy244; case '"': @@ -4256,7 +4317,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy278; + case ' ': + case 0xA0: goto yy278; case '\n': goto yy243; case '\r': goto yy260; case '"': goto yy274; @@ -4270,7 +4332,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy278; + case ' ': + case 0xA0: goto yy278; case '\n': goto yy243; case '\r': goto yy260; case '"': goto yy284; @@ -4285,7 +4348,8 @@ size_t scan_ref_link_no_attributes(const char * c) { case 0x00: case '\n': goto yy241; case '\t': - case ' ': goto yy280; + case ' ': + case 0xA0: goto yy280; case '\r': goto yy269; case '\'': goto yy267; default: goto yy263; @@ -4320,7 +4384,8 @@ size_t scan_ref_link_no_attributes(const char * c) { case 0x00: case '\n': goto yy241; case '\t': - case ' ': goto yy286; + case ' ': + case 0xA0: goto yy286; case '\r': goto yy269; case '\'': goto yy288; case ')': goto yy280; @@ -4333,7 +4398,8 @@ size_t scan_ref_link_no_attributes(const char * c) { case 0x00: case '\n': goto yy241; case '\t': - case ' ': goto yy288; + case ' ': + case 0xA0: goto yy288; case '\r': goto yy269; case ')': goto yy267; default: goto yy265; @@ -4345,7 +4411,8 @@ size_t scan_ref_link_no_attributes(const char * c) { case 0x00: case '\n': goto yy241; case '\t': - case ' ': goto yy290; + case ' ': + case 0xA0: goto yy290; case '\r': goto yy269; case '"': goto yy288; case ')': goto yy294; @@ -4358,7 +4425,8 @@ size_t scan_ref_link_no_attributes(const char * c) { case 0x00: case '\n': goto yy241; case '\t': - case ' ': goto yy292; + case ' ': + case 0xA0: goto yy292; case '\r': goto yy269; case '"': goto yy280; case '\'': goto yy294; @@ -4371,7 +4439,8 @@ size_t scan_ref_link_no_attributes(const char * c) { case 0x00: case '\n': goto yy241; case '\t': - case ' ': goto yy294; + case ' ': + case 0xA0: goto yy294; case '\r': goto yy269; case '"': goto yy267; default: goto yy261; @@ -4404,7 +4473,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy314; + case ' ': + case 0xA0: goto yy314; case '\n': goto yy243; case '\r': goto yy260; case '"': @@ -4418,7 +4488,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy302; + case ' ': + case 0xA0: goto yy302; case '\n': goto yy243; case '\r': goto yy244; case '"': @@ -4432,7 +4503,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy306; + case ' ': + case 0xA0: goto yy306; case '\n': goto yy243; case '\r': goto yy260; case '"': @@ -4446,7 +4518,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy306; + case ' ': + case 0xA0: goto yy306; case '\n': goto yy243; case '\r': goto yy260; case '"': @@ -4460,7 +4533,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy310; + case ' ': + case 0xA0: goto yy310; case '\n': goto yy243; case '\r': goto yy244; case '"': @@ -4474,7 +4548,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy310; + case ' ': + case 0xA0: goto yy310; case '\n': goto yy243; case '\r': goto yy244; case '"': @@ -4489,7 +4564,8 @@ size_t scan_ref_link_no_attributes(const char * c) { case 0x00: case '\n': goto yy241; case '\t': - case ' ': goto yy312; + case ' ': + case 0xA0: goto yy312; case '\r': goto yy269; case '"': goto yy286; case '\'': goto yy290; @@ -4502,7 +4578,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy314; + case ' ': + case 0xA0: goto yy314; case '\n': goto yy243; case '\r': goto yy260; case '"': @@ -4516,7 +4593,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy316; + case ' ': + case 0xA0: goto yy316; case '\n': goto yy243; case '\r': goto yy260; case '"': goto yy296; @@ -4530,7 +4608,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy326; + case ' ': + case 0xA0: goto yy326; case '\n': goto yy243; case '\r': goto yy260; case '"': goto yy318; @@ -4544,7 +4623,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy320; + case ' ': + case 0xA0: goto yy320; case '\n': goto yy243; case '\r': goto yy244; case '"': goto yy290; @@ -4558,7 +4638,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy324; + case ' ': + case 0xA0: goto yy324; case '\n': goto yy243; case '\r': goto yy260; case '"': goto yy322; @@ -4572,7 +4653,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy324; + case ' ': + case 0xA0: goto yy324; case '\n': goto yy243; case '\r': goto yy260; case '"': goto yy290; @@ -4586,7 +4668,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy326; + case ' ': + case 0xA0: goto yy326; case '\n': goto yy243; case '\r': goto yy260; case '"': goto yy294; @@ -4600,7 +4683,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy328; + case ' ': + case 0xA0: goto yy328; case '\n': goto yy243; case '\r': goto yy244; case '"': goto yy296; @@ -4614,7 +4698,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy330; + case ' ': + case 0xA0: goto yy330; case '\n': goto yy243; case '\r': goto yy244; case '"': goto yy294; @@ -4628,7 +4713,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy330; + case ' ': + case 0xA0: goto yy330; case '\n': goto yy243; case '\r': goto yy244; case '"': goto yy355; @@ -4643,7 +4729,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy328; + case ' ': + case 0xA0: goto yy328; case '\n': goto yy243; case '\r': goto yy244; case '"': goto yy353; @@ -4658,7 +4745,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy251; + case ' ': + case 0xA0: goto yy251; case '\n': goto yy243; case '\r': goto yy244; case '"': goto yy338; @@ -4673,7 +4761,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy320; + case ' ': + case 0xA0: goto yy320; case '\n': goto yy243; case '\r': goto yy244; case '"': goto yy357; @@ -4688,7 +4777,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy272; + case ' ': + case 0xA0: goto yy272; case '\n': goto yy243; case '\r': goto yy244; case '"': goto yy345; @@ -4703,7 +4793,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy258; + case ' ': + case 0xA0: goto yy258; case '\n': goto yy243; case '\r': goto yy260; case '"': goto yy332; @@ -4718,7 +4809,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy316; + case ' ': + case 0xA0: goto yy316; case '\n': goto yy243; case '\r': goto yy260; case '"': goto yy353; @@ -4733,7 +4825,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy302; + case ' ': + case 0xA0: goto yy302; case '\n': goto yy243; case '\r': goto yy244; case '"': @@ -4748,7 +4841,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy278; + case ' ': + case 0xA0: goto yy278; case '\n': goto yy243; case '\r': goto yy260; case '"': goto yy345; @@ -4763,7 +4857,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy314; + case ' ': + case 0xA0: goto yy314; case '\n': goto yy243; case '\r': goto yy260; case '"': @@ -4778,7 +4873,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy306; + case ' ': + case 0xA0: goto yy306; case '\n': goto yy243; case '\r': goto yy260; case '"': @@ -4793,7 +4889,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy310; + case ' ': + case 0xA0: goto yy310; case '\n': goto yy243; case '\r': goto yy244; case '"': @@ -4808,7 +4905,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy326; + case ' ': + case 0xA0: goto yy326; case '\n': goto yy243; case '\r': goto yy260; case '"': goto yy355; @@ -4823,7 +4921,8 @@ size_t scan_ref_link_no_attributes(const char * c) { switch (yych) { case 0x00: goto yy241; case '\t': - case ' ': goto yy324; + case ' ': + case 0xA0: goto yy324; case '\n': goto yy243; case '\r': goto yy260; case '"': goto yy357; @@ -4835,7 +4934,8 @@ size_t scan_ref_link_no_attributes(const char * c) { yy359: yych = *++c; switch (yych) { - case ' ': goto yy360; + case ' ': + case 0xA0: goto yy360; case '[': goto yy227; default: goto yy226; } @@ -4856,11 +4956,12 @@ size_t scan_ref_link(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy363; - case ' ': goto yy364; + case ' ': + case 0xA0: goto yy364; case '[': goto yy365; default: goto yy366; } @@ -4869,7 +4970,8 @@ size_t scan_ref_link(const char * c) { yy364: yych = *(marker = ++c); switch (yych) { - case ' ': goto yy377; + case ' ': + case 0xA0: goto yy377; case '[': goto yy370; default: goto yy363; } @@ -4939,7 +5041,8 @@ size_t scan_ref_link(const char * c) { yy377: yych = *++c; switch (yych) { - case ' ': goto yy378; + case ' ': + case 0xA0: goto yy378; case '[': goto yy370; default: goto yy369; } @@ -4960,7 +5063,7 @@ size_t scan_html(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy381; @@ -5102,7 +5205,8 @@ size_t scan_html(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy391; + case ' ': + case 0xA0: goto yy391; case '\n': goto yy393; case '\r': goto yy395; case '-': @@ -5179,7 +5283,8 @@ size_t scan_html(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy391; + case ' ': + case 0xA0: goto yy391; case '\n': goto yy393; case '\r': goto yy395; case '-': @@ -5258,7 +5363,8 @@ size_t scan_html(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy391; + case ' ': + case 0xA0: goto yy391; case '\n': goto yy393; case '\r': goto yy395; case '/': goto yy400; @@ -5324,7 +5430,8 @@ size_t scan_html(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy393; + case ' ': + case 0xA0: goto yy393; case ':': case 'A': case 'B': @@ -5387,7 +5494,8 @@ size_t scan_html(const char * c) { switch (yych) { case '\t': case '\n': - case ' ': goto yy393; + case ' ': + case 0xA0: goto yy393; case ':': case 'A': case 'B': @@ -5531,7 +5639,8 @@ size_t scan_html(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy401; + case ' ': + case 0xA0: goto yy401; case '"': goto yy403; case '\'': goto yy405; case '.': @@ -5624,7 +5733,8 @@ size_t scan_html(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy391; + case ' ': + case 0xA0: goto yy391; case '\n': goto yy393; case '\r': goto yy395; case '.': @@ -5701,7 +5811,8 @@ size_t scan_html(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy391; + case ' ': + case 0xA0: goto yy391; case '\n': goto yy393; case '\r': goto yy395; case '-': @@ -5780,7 +5891,8 @@ size_t scan_html(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy413; + case ' ': + case 0xA0: goto yy413; case '-': case '0': case '1': @@ -5852,7 +5964,8 @@ size_t scan_html(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy413; + case ' ': + case 0xA0: goto yy413; case '>': goto yy398; default: goto yy385; } @@ -5907,7 +6020,7 @@ size_t scan_html_comment(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy424; @@ -5988,7 +6101,7 @@ size_t scan_html_block(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy440; @@ -6260,7 +6373,8 @@ size_t scan_html_block(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy465; + case ' ': + case 0xA0: goto yy465; case '\n': goto yy467; case '\r': goto yy469; case '/': goto yy472; @@ -6327,7 +6441,8 @@ size_t scan_html_block(const char * c) { yy466: switch (yych) { case '\t': - case ' ': goto yy465; + case ' ': + case 0xA0: goto yy465; case '\n': goto yy467; case '\r': goto yy469; case ':': @@ -6391,7 +6506,8 @@ size_t scan_html_block(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy467; + case ' ': + case 0xA0: goto yy467; case ':': case 'A': case 'B': @@ -6454,7 +6570,8 @@ size_t scan_html_block(const char * c) { switch (yych) { case '\t': case '\n': - case ' ': goto yy467; + case ' ': + case 0xA0: goto yy467; case ':': case 'A': case 'B': @@ -6599,7 +6716,8 @@ size_t scan_html_block(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy475; + case ' ': + case 0xA0: goto yy475; case '"': goto yy477; case '\'': goto yy479; case '.': @@ -6692,7 +6810,8 @@ size_t scan_html_block(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy465; + case ' ': + case 0xA0: goto yy465; case '\n': goto yy467; case '\r': goto yy469; case '.': @@ -6769,7 +6888,8 @@ size_t scan_html_block(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy465; + case ' ': + case 0xA0: goto yy465; case '\n': goto yy467; case '\r': goto yy469; case '-': @@ -7635,7 +7755,7 @@ size_t scan_html_line(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy595; @@ -7777,7 +7897,8 @@ size_t scan_html_line(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy605; + case ' ': + case 0xA0: goto yy605; case '\n': goto yy607; case '\r': goto yy609; case '-': @@ -7854,7 +7975,8 @@ size_t scan_html_line(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy605; + case ' ': + case 0xA0: goto yy605; case '\n': goto yy607; case '\r': goto yy609; case '-': @@ -7933,7 +8055,8 @@ size_t scan_html_line(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy605; + case ' ': + case 0xA0: goto yy605; case '\n': goto yy607; case '\r': goto yy609; case '/': goto yy614; @@ -7999,7 +8122,8 @@ size_t scan_html_line(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy607; + case ' ': + case 0xA0: goto yy607; case ':': case 'A': case 'B': @@ -8062,7 +8186,8 @@ size_t scan_html_line(const char * c) { switch (yych) { case '\t': case '\n': - case ' ': goto yy607; + case ' ': + case 0xA0: goto yy607; case ':': case 'A': case 'B': @@ -8197,7 +8322,8 @@ size_t scan_html_line(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy612; + case ' ': + case 0xA0: goto yy612; case '\n': goto yy615; case '\r': goto yy617; default: goto yy599; @@ -8223,7 +8349,8 @@ size_t scan_html_line(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy618; + case ' ': + case 0xA0: goto yy618; case '"': goto yy620; case '\'': goto yy622; case '.': @@ -8316,7 +8443,8 @@ size_t scan_html_line(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy605; + case ' ': + case 0xA0: goto yy605; case '\n': goto yy607; case '\r': goto yy609; case '.': @@ -8393,7 +8521,8 @@ size_t scan_html_line(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy605; + case ' ': + case 0xA0: goto yy605; case '\n': goto yy607; case '\r': goto yy609; case '-': @@ -8472,7 +8601,8 @@ size_t scan_html_line(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy630; + case ' ': + case 0xA0: goto yy630; case '-': case '0': case '1': @@ -8544,7 +8674,8 @@ size_t scan_html_line(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy630; + case ' ': + case 0xA0: goto yy630; case '>': goto yy612; default: goto yy599; } @@ -8599,11 +8730,12 @@ size_t scan_fence_start(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy641; - case ' ': goto yy642; + case ' ': + case 0xA0: goto yy642; case '`': case '~': goto yy643; default: goto yy644; @@ -8613,7 +8745,8 @@ size_t scan_fence_start(const char * c) { yy642: yych = *(marker = ++c); switch (yych) { - case ' ': goto yy656; + case ' ': + case 0xA0: goto yy656; case '`': case '~': goto yy657; default: goto yy641; @@ -8686,7 +8819,8 @@ size_t scan_fence_start(const char * c) { yy656: yych = *++c; switch (yych) { - case ' ': goto yy658; + case ' ': + case 0xA0: goto yy658; case '`': case '~': goto yy657; default: goto yy646; @@ -8716,11 +8850,12 @@ size_t scan_fence_end(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy661; - case ' ': goto yy662; + case ' ': + case 0xA0: goto yy662; case '`': case '~': goto yy663; default: goto yy664; @@ -8730,7 +8865,8 @@ size_t scan_fence_end(const char * c) { yy662: yych = *(marker = ++c); switch (yych) { - case ' ': goto yy674; + case ' ': + case 0xA0: goto yy674; case '`': case '~': goto yy675; default: goto yy661; @@ -8762,7 +8898,8 @@ size_t scan_fence_end(const char * c) { case 0x00: case '\n': goto yy671; case '\t': - case ' ': goto yy669; + case ' ': + case 0xA0: goto yy669; case '\r': goto yy673; case '`': case '~': goto yy667; @@ -8775,7 +8912,8 @@ size_t scan_fence_end(const char * c) { case 0x00: case '\n': goto yy671; case '\t': - case ' ': goto yy669; + case ' ': + case 0xA0: goto yy669; case '\r': goto yy673; default: goto yy666; } @@ -8792,7 +8930,8 @@ size_t scan_fence_end(const char * c) { yy674: yych = *++c; switch (yych) { - case ' ': goto yy676; + case ' ': + case 0xA0: goto yy676; case '`': case '~': goto yy675; default: goto yy666; @@ -8822,7 +8961,7 @@ size_t scan_meta_line(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy679; @@ -8962,7 +9101,8 @@ size_t scan_meta_line(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy683; + case 'z': + case 0xA0: goto yy683; default: goto yy679; } yy681: @@ -9039,7 +9179,8 @@ size_t scan_meta_line(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy682; + case 'z': + case 0xA0: goto yy682; case ':': goto yy685; default: goto yy684; } @@ -9083,7 +9224,7 @@ size_t scan_meta_key(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy693; @@ -9233,7 +9374,8 @@ size_t scan_meta_key(const char * c) { case 'w': case 'x': case 'y': - case 'z': goto yy697; + case 'z': + case 0xA0: goto yy697; default: goto yy695; } } @@ -9247,11 +9389,12 @@ size_t scan_definition(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy701; - case ' ': goto yy702; + case ' ': + case 0xA0: goto yy702; case ':': goto yy703; default: goto yy704; } @@ -9260,7 +9403,8 @@ size_t scan_definition(const char * c) { yy702: yych = *(marker = ++c); switch (yych) { - case ' ': goto yy709; + case ' ': + case 0xA0: goto yy709; case ':': goto yy711; default: goto yy701; } @@ -9284,7 +9428,8 @@ size_t scan_definition(const char * c) { case '\n': case '\r': goto yy707; case '\t': - case ' ': goto yy705; + case ' ': + case 0xA0: goto yy705; default: goto yy708; } yy707: @@ -9295,7 +9440,8 @@ size_t scan_definition(const char * c) { yy709: yych = *++c; switch (yych) { - case ' ': goto yy712; + case ' ': + case 0xA0: goto yy712; case ':': goto yy711; default: goto yy710; } @@ -9327,7 +9473,7 @@ size_t scan_table_separator(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\t': @@ -9335,7 +9481,8 @@ size_t scan_table_separator(const char * c) { case '+': case '-': case ':': - case '=': goto yy717; + case '=': + case 0xA0: goto yy717; case '\n': goto yy715; case '|': goto yy716; default: goto yy718; @@ -9354,7 +9501,8 @@ size_t scan_table_separator(const char * c) { case '-': case ':': case '=': - case '|': goto yy728; + case '|': + case 0xA0: goto yy728; default: goto yy715; } yy717: @@ -9365,7 +9513,8 @@ size_t scan_table_separator(const char * c) { case '+': case '-': case ':': - case '=': goto yy722; + case '=': + case 0xA0: goto yy722; case '|': goto yy719; default: goto yy715; } @@ -9384,7 +9533,8 @@ size_t scan_table_separator(const char * c) { case '-': case ':': case '=': - case '|': goto yy719; + case '|': + case 0xA0: goto yy719; case '\r': goto yy726; default: goto yy721; } @@ -9400,7 +9550,8 @@ size_t scan_table_separator(const char * c) { case '+': case '-': case ':': - case '=': goto yy722; + case '=': + case 0xA0: goto yy722; case '|': goto yy719; default: goto yy721; } @@ -9427,7 +9578,8 @@ size_t scan_table_separator(const char * c) { case '-': case ':': case '=': - case '|': goto yy727; + case '|': + case 0xA0: goto yy727; case '\r': goto yy726; default: goto yy721; } @@ -9441,11 +9593,12 @@ size_t scan_alignment_string(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\t': - case ' ': goto yy732; + case ' ': + case 0xA0: goto yy732; case '\n': goto yy731; case '-': case '=': goto yy734; @@ -9458,7 +9611,8 @@ size_t scan_alignment_string(const char * c) { yych = *(marker = ++c); switch (yych) { case '\t': - case ' ': goto yy774; + case ' ': + case 0xA0: goto yy774; case '-': case '=': goto yy738; case ':': goto yy773; @@ -9509,7 +9663,8 @@ size_t scan_alignment_string(const char * c) { case '\n': case '|': goto yy742; case '\t': - case ' ': goto yy740; + case ' ': + case 0xA0: goto yy740; case '\r': goto yy744; default: goto yy737; } @@ -9531,7 +9686,8 @@ size_t scan_alignment_string(const char * c) { case '\n': case '|': goto yy747; case '\t': - case ' ': goto yy745; + case ' ': + case 0xA0: goto yy745; case '\r': goto yy749; default: goto yy737; } @@ -9553,7 +9709,8 @@ size_t scan_alignment_string(const char * c) { case '\n': case '|': goto yy754; case '\t': - case ' ': goto yy752; + case ' ': + case 0xA0: goto yy752; case '\r': goto yy756; case '+': goto yy758; case '-': @@ -9569,7 +9726,8 @@ size_t scan_alignment_string(const char * c) { case '\n': case '|': goto yy754; case '\t': - case ' ': goto yy752; + case ' ': + case 0xA0: goto yy752; case '\r': goto yy756; default: goto yy737; } @@ -9597,7 +9755,8 @@ size_t scan_alignment_string(const char * c) { case '\n': case '|': goto yy760; case '\t': - case ' ': goto yy758; + case ' ': + case 0xA0: goto yy758; case '\r': goto yy762; default: goto yy737; } @@ -9619,7 +9778,8 @@ size_t scan_alignment_string(const char * c) { case '\n': case '|': goto yy770; case '\t': - case ' ': goto yy763; + case ' ': + case 0xA0: goto yy763; case '\r': goto yy772; default: goto yy737; } @@ -9632,7 +9792,8 @@ size_t scan_alignment_string(const char * c) { case '\n': case '|': goto yy767; case '\t': - case ' ': goto yy765; + case ' ': + case 0xA0: goto yy765; case '\r': goto yy769; default: goto yy737; } @@ -9668,7 +9829,8 @@ size_t scan_alignment_string(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy774; + case ' ': + case 0xA0: goto yy774; case '-': case '=': goto yy738; case ':': goto yy773; @@ -9684,13 +9846,14 @@ size_t scan_destination(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case 0x00: case '\t': case '\r': - case ' ': goto yy782; + case ' ': + case 0xA0: goto yy782; case '\n': goto yy778; case '<': goto yy779; default: goto yy781; @@ -9718,7 +9881,8 @@ size_t scan_destination(const char * c) { case '\t': case '\n': case '\r': - case ' ': goto yy780; + case ' ': + case 0xA0: goto yy780; default: goto yy783; } yy785: @@ -9730,7 +9894,8 @@ size_t scan_destination(const char * c) { case '\t': case '\n': case '\r': - case ' ': goto yy780; + case ' ': + case 0xA0: goto yy780; case '>': goto yy783; default: goto yy785; } @@ -9745,7 +9910,7 @@ size_t scan_title(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy789; @@ -9832,11 +9997,12 @@ size_t scan_setext(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy805; - case ' ': goto yy806; + case ' ': + case 0xA0: goto yy806; case '-': goto yy808; case '=': goto yy807; default: goto yy809; @@ -9846,7 +10012,8 @@ size_t scan_setext(const char * c) { yy806: yych = *(marker = ++c); switch (yych) { - case ' ': goto yy821; + case ' ': + case 0xA0: goto yy821; case '-': goto yy822; case '=': goto yy823; default: goto yy805; @@ -9912,7 +10079,8 @@ size_t scan_setext(const char * c) { yy821: yych = *++c; switch (yych) { - case ' ': goto yy824; + case ' ': + case 0xA0: goto yy824; case '-': goto yy822; case '=': goto yy823; default: goto yy812; @@ -9946,7 +10114,7 @@ size_t scan_atx(const char * c) { { - char yych; + unsigned char yych; yych = *c; switch (yych) { case '\n': goto yy827; @@ -9959,7 +10127,8 @@ size_t scan_atx(const char * c) { yych = *(marker = ++c); switch (yych) { case '\t': - case ' ': goto yy830; + case ' ': + case 0xA0: goto yy830; case '#': goto yy833; default: goto yy827; } @@ -9974,7 +10143,8 @@ size_t scan_atx(const char * c) { case '\n': case '\r': goto yy832; case '\t': - case ' ': goto yy830; + case ' ': + case 0xA0: goto yy830; default: goto yy835; } yy832: @@ -9985,7 +10155,8 @@ size_t scan_atx(const char * c) { yych = *c; switch (yych) { case '\t': - case ' ': goto yy830; + case ' ': + case 0xA0: goto yy830; case '#': goto yy833; default: goto yy832; } diff --git a/Sources/libMultiMarkdown/scanners.re b/Sources/libMultiMarkdown/scanners.re index e891d56d..5b7e0d58 100644 --- a/Sources/libMultiMarkdown/scanners.re +++ b/Sources/libMultiMarkdown/scanners.re @@ -59,21 +59,21 @@ /*!re2c - re2c:define:YYCTYPE = "char"; + re2c:define:YYCTYPE = "unsigned char"; re2c:define:YYCURSOR = c; re2c:define:YYMARKER = marker; re2c:define:YYCTXMARKER = marker; re2c:yyfill:enable = 0; nl = ( '\n' | '\r' '\n'?); - sp = [ \t]*; + sp = [ \t\240]*; spnl = sp (nl sp)?; - non_indent = ' '{0,3}; + non_indent = [ \240]{0,3}; nl_eof = nl | '\x00'; - email = 'mailto:'? [-A-Za-z0-9+_./!%~$]+ '@' [^ \t\n\r\x00>]+; + email = 'mailto:'? [-A-Za-z0-9+_./!%~$]+ '@' [^ \240\t\n\r\x00>]+; - url = [A-Za-z\-]+ '://' [^ \t\n\r\x00>]+; + url = [A-Za-z\-]+ '://' [^ \240\t\n\r\x00>]+; name = [A-Za-z_:] [A-Za-z0-9_.:-]*; quoted_d = '"' [^"\n\r\x00]* '"'; @@ -99,7 +99,7 @@ ref_link = non_indent '[' label ']' ':' finish_line; - destination = ('<' [^ \t\n\r\x00>]* '>') | [^ \t\n\r\x00]+; + destination = ('<' [^ \240\t\n\r\x00>]* '>') | [^ \240\t\n\r\x00]+; ref_link_no_attributes = non_indent '[' label ']' ':' spnl destination sp (nl_eof | (nl? (title) sp) nl_eof); @@ -136,7 +136,7 @@ fence_end = non_indent [`~]{3,} sp nl_eof; - meta_key = [A-Za-z0-9] [A-Za-z0-9_ \t\-\.]*; + meta_key = [A-Za-z0-9] [A-Za-z0-9_ \240\t\-\.]*; meta_value = [^\n\r\x00]+; @@ -144,7 +144,7 @@ definition = non_indent ':' sp [^\n\r\x00]; - table_separator = (('|' [:\-= \t|+]*) | ([:\-= \t+]+ '|' [:\-= \t|+]*)) nl_eof; + table_separator = (('|' [:\-= \240\t|+]*) | ([:\-= \240\t+]+ '|' [:\-= \240\t|+]*)) nl_eof; align = [\-=]+; align_left = sp ':' align sp ('|' | nl_eof); @@ -158,7 +158,7 @@ setext_2 = non_indent '-'{2,} nl_eof; - atx = '#'+ [ \t]+ [^ \t\n\r\x00]; + atx = '#'+ [ \240\t]+ [^ \240\t\n\r\x00]; */ From 6dabedebc21575c216001f873e51e51561b038d7 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Wed, 15 Mar 2017 00:36:45 -0400 Subject: [PATCH 22/29] CHANGED: Remove debugging statement --- Sources/libMultiMarkdown/mmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/libMultiMarkdown/mmd.c b/Sources/libMultiMarkdown/mmd.c index 0046deb4..983c5f3c 100644 --- a/Sources/libMultiMarkdown/mmd.c +++ b/Sources/libMultiMarkdown/mmd.c @@ -415,7 +415,7 @@ void mmd_assign_line_type(mmd_engine * e, token * line) { (line->child->tail->prev->type <= HASH6)) line->child->tail->prev->type = TEXT_EMPTY; } else { - token_describe(line->child->tail, NULL); +// token_describe(line->child->tail, NULL); if ((line->child->tail->type >= HASH1) && (line->child->tail->type <= HASH6)) line->child->tail->type = TEXT_EMPTY; From ac864e797fc06b7e8b31421058c70ee0d50a08f1 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Wed, 15 Mar 2017 01:14:25 -0400 Subject: [PATCH 23/29] FIXED: Improve metadata edge cases; Fix NULL pointer dereference --- Sources/libMultiMarkdown/mmd.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Sources/libMultiMarkdown/mmd.c b/Sources/libMultiMarkdown/mmd.c index 983c5f3c..ff003316 100644 --- a/Sources/libMultiMarkdown/mmd.c +++ b/Sources/libMultiMarkdown/mmd.c @@ -1373,7 +1373,8 @@ void pair_emphasis_tokens(token * t) { case STAR: case UL: closer = t->mate; - if ((t->next->mate == closer->prev) && + if (t->next && + (t->next->mate == closer->prev) && (t->type == t->next->type) && (t->next->mate != t) && (t->start+t->len == t->next->start) && @@ -1522,6 +1523,7 @@ void strip_line_tokens_from_metadata(mmd_engine * e, token * metadata) { while (l) { switch (l->type) { case LINE_META: + meta: if (m) { meta_set_value(m, d->str); d_string_erase(d, 0, -1); @@ -1540,9 +1542,16 @@ void strip_line_tokens_from_metadata(mmd_engine * e, token * metadata) { l->len--; } case LINE_PLAIN: + plain: d_string_append_c(d, '\n'); d_string_append_c_array(d, &source[l->start], l->len); break; + case LINE_TABLE: + if (scan_meta_line(&source[l->start])) { + goto meta; + } else { + goto plain; + } default: fprintf(stderr, "ERROR!\n"); token_describe(l, NULL); From 89130c6ebdc676e5e67a63a347e134c4ec6e2deb Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Wed, 15 Mar 2017 01:50:08 -0400 Subject: [PATCH 24/29] FIXED: Add missing CriticMarkup tokens to LaTeX --- Sources/libMultiMarkdown/latex.c | 33 ++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Sources/libMultiMarkdown/latex.c b/Sources/libMultiMarkdown/latex.c index 0a287b0b..85bfba09 100644 --- a/Sources/libMultiMarkdown/latex.c +++ b/Sources/libMultiMarkdown/latex.c @@ -787,6 +787,39 @@ void mmd_export_token_latex(DString * out, const char * source, token * t, scrat case COLON: print_const(":"); break; + case CRITIC_ADD_OPEN: + print_const("{++"); + break; + case CRITIC_ADD_CLOSE: + print_const("++}"); + break; + case CRITIC_COM_OPEN: + print_const("{>>"); + break; + case CRITIC_COM_CLOSE: + print_const("<<}"); + break; + case CRITIC_DEL_OPEN: + print_const("{--"); + break; + case CRITIC_DEL_CLOSE: + print_const("--}"); + break; + case CRITIC_HI_OPEN: + print_const("{=="); + break; + case CRITIC_HI_CLOSE: + print_const("==}"); + break; + case CRITIC_SUB_OPEN: + print_const("{~~"); + break; + case CRITIC_SUB_DIV: + print_const("~>"); + break; + case CRITIC_SUB_CLOSE: + print_const("~~}"); + break; case DASH_M: if (!(scratch->extensions & EXT_SMART)) { print_token(t); From 630db16db5ede5051e03d4cc963adfcd761bd879 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Wed, 15 Mar 2017 10:39:48 -0400 Subject: [PATCH 25/29] CHANGE: Update documentation and test suite --- DevelopmentNotes/DevelopmentNotes.txt | 431 ++++++++++++++++++ QuickStart.epub => QuickStart/QuickStart.epub | Bin QuickStart.fodt => QuickStart/QuickStart.fodt | 0 QuickStart.html => QuickStart/QuickStart.html | 0 QuickStart.pdf => QuickStart/QuickStart.pdf | Bin QuickStart.txt => QuickStart/QuickStart.txt | 7 +- README.md | 350 -------------- templates/README.md.in | 350 -------------- .../{MMD6Tests => Disabled}/What Is MMD.text | 0 tests/MMD6Tests/Fuzz.fodt | 322 +++++++++++++ tests/MMD6Tests/Fuzz.html | 43 ++ tests/MMD6Tests/Fuzz.htmlc | 38 ++ tests/MMD6Tests/Fuzz.tex | 46 ++ tests/MMD6Tests/Fuzz.text | 40 ++ 14 files changed, 923 insertions(+), 704 deletions(-) create mode 100644 DevelopmentNotes/DevelopmentNotes.txt rename QuickStart.epub => QuickStart/QuickStart.epub (100%) rename QuickStart.fodt => QuickStart/QuickStart.fodt (100%) rename QuickStart.html => QuickStart/QuickStart.html (100%) rename QuickStart.pdf => QuickStart/QuickStart.pdf (100%) rename QuickStart.txt => QuickStart/QuickStart.txt (98%) rename tests/{MMD6Tests => Disabled}/What Is MMD.text (100%) create mode 100644 tests/MMD6Tests/Fuzz.fodt create mode 100644 tests/MMD6Tests/Fuzz.html create mode 100644 tests/MMD6Tests/Fuzz.htmlc create mode 100644 tests/MMD6Tests/Fuzz.tex create mode 100644 tests/MMD6Tests/Fuzz.text diff --git a/DevelopmentNotes/DevelopmentNotes.txt b/DevelopmentNotes/DevelopmentNotes.txt new file mode 100644 index 00000000..0dbb37ab --- /dev/null +++ b/DevelopmentNotes/DevelopmentNotes.txt @@ -0,0 +1,431 @@ +Title: MultiMarkdown v6 Development Notes +Author: Fletcher T. Penney +Date: 2017-03-14 +LaTeX Config: tufte-handout +Base Header Level: 3 + + +# Introduction # + +This document includes some notes on the development of MMD v6. Most of it +will be interesting only to other developers or those needing to choose the +absolute "best" MD implementation for their needs -- it is not required +reading to understand how the software works. + + +## Why a New Version? ## + +MultiMarkdown version 5 was released in November of 2015, but the codebase was +essentially the same as that of v4 -- and that was released in beta in April +of 2013. A few key things prompted work on a new version: + +* Accuracy -- MMD v4 and v5 were the most accurate versions yet, and a lot of +effort went into finding and resolving various edge cases. However, it began +to feel like a game of whack-a-mole where new bugs would creep in every time I +fixed an old one. The PEG began to feel rather convoluted in spots, even +though it did allow for a precise (if not always accurate) specification of +the grammar. + +* Performance -- "Back in the day" [peg-markdown] was one of the fastest +Markdown parsers around. MMD v3 was based on peg-markdown, and would leap- +frog with it in terms of performance. Then [CommonMark] was released, which +was a bit faster. Then a couple of years went by and CommonMark became *much* +faster -- in one of my test suites, MMD v 5.4.0 takes about 25 times longer to +process a long document than CommonMark 0.27.0. + +[peg-markdown]: https://github.com/jgm/peg-markdown +[CommonMark]: http://commonmark.org/ + +In the spring of 2016, I decided I wanted to rewrite MultiMarkdown from scratch, +building the parser myself rather than relying on a pre-rolled solution. (I +had been using [greg](https://github.com/ooc-lang/greg) to compile the PEG +into parser code. It worked well overall, but lacked some features I needed, +requiring a lot of workarounds.) + + +# First Attempt # + +My first attempt started by hand-crafting a parser that scanned through the +document a line at a time, deciding what to do with each line as it found +them. I used regex parsers made with [re2c](http://re2c.org/index.html) to +help classify each line, and then a separate parser layer to process groups of +lines into blocks. Initially this approach worked well, and was really +efficient. But I quickly began to code my way into a dead-end -- the strategy +was not elegant enough to handle things like nested lists, etc. + +One thing that did turn out well from the first attempt, however, was an +approach for handling `` and `` parsing. I've learned over the +years that this can be one of the hardest parts of coding accurately for +Markdown. There are many examples that are obvious to a person, but difficult +to properly "explain" how to parse to a computer. + +No solution is perfect, but I developed an approach that seems to accurately +handle a wide range of situations without a great deal of complexity: + +1. Scan the documents for asterisks (`*`). Each one will be handled one at a +time. + +2. Unlike brackets (`[` and `]`), an asterisk is "ambidextrous", in that it +may be able to open a matched pair of asterisks, close a pair, or both. For +example, in `foo *bar* foo`: + + 1. The first asterisk can open a pair, but not close one. + + 2. The second asterisk can close a pair, but not open one. + +3. So, once the asterisks have been identified, each has to be examined to +determine whether it can open/close/both. The algorithm is not that complex, +but I'll describe it in general terms. Check the code for more specifics. +This approach seems to work, but might still need some slight tweaking. In +the future, I'll codify this better in language rather than just in code. + + 1. If there is whitespace to the left of an asterisk, it can't close. + + 2. If there is whitespace or punctuation to the right it can't open. + + 3. "Runs" of asterisks, e.g. `**bar` are treated as a unit in terms of + looking left/right. + + 4. Asterisks inside a word are a bit trickier -- we look at the number of + asterisks before the word, the number in the current run, and the number + of asterisks after the word to determine which combinations, if any, are + permitted. + +4. Once all asterisks have been tagged as able to open/close/both, we proceed +through them in order: + + 1. When we encounter a tag that can close, we look to see if there is a + previous opener that has not been paired off. If so, pair the two and + remove the opener from the list of available asterisks. + + 2. When we encounter an opener, add it to the stack of available openers. + + 3. When encounter an asterisk that can do both, see if it can close an + existing opener. If not, then add it to the stack. + +5. After all tokens in the block have been paired, then we look for nesting +pairs of asterisks in order to create `` and `` sets. For +example, assume we have six asterisks wrapped around a word, three in front, +and three after. The asterisks are indicated with numbers: `123foo456`. We +proceed in the following manner: + + 1. Based on the pairing algorithm above, these asterisks would be paired as + follows, with matching asterisks sharing numbers -- `123foo321`. + + 2. Moving forwards, we come to asterisk "1". It is followed by an + asterisk, so we check to see if they should be grouped as a ``. + Since the "1" asterisks are wrapped immediately outside the "2" asterisks, + they are joined together. More than two pairs can't be joined, so we now + get the following -- `112foo211`, where the "11" represents the opening + and closing of a ``, and the "2" represents a ``. + +6. When matching a pair, any unclosed openers that are on the stack are +removed, preventing pairs from "crossing" or "intersecting". Pairs can wrap +around each other, e.g. `[(foo)]`, but not intersect like `[(foo])`. In the +second case, the brackets would close, removing the `(` from the stack. + +7. This same approach is used in all tokens that are matched in pairs-- +`[foo]`, `(foo)`, `_foo_`, etc. There's slightly more to it, but once you +figure out how to assign opening/closing ability, the rest is easy. By using +a stack to track available openers, it can be performed efficiently. + +In my testing, this approach has worked quite well. It handles all the basic +scenarios I've thrown at it, and all of the "basic" and "devious" edge cases I +have thought of (some of these don't necessarily have a "right" answer -- but +v6 gives consistency answers that seem as reasonable as any others to me). +There are also three more edge cases I've come up can still stump it, and +ironically they are handled correctly by most implementations. They just +don't follow the rules above. I'll continue to work on this. + +In the end, I scrapped this effort, but kept the lessons learned in the token +pairing algorithm. + + +# Second Attempt # + +I tried again this past Fall. This time, I approached the problem with lots +of reading. *Lots and lots* of reading -- tons of websites, computer science +journal articles, PhD theses, etc. Learned a lot about lexers, and a lot +about parsers, including hand-crafting vs using parser generators. In brief: + +1. I learned about the [Aho–Corasick algorithm], which is a great way to +efficiently search a string for multiple target strings at once. I used this +to create a custom lexer to identify tokens in a MultiMarkdown text document +(e.g. `*`, `[ `, `{++`, etc.). I learned a lot, and had a good time working +out the implementation. This code efficiently allowed me to break a string of +text into the tokens that mattered for Markdown parsing. + +2. However, in a few instances I really needed some features of regular +expressions to simplify more complex structures. After a quick bit of testing, +using re2c to create a tokenizer was just as efficient, and allowed me to +incorporate some regex functionality that simplified later parsing. I'll keep +the Aho-Corasick stuff around, and will probably experiment more with it +later. But I didn't need it for MMD now. `lexer.re` contains the source for +the tokenizer. + +[Aho–Corasick algorithm]: https://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_algorithm + +I looked long and hard for a way to simplify the parsing algorithm to try and +"touch" each token only once. Ideally, the program could step through each +token, and decide when to create a new block, when to pair things together, +etc. But I'm not convinced it's possible. Since Markdown's grammar varies +based on context, it seems to work best when handled in distinct phases: + +1. Tokenize the string to identify key sections of text. This includes line +breaks, allowing the text to be examined one line at time. + +2. Join series of lines together into blocks, such as paragraphs, code blocks, +lists, etc. + +3. The tokens inside each block can then be paired together to create more +complex syntax such as links, strong, emphasis, etc. + +To handle the block parsing, I started off using the [Aho-Corasick] code to +handle my first attempt. I had actually implemented some basic regex +functionality, and used that to group lines together to create blocks. But +this quickly fell apart in the face of more complex structures such as +recursive lists. After a lot of searching, and *tons* more reading, I +ultimately decided to use a parser generator to handle the task of group lines +into blocks. `parser.y` has the source for this, and it is processed by the +[lemon](http://www.hwaci.com/sw/lemon/) parser generator to create the actual +code. + +I chose to do this because hand-crafting the block parser would be complex. +The end result would likely be difficult to read and understand, which would +make it difficult to update later on. Using the parser generator allows me to +write things out in a way that can more easily be understood by a person. In +all likelihood, the performance is probably as good as anything I could do +anyway, if not better. + +Because lemon is a LALR(1) parser, it does require a bit of thinking ahead +about how to create the grammar used. But so far, it has been able to handle +everything I have thrown at it. + + +# Optimization # + +One of my goals for MMD 6 was performance. So I've paid attention to speed +along the way, and have tried to use a few tricks to keep things fast. Here +are some things I've learned along the way. In no particular order: + + +## Memory Allocation ## + +When parsing a long document, a *lot* of token structures are created. Each +one requires a small bit of memory to be allocated. In aggregate, that time +added up and slowed down performance. + +After reading for a bit, I ended up coming up with an approach that uses +larger chunks of memory. I allocate pools of of memory in large slabs for +smaller "objects"". For example, I allocate memory for 1024 tokens at a +single time, and then dole that memory out as needed. When the slab is empty, +a new one is allocated. This dramatically improved performance. + +When pairing tokens, I created a new stack for each block. I realized that an +empty stack didn't have any "leftover" cruft to interfere with re-use, so I +just used one for the entire document. Again a sizeable improvement in +performance from only allocating one object instead of many. When recursing +to a deeper level, the stack just gets deeper, but earlier levels aren't +modified. + +Speaking of tokens, I realized that the average document contains a lot of +single spaces (there's one between every two words I have written, for +example.) The vast majority of the time, these single spaces have no effect +on the output of Markdown documents. I changed my whitespace token search to +only flag runs of 2 or more spaces, dramatically reducing the number of +tokens. This gives the benefit of needing fewer memory allocations, and also +reduces the number of tokens that need to be processed later on. The only +downside is remember to check for a single space character in a few instances +where it matters. + + +## Proper input buffering ## + +When I first began last spring, I was amazed to see how much time was being +spent by MultiMarkdown simply reading the input file. Then I discovered it +was because I was reading it one character at a time. I switched to using a +buffered read approach and the time to read the file went to almost nothing. I +experimented with different buffer sizes, but they did not seem to make a +measurable difference. + + +## Output Buffering ## + +I experimented with different approaches to creating the output after parsing. +I tried printing directly to `stdout`, and even played with different +buffering settings. None of those seemed to work well, and all were slower +than using the `d_string` approach (formerly call `GString` in MMD 5). + + +## Fast Searches ## + +After getting basic Markdown functionality complete, I discovered during +testing that the time required to parse a document grew exponentially as the +document grew longer. Performance was on par with CommonMark for shorter +documents, but fell increasingly behind in larger tests. Time profiling found +that the culprit was searching for link definitions when they didn't exist. +My first approach was to keep a stack of used link definitions, and to iterate +through them when necessary. In long documents, this performs very poorly. +More research and I ended up using +[uthash](http://troydhanson.github.io/uthash/). This allows me to search for +a link (or footnote, etc.) by "name" rather than searching through an array. +This allowed me to get MMD's performance back to O(n), taking roughly twice as +much time to process a document that is twice as long. + + +## Efficient Utility Functions ## + +It is frequently necessary when parsing Markdown to check what sort of +character we are dealing with at a certain position -- a letter, whitespace, +punctuation, etc. I created a lookup table for this via `char_lookup.c` and +hard-coded it in `char.c`. These routines allow me to quickly, and +consistently, classify any byte within a document. This saved a lot of +programming time, and saved time tracking down bugs from handling things +slightly differently under different circumstances. I also suspect it +improved performance, but don't have the data to back it up. + + +## Testing While Writing ## + +I developed several chunks of code in parallel while creating MMD 6. The vast +majority of it was developed largely in a [test-driven development] approach. +The other code was largely created with extensive unit testing to accomplish +this. + +[test-driven development]: https://en.wikipedia.org/wiki/Test-driven_development + +MMD isn't particularly amenable to this approach at the small level, but +instead I relied more on integration testing with an ever-growing collection +of text files and the corresponding HTML files in the MMD 6 test suite. This +allowed me to ensure new features work properly and that old features aren't +broken. At this time, there are 29 text files in the test suite, and many +more to come. + + +## Other Lessons ## + +Some things that didn't do me any good.... + +I considered differences between using `malloc` and `calloc` when initializing +tokens. The time saved by using `malloc` was basically exactly offset by the +initial time required to initialize the token to default null values as +compared to using `calloc`. When trying `calloc` failed to help me out +(thinking that clearing a single slab in the object pool would be faster), I +stuck with `malloc` as it makes more sense to me in my workflow. + +I read a bit about [struct padding] and reordered some of my structs. It was +until later that I discovered the `-Wpadded` option, and it's not clear +whether my changes modified anything. Since the structs were being padded +automatically, there was no noticeable performance change, and I didn't have +the tools to measure whether I could have improved memory usage at all. Not +sure this would be worth the effort -- much lower hanging fruit available. + +[struct padding]: http://www.catb.org/esr/structure-packing/ + + +# Performance # + +Basic tests show that currently MMD 6 takes about 20-25% longer the CommonMark +0.27.0 to process long files (e.g. 0.2 MB). However, it is around 5% *faster* +than CommonMark when parsing a shorter file (27 kB) (measured by parsing the +same file 200 times over). This test suite is performed by using the Markdown +[syntax page], modified to avoid the use of the Setext header at the top. The +longer files tested are created by copying the same syntax page onto itself, +thereby doubling the length of the file with each iteration. + +The largest file I test is approximately 108 MB (4096 copies of the syntax +page). On my machine (2012 Mac mini with 2.3 GHz Intel Core i7, 16 GB RAM), +it takes approximately 4.4 seconds to parse with MMD 6 and 3.7 seconds with +CommonMark. MMD 6 processes approximately 25 MB/s on this test file. +CommonMark 0.27.0 gets about 29 MB/s on the same machine. + +There are some slight variations with the smaller test files (8-32 copies), +but overall the performance of both programs (MMD 6 and CommonMark) are +roughly linear as the test file gets bigger (double the file size and it takes +twice as long to parse, aka O(n)). + +Out of curiosity, I ran the same tests on the original Markdown.pl by Gruber +(v 1.0.2b8). It took approximately 178 seconds to parse 128 copies of the +file (3.4 MB) and was demonstrating quadratic performance characteristics +(double the file size and it takes 2^2 or 4 times longer to process, aka +O(n^2)). I didn't bother running it on larger versions of the test file. For +comparison, MMD 6 can process 128 copies in approximately 140 msec. + +Of note, the throughput speed drops when testing more complicated files +containing more advanced MultiMarkdown features, though it still seems to +maintain linear performance characteristics. A second test file is created by +concatenating all of the test suite files (including the Markdown syntax +file). In this case, MMD gets about 13 MB/s. CommonMark doesn't support +these additional features, so testing it with that file is not relevant. I +will work to see whether there are certain features in particular that are +more challenging and see whether they can be reworked to improve performance. + +As above, I have done some high level optimization of the parse strategy, but +I'm sure there's still a lot of room for further improvement to be made. +Suggestions welcome! + + +# Testing # + +## Test Suite ## + +The development of MMD v6 was heavily, but not absolutely, influenced by the +philosophy of test-driven development. While coding, I made use of test +suites to verify successful implementation of new features, to avoid +regression problems when adding new features, and to identify known edge cases +in need of proper handling. + +The test suite (located in `tests/MMD6Tests`) is a "living" collection of +documents that will continue to be updated as new bugs and edge cases are +identified. This helps make proper integration testing of the entire +application with every release. + + +## Fuzz Testing ## + +I was not familiar with the concept of [Fuzz Testing] +(https://en.wikipedia.org/wiki/Fuzzing) until a user mentioned something about +it to me a year or two ago. I had never used it before, but it seemed like a +good idea. I implement it in two ways. + +The first is that I created a simplified version of the line parser that +simply accepts various combinations of line type identifiers to see if they +would successfully parse. The line parser is responsible for taking a series +of line types (e.g. plain text, indented line, etc.) and determining what sort +of block they should become. The file `test/parser_text.y` is run through the +`lemon` program, compiled (with or without the `-DNDEBUG` flag) and then run. +It sequentially throws every combination of line types at the simplified line +parser to make sure that it doesn't choke. When I first did this, I found +several combinations of lines that did not pass. + +**NOTE**: This does not verify accurate parsing, simply that the parser does +not crash by an unacceptable combination of lines. + +The second form of fuzz testing I have started using more recently. This is +using the [American fuzzy lop](http://lcamtuf.coredump.cx/afl/) program to try +to find text input that crashes MMD. This works by taking sample input (e.g. +files from the test suite), modifying them slightly, and trying the modified +versions. Do this over and over and over, and some interesting edge cases are +sometimes identified. I have found some interesting edge cases this way. +Definitely a very useful tool! + + +## Unit Testing ## + +Some of the original development was done with unit testing in some other +tools I developed. This code formed the basis of a few parts of MMD. +Otherwise, it was hard to see how to really create very good unit tests for +the development of MMD. So there is really not much unit testing built into +the code or used during the development. + + + +[>MMD]: MultiMarkdown +[>MD]: Markdown + +[CriticMarkup]: http://criticmarkup.com/ + +[?PEG]: Parsing Expression Grammar + +[?AST]: Abstract Syntax Tree + diff --git a/QuickStart.epub b/QuickStart/QuickStart.epub similarity index 100% rename from QuickStart.epub rename to QuickStart/QuickStart.epub diff --git a/QuickStart.fodt b/QuickStart/QuickStart.fodt similarity index 100% rename from QuickStart.fodt rename to QuickStart/QuickStart.fodt diff --git a/QuickStart.html b/QuickStart/QuickStart.html similarity index 100% rename from QuickStart.html rename to QuickStart/QuickStart.html diff --git a/QuickStart.pdf b/QuickStart/QuickStart.pdf similarity index 100% rename from QuickStart.pdf rename to QuickStart/QuickStart.pdf diff --git a/QuickStart.txt b/QuickStart/QuickStart.txt similarity index 98% rename from QuickStart.txt rename to QuickStart/QuickStart.txt index 491975eb..81159351 100644 --- a/QuickStart.txt +++ b/QuickStart/QuickStart.txt @@ -202,10 +202,9 @@ older versions of the EPUB format, but other tools can convert to other document formats you need. Same goes for Amazon's ebook formats -- the [Calibre] program can also be used to interconvert between formats. -**NOTE: Because EPUB documents are binary files, MMD only creates them when -**run in batch mode (using the `-b\--batch` options). Otherwise, it simply -**outputs the HTML 5 file that would serve as the primary content for the -**EPUB. +**NOTE**: Because EPUB documents are binary files, MMD only creates them when +run in batch mode (using the `-b\--batch` options). Otherwise, it simply +outputs the HTML 5 file that would serve as the primary content for the EPUB. ## Fenced Code Blocks ## diff --git a/README.md b/README.md index 9c4863c1..3ce8774a 100644 --- a/README.md +++ b/README.md @@ -201,315 +201,6 @@ my experiences for those who are working on their own products. But first, some background... -### Why a New Version? ### - -MultiMarkdown version 5 was released in November of 2015, but the codebase was -essentially the same as that of v4 -- and that was released in beta in April -of 2013. A few key things prompted work on a new version: - -* Accuracy -- MMD v4 and v5 were the most accurate versions yet, and a lot of -effort went into finding and resolving various edge cases. However, it began -to feel like a game of whack-a-mole where new bugs would creep in every time I -fixed an old one. The PEG began to feel rather convoluted in spots, even -though it did allow for a precise (if not always accurate) specification of -the grammar. - -* Performance -- "Back in the day" [peg-markdown] was one of the fastest -Markdown parsers around. MMD v3 was based on peg-markdown, and would leap- -frog with it in terms of performance. Then [CommonMark] was released, which -was a bit faster. Then a couple of years went by and CommonMark became *much* -faster -- in one of my test suites, MMD v 5.4.0 takes about 25 times longer to -process a long document than CommonMark 0.27.0. - -[peg-markdown]: https://github.com/jgm/peg-markdown -[CommonMark]: http://commonmark.org/ - -Last spring, I decided I wanted to rewrite MultiMarkdown from scratch, -building the parser myself rather than relying on a pre-rolled solution. (I -had been using [greg](https://github.com/ooc-lang/greg) to compile the PEG -into parser code. It worked well overall, but lacked some features I needed, -requiring a lot of workarounds.) - - -## First Attempt ## - -My first attempt started by hand-crafting a parser that scanned through the -document a line at a time, deciding what to do with each line as it found -them. I used regex parsers made with [re2c](http://re2c.org/index.html) to -help classify each line, and then a separate parser layer to process groups of -lines into blocks. Initially this approach worked well, and was really -efficient. But I quickly began to code my way into a dead-end -- the strategy -was not elegant enough to handle things like nested lists, etc. - -One thing that did turn out well from the first attempt, however, was an -approach for handling `` and `` parsing. I've learned over the -years that this can be one of the hardest parts of coding accurately for -Markdown. There are many examples that are obvious to a person, but difficult -to properly "explain" how to parse to a computer. - -No solution is perfect, but I developed an approach that seems to accurately -handle a wide range of situations without a great deal of complexity: - -1. Scan the documents for asterisks (`*`). Each one will be handled one at a -time. - -2. Unlike brackets (`[` and `]`), an asterisk is "ambidextrous", in that it -may be able to open a matched pair of asterisks, close a pair, or both. For -example, in `foo *bar* foo`: - - 1. The first asterisk can open a pair, but not close one. - - 2. The second asterisk can close a pair, but not open one. - -3. So, once the asterisks have been identified, each has to be examined to -determine whether it can open/close/both. The algorithm is not that complex, -but I'll describe it in general terms. Check the code for more specifics. -This approach seems to work, but might still need some slight tweaking. In -the future, I'll codify this better in language rather than just in code. - - 1. If there is whitespace to the left of an asterisk, it can't close. - - 2. If there is whitespace or punctuation to the right it can't open. - - 3. "Runs" of asterisks, e.g. `**bar` are treated as a unit in terms of - looking left/right. - - 4. Asterisks inside a word are a bit trickier -- we look at the number of - asterisks before the word, the number in the current run, and the number - of asterisks after the word to determine which combinations, if any, are - permitted. - -4. Once all asterisks have been tagged as able to open/close/both, we proceed -through them in order: - - 1. When we encounter a tag that can close, we look to see if there is a - previous opener that has not been paired off. If so, pair the two and - remove the opener from the list of available asterisks. - - 2. When we encounter an opener, add it to the stack of available openers. - - 3. When encounter an asterisk that can do both, see if it can close an - existing opener. If not, then add it to the stack. - -5. After all tokens in the block have been paired, then we look for nesting -pairs of asterisks in order to create `` and `` sets. For -example, assume we have six asterisks wrapped around a word, three in front, -and three after. The asterisks are indicated with numbers: `123foo456`. We -proceed in the following manner: - - 1. Based on the pairing algorithm above, these asterisks would be paired as - follows, with matching asterisks sharing numbers -- `123foo321`. - - 2. Moving forwards, we come to asterisk "1". It is followed by an - asterisk, so we check to see if they should be grouped as a ``. - Since the "1" asterisks are wrapped immediately outside the "2" asterisks, - they are joined together. More than two pairs can't be joined, so we now - get the following -- `112foo211`, where the "11" represents the opening - and closing of a ``, and the "2" represents a ``. - -6. When matching a pair, any unclosed openers that are on the stack are -removed, preventing pairs from "crossing" or "intersecting". Pairs can wrap -around each other, e.g. `[(foo)]`, but not intersect like `[(foo])`. In the -second case, the brackets would close, removing the `(` from the stack. - -7. This same approach is used in all tokens that are matched in pairs-- -`[foo]`, `(foo)`, `_foo_`, etc. There's slightly more to it, but once you -figure out how to assign opening/closing ability, the rest is easy. By using -a stack to track available openers, it can be performed efficiently. - -In my testing, this approach has worked quite well. It handles all the basic -scenarios I've thrown at it, and all of the "basic" and "devious" edge cases I -have thought of (some of these don't necessarily have a "right" answer -- but -v6 gives consistency answers that seem as reasonable as any others to me). -There are also three more edge cases I've come up can still stump it, and -ironically they are handled correctly by most implementations. They just -don't follow the rules above. I'll continue to work on this. - -In the end, I scrapped this effort, but kept the lessons learned in the token -pairing algorithm. - - -## Second Attempt ## - -I tried again this past Fall. This time, I approached the problem with lots -of reading. *Lots and lots* of reading -- tons of websites, computer science -journal articles, PhD theses, etc. Learned a lot about lexers, and a lot -about parsers, including hand-crafting vs using parser generators. In brief: - -1. I learned about the [Aho–Corasick algorithm], which is a great way to -efficiently search a string for multiple target strings at once. I used this -to create a custom lexer to identify tokens in a MultiMarkdown text document -(e.g. `*`, `[ `, `{++`, etc.). I learned a lot, and had a good time working -out the implementation. This code efficiently allowed me to break a string of -text into the tokens that mattered for Markdown parsing. - -2. However, in a few instances I really needed some features of regular -expressions to simplify more complex structures. After a quick bit of testing, -using re2c to create a tokenizer was just as efficient, and allowed me to -incorporate some regex functionality that simplified later parsing. I'll keep -the Aho-Corasick stuff around, and will probably experiment more with it -later. But I didn't need it for MMD now. `lexer.re` contains the source for -the tokenizer. - -[Aho–Corasick algorithm]: https://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_algorithm - -I looked long and hard for a way to simplify the parsing algorithm to try and -"touch" each token only once. Ideally, the program could step through each -token, and decide when to create a new block, when to pair things together, -etc. But I'm not convinced it's possible. Since Markdown's grammar varies -based on context, it seems to work best when handled in distinct phases: - -1. Tokenize the string to identify key sections of text. This includes line -breaks, allowing the text to be examined one line at time. - -2. Join series of lines together into blocks, such as paragraphs, code blocks, -lists, etc. - -3. The tokens inside each block can then be paired together to create more -complex syntax such as links, strong, emphasis, etc. - -To handle the block parsing, I started off using the [Aho-Corasick] code to -handle my first attempt. I had actually implemented some basic regex -functionality, and used that to group lines together to create blocks. But -this quickly fell apart in the face of more complex structures such as -recursive lists. After a lot of searching, and *tons* more reading, I -ultimately decided to use a parser generator to handle the task of group lines -into blocks. `parser.y` has the source for this, and it is processed by the -[lemon](http://www.hwaci.com/sw/lemon/) parser generator to create the actual -code. - -I chose to do this because hand-crafting the block parser would be complex. -The end result would likely be difficult to read and understand, which would -make it difficult to update later on. Using the parser generator allows me to -write things out in a way that can more easily be understood by a person. In -all likelihood, the performance is probably as good as anything I could do -anyway, if not better. - -Because lemon is a LALR(1) parser, it does require a bit of thinking ahead -about how to create the grammar used. But so far, it has been able to handle -everything I have thrown at it. - - -## Optimization ## - -One of my goals for MMD 6 was performance. So I've paid attention to speed -along the way, and have tried to use a few tricks to keep things fast. Here -are some things I've learned along the way. In no particular order: - - -### Memory Allocation ### - -When parsing a long document, a *lot* of token structures are created. Each -one requires a small bit of memory to be allocated. In aggregate, that time -added up and slowed down performance. - -After reading for a bit, I ended up coming up with an approach that uses -larger chunks of memory. I allocate pools of of memory in large slabs for -smaller "objects"". For example, I allocate memory for 1024 tokens at a -single time, and then dole that memory out as needed. When the slab is empty, -a new one is allocated. This dramatically improved performance. - -When pairing tokens, I created a new stack for each block. I realized that an -empty stack didn't have any "leftover" cruft to interfere with re-use, so I -just used one for the entire document. Again a sizeable improvement in -performance from only allocating one object instead of many. When recursing -to a deeper level, the stack just gets deeper, but earlier levels aren't -modified. - -Speaking of tokens, I realized that the average document contains a lot of -single spaces (there's one between every two words I have written, for -example.) The vast majority of the time, these single spaces have no effect -on the output of Markdown documents. I changed my whitespace token search to -only flag runs of 2 or more spaces, dramatically reducing the number of -tokens. This gives the benefit of needing fewer memory allocations, and also -reduces the number of tokens that need to be processed later on. The only -downside is remember to check for a single space character in a few instances -where it matters. - - -### Proper input buffering ### - -When I first began last spring, I was amazed to see how much time was being -spent by MultiMarkdown simply reading the input file. Then I discovered it -was because I was reading it one character at a time. I switched to using a -buffered read approach and the time to read the file went to almost nothing. I -experimented with different buffer sizes, but they did not seem to make a -measurable difference. - - -### Output Buffering ### - -I experimented with different approaches to creating the output after parsing. -I tried printing directly to `stdout`, and even played with different -buffering settings. None of those seemed to work well, and all were slower -than using the `d_string` approach (formerly call `GString` in MMD 5). - - -### Fast Searches ### - -After getting basic Markdown functionality complete, I discovered during -testing that the time required to parse a document grew exponentially as the -document grew longer. Performance was on par with CommonMark for shorter -documents, but fell increasingly behind in larger tests. Time profiling found -that the culprit was searching for link definitions when they didn't exist. -My first approach was to keep a stack of used link definitions, and to iterate -through them when necessary. In long documents, this performs very poorly. -More research and I ended up using -[uthash](http://troydhanson.github.io/uthash/). This allows me to search for -a link (or footnote, etc.) by "name" rather than searching through an array. -This allowed me to get MMD's performance back to O(n), taking roughly twice as -much time to process a document that is twice as long. - - -### Efficient Utility Functions ### - -It is frequently necessary when parsing Markdown to check what sort of -character we are dealing with at a certain position -- a letter, whitespace, -punctuation, etc. I created a lookup table for this via `char_lookup.c` and -hard-coded it in `char.c`. These routines allow me to quickly, and -consistently, classify any byte within a document. This saved a lot of -programming time, and saved time tracking down bugs from handling things -slightly differently under different circumstances. I also suspect it -improved performance, but don't have the data to back it up. - - -### Testing While Writing ### - -I developed several chunks of code in parallel while creating MMD 6. The vast -majority of it was developed largely in a [test-driven development] approach. -The other code was largely created with extensive unit testing to accomplish -this. - -[test-driven development]: https://en.wikipedia.org/wiki/Test-driven_development - -MMD isn't particularly amenable to this approach at the small level, but -instead I relied more on integration testing with an ever-growing collection -of text files and the corresponding HTML files in the MMD 6 test suite. This -allowed me to ensure new features work properly and that old features aren't -broken. At this time, there are 29 text files in the test suite, and many -more to come. - - -### Other Lessons ### - -Some things that didn't do me any good.... - -I considered differences between using `malloc` and `calloc` when initializing -tokens. The time saved by using `malloc` was basically exactly offset by the -initial time required to initialize the token to default null values as -compared to using `calloc`. When trying `calloc` failed to help me out -(thinking that clearing a single slab in the object pool would be faster), I -stuck with `malloc` as it makes more sense to me in my workflow. - -I read a bit about [struct padding] and reordered some of my structs. It was -until later that I discovered the `-Wpadded` option, and it's not clear -whether my changes modified anything. Since the structs were being padded -automatically, there was no noticeable performance change, and I didn't have -the tools to measure whether I could have improved memory usage at all. Not -sure this would be worth the effort -- much lower hanging fruit available. - -[struct padding]: http://www.catb.org/esr/structure-packing/ - ## Differences in MultiMarkdown Itself ## @@ -627,47 +318,6 @@ There are a few at [syntax page]: https://daringfireball.net/projects/markdown/syntax -### Performance ### - -Basic tests show that currently MMD 6 takes about 20-25% longer the CommonMark -0.27.0 to process long files (e.g. 0.2 MB). However, it is around 5% *faster* -than CommonMark when parsing a shorter file (27 kB) (measured by parsing the -same file 200 times over). This test suite is performed by using the Markdown -[syntax page], modified to avoid the use of the Setext header at the top. The -longer files tested are created by copying the same syntax page onto itself, -thereby doubling the length of the file with each iteration. - -The largest file I test is approximately 108 MB (4096 copies of the syntax -page). On my machine (2012 Mac mini with 2.3 GHz Intel Core i7, 16 GB RAM), -it takes approximately 4.4 seconds to parse with MMD 6 and 3.7 seconds with -CommonMark. MMD 6 processes approximately 25 MB/s on this test file. -CommonMark 0.27.0 gets about 29 MB/s on the same machine. - -There are some slight variations with the smaller test files (8-32 copies), -but overall the performance of both programs (MMD 6 and CommonMark) are -roughly linear as the test file gets bigger (double the file size and it takes -twice as long to parse, aka O(n)). - -Out of curiosity, I ran the same tests on the original Markdown.pl by Gruber -(v 1.0.2b8). It took approximately 178 seconds to parse 128 copies of the -file (3.4 MB) and was demonstrating quadratic performance characteristics -(double the file size and it takes 2^2 or 4 times longer to process, aka -O(n^2)). I didn't bother running it on larger versions of the test file. For -comparison, MMD 6 can process 128 copies in approximately 140 msec. - -Of note, the throughput speed drops when testing more complicated files -containing more advanced MultiMarkdown features, though it still seems to -maintain linear performance characteristics. A second test file is created by -concatenating all of the test suite files (including the Markdown syntax -file). In this case, MMD gets about 13 MB/s. CommonMark doesn't support -these additional features, so testing it with that file is not relevant. I -will work to see whether there are certain features in particular that are -more challenging and see whether they can be reworked to improve performance. - -As above, I have done some high level optimization of the parse strategy, but -I'm sure there's still a lot of room for further improvement to be made. -Suggestions welcome! - ## License ## diff --git a/templates/README.md.in b/templates/README.md.in index e5056129..5e388ded 100644 --- a/templates/README.md.in +++ b/templates/README.md.in @@ -201,315 +201,6 @@ my experiences for those who are working on their own products. But first, some background... -### Why a New Version? ### - -MultiMarkdown version 5 was released in November of 2015, but the codebase was -essentially the same as that of v4 -- and that was released in beta in April -of 2013. A few key things prompted work on a new version: - -* Accuracy -- MMD v4 and v5 were the most accurate versions yet, and a lot of -effort went into finding and resolving various edge cases. However, it began -to feel like a game of whack-a-mole where new bugs would creep in every time I -fixed an old one. The PEG began to feel rather convoluted in spots, even -though it did allow for a precise (if not always accurate) specification of -the grammar. - -* Performance -- "Back in the day" [peg-markdown] was one of the fastest -Markdown parsers around. MMD v3 was based on peg-markdown, and would leap- -frog with it in terms of performance. Then [CommonMark] was released, which -was a bit faster. Then a couple of years went by and CommonMark became *much* -faster -- in one of my test suites, MMD v 5.4.0 takes about 25 times longer to -process a long document than CommonMark 0.27.0. - -[peg-markdown]: https://github.com/jgm/peg-markdown -[CommonMark]: http://commonmark.org/ - -Last spring, I decided I wanted to rewrite MultiMarkdown from scratch, -building the parser myself rather than relying on a pre-rolled solution. (I -had been using [greg](https://github.com/ooc-lang/greg) to compile the PEG -into parser code. It worked well overall, but lacked some features I needed, -requiring a lot of workarounds.) - - -## First Attempt ## - -My first attempt started by hand-crafting a parser that scanned through the -document a line at a time, deciding what to do with each line as it found -them. I used regex parsers made with [re2c](http://re2c.org/index.html) to -help classify each line, and then a separate parser layer to process groups of -lines into blocks. Initially this approach worked well, and was really -efficient. But I quickly began to code my way into a dead-end -- the strategy -was not elegant enough to handle things like nested lists, etc. - -One thing that did turn out well from the first attempt, however, was an -approach for handling `` and `` parsing. I've learned over the -years that this can be one of the hardest parts of coding accurately for -Markdown. There are many examples that are obvious to a person, but difficult -to properly "explain" how to parse to a computer. - -No solution is perfect, but I developed an approach that seems to accurately -handle a wide range of situations without a great deal of complexity: - -1. Scan the documents for asterisks (`*`). Each one will be handled one at a -time. - -2. Unlike brackets (`[` and `]`), an asterisk is "ambidextrous", in that it -may be able to open a matched pair of asterisks, close a pair, or both. For -example, in `foo *bar* foo`: - - 1. The first asterisk can open a pair, but not close one. - - 2. The second asterisk can close a pair, but not open one. - -3. So, once the asterisks have been identified, each has to be examined to -determine whether it can open/close/both. The algorithm is not that complex, -but I'll describe it in general terms. Check the code for more specifics. -This approach seems to work, but might still need some slight tweaking. In -the future, I'll codify this better in language rather than just in code. - - 1. If there is whitespace to the left of an asterisk, it can't close. - - 2. If there is whitespace or punctuation to the right it can't open. - - 3. "Runs" of asterisks, e.g. `**bar` are treated as a unit in terms of - looking left/right. - - 4. Asterisks inside a word are a bit trickier -- we look at the number of - asterisks before the word, the number in the current run, and the number - of asterisks after the word to determine which combinations, if any, are - permitted. - -4. Once all asterisks have been tagged as able to open/close/both, we proceed -through them in order: - - 1. When we encounter a tag that can close, we look to see if there is a - previous opener that has not been paired off. If so, pair the two and - remove the opener from the list of available asterisks. - - 2. When we encounter an opener, add it to the stack of available openers. - - 3. When encounter an asterisk that can do both, see if it can close an - existing opener. If not, then add it to the stack. - -5. After all tokens in the block have been paired, then we look for nesting -pairs of asterisks in order to create `` and `` sets. For -example, assume we have six asterisks wrapped around a word, three in front, -and three after. The asterisks are indicated with numbers: `123foo456`. We -proceed in the following manner: - - 1. Based on the pairing algorithm above, these asterisks would be paired as - follows, with matching asterisks sharing numbers -- `123foo321`. - - 2. Moving forwards, we come to asterisk "1". It is followed by an - asterisk, so we check to see if they should be grouped as a ``. - Since the "1" asterisks are wrapped immediately outside the "2" asterisks, - they are joined together. More than two pairs can't be joined, so we now - get the following -- `112foo211`, where the "11" represents the opening - and closing of a ``, and the "2" represents a ``. - -6. When matching a pair, any unclosed openers that are on the stack are -removed, preventing pairs from "crossing" or "intersecting". Pairs can wrap -around each other, e.g. `[(foo)]`, but not intersect like `[(foo])`. In the -second case, the brackets would close, removing the `(` from the stack. - -7. This same approach is used in all tokens that are matched in pairs-- -`[foo]`, `(foo)`, `_foo_`, etc. There's slightly more to it, but once you -figure out how to assign opening/closing ability, the rest is easy. By using -a stack to track available openers, it can be performed efficiently. - -In my testing, this approach has worked quite well. It handles all the basic -scenarios I've thrown at it, and all of the "basic" and "devious" edge cases I -have thought of (some of these don't necessarily have a "right" answer -- but -v6 gives consistency answers that seem as reasonable as any others to me). -There are also three more edge cases I've come up can still stump it, and -ironically they are handled correctly by most implementations. They just -don't follow the rules above. I'll continue to work on this. - -In the end, I scrapped this effort, but kept the lessons learned in the token -pairing algorithm. - - -## Second Attempt ## - -I tried again this past Fall. This time, I approached the problem with lots -of reading. *Lots and lots* of reading -- tons of websites, computer science -journal articles, PhD theses, etc. Learned a lot about lexers, and a lot -about parsers, including hand-crafting vs using parser generators. In brief: - -1. I learned about the [Aho–Corasick algorithm], which is a great way to -efficiently search a string for multiple target strings at once. I used this -to create a custom lexer to identify tokens in a MultiMarkdown text document -(e.g. `*`, `[ `, `{++`, etc.). I learned a lot, and had a good time working -out the implementation. This code efficiently allowed me to break a string of -text into the tokens that mattered for Markdown parsing. - -2. However, in a few instances I really needed some features of regular -expressions to simplify more complex structures. After a quick bit of testing, -using re2c to create a tokenizer was just as efficient, and allowed me to -incorporate some regex functionality that simplified later parsing. I'll keep -the Aho-Corasick stuff around, and will probably experiment more with it -later. But I didn't need it for MMD now. `lexer.re` contains the source for -the tokenizer. - -[Aho–Corasick algorithm]: https://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_algorithm - -I looked long and hard for a way to simplify the parsing algorithm to try and -"touch" each token only once. Ideally, the program could step through each -token, and decide when to create a new block, when to pair things together, -etc. But I'm not convinced it's possible. Since Markdown's grammar varies -based on context, it seems to work best when handled in distinct phases: - -1. Tokenize the string to identify key sections of text. This includes line -breaks, allowing the text to be examined one line at time. - -2. Join series of lines together into blocks, such as paragraphs, code blocks, -lists, etc. - -3. The tokens inside each block can then be paired together to create more -complex syntax such as links, strong, emphasis, etc. - -To handle the block parsing, I started off using the [Aho-Corasick] code to -handle my first attempt. I had actually implemented some basic regex -functionality, and used that to group lines together to create blocks. But -this quickly fell apart in the face of more complex structures such as -recursive lists. After a lot of searching, and *tons* more reading, I -ultimately decided to use a parser generator to handle the task of group lines -into blocks. `parser.y` has the source for this, and it is processed by the -[lemon](http://www.hwaci.com/sw/lemon/) parser generator to create the actual -code. - -I chose to do this because hand-crafting the block parser would be complex. -The end result would likely be difficult to read and understand, which would -make it difficult to update later on. Using the parser generator allows me to -write things out in a way that can more easily be understood by a person. In -all likelihood, the performance is probably as good as anything I could do -anyway, if not better. - -Because lemon is a LALR(1) parser, it does require a bit of thinking ahead -about how to create the grammar used. But so far, it has been able to handle -everything I have thrown at it. - - -## Optimization ## - -One of my goals for MMD 6 was performance. So I've paid attention to speed -along the way, and have tried to use a few tricks to keep things fast. Here -are some things I've learned along the way. In no particular order: - - -### Memory Allocation ### - -When parsing a long document, a *lot* of token structures are created. Each -one requires a small bit of memory to be allocated. In aggregate, that time -added up and slowed down performance. - -After reading for a bit, I ended up coming up with an approach that uses -larger chunks of memory. I allocate pools of of memory in large slabs for -smaller "objects"". For example, I allocate memory for 1024 tokens at a -single time, and then dole that memory out as needed. When the slab is empty, -a new one is allocated. This dramatically improved performance. - -When pairing tokens, I created a new stack for each block. I realized that an -empty stack didn't have any "leftover" cruft to interfere with re-use, so I -just used one for the entire document. Again a sizeable improvement in -performance from only allocating one object instead of many. When recursing -to a deeper level, the stack just gets deeper, but earlier levels aren't -modified. - -Speaking of tokens, I realized that the average document contains a lot of -single spaces (there's one between every two words I have written, for -example.) The vast majority of the time, these single spaces have no effect -on the output of Markdown documents. I changed my whitespace token search to -only flag runs of 2 or more spaces, dramatically reducing the number of -tokens. This gives the benefit of needing fewer memory allocations, and also -reduces the number of tokens that need to be processed later on. The only -downside is remember to check for a single space character in a few instances -where it matters. - - -### Proper input buffering ### - -When I first began last spring, I was amazed to see how much time was being -spent by MultiMarkdown simply reading the input file. Then I discovered it -was because I was reading it one character at a time. I switched to using a -buffered read approach and the time to read the file went to almost nothing. I -experimented with different buffer sizes, but they did not seem to make a -measurable difference. - - -### Output Buffering ### - -I experimented with different approaches to creating the output after parsing. -I tried printing directly to `stdout`, and even played with different -buffering settings. None of those seemed to work well, and all were slower -than using the `d_string` approach (formerly call `GString` in MMD 5). - - -### Fast Searches ### - -After getting basic Markdown functionality complete, I discovered during -testing that the time required to parse a document grew exponentially as the -document grew longer. Performance was on par with CommonMark for shorter -documents, but fell increasingly behind in larger tests. Time profiling found -that the culprit was searching for link definitions when they didn't exist. -My first approach was to keep a stack of used link definitions, and to iterate -through them when necessary. In long documents, this performs very poorly. -More research and I ended up using -[uthash](http://troydhanson.github.io/uthash/). This allows me to search for -a link (or footnote, etc.) by "name" rather than searching through an array. -This allowed me to get MMD's performance back to O(n), taking roughly twice as -much time to process a document that is twice as long. - - -### Efficient Utility Functions ### - -It is frequently necessary when parsing Markdown to check what sort of -character we are dealing with at a certain position -- a letter, whitespace, -punctuation, etc. I created a lookup table for this via `char_lookup.c` and -hard-coded it in `char.c`. These routines allow me to quickly, and -consistently, classify any byte within a document. This saved a lot of -programming time, and saved time tracking down bugs from handling things -slightly differently under different circumstances. I also suspect it -improved performance, but don't have the data to back it up. - - -### Testing While Writing ### - -I developed several chunks of code in parallel while creating MMD 6. The vast -majority of it was developed largely in a [test-driven development] approach. -The other code was largely created with extensive unit testing to accomplish -this. - -[test-driven development]: https://en.wikipedia.org/wiki/Test-driven_development - -MMD isn't particularly amenable to this approach at the small level, but -instead I relied more on integration testing with an ever-growing collection -of text files and the corresponding HTML files in the MMD 6 test suite. This -allowed me to ensure new features work properly and that old features aren't -broken. At this time, there are 29 text files in the test suite, and many -more to come. - - -### Other Lessons ### - -Some things that didn't do me any good.... - -I considered differences between using `malloc` and `calloc` when initializing -tokens. The time saved by using `malloc` was basically exactly offset by the -initial time required to initialize the token to default null values as -compared to using `calloc`. When trying `calloc` failed to help me out -(thinking that clearing a single slab in the object pool would be faster), I -stuck with `malloc` as it makes more sense to me in my workflow. - -I read a bit about [struct padding] and reordered some of my structs. It was -until later that I discovered the `-Wpadded` option, and it's not clear -whether my changes modified anything. Since the structs were being padded -automatically, there was no noticeable performance change, and I didn't have -the tools to measure whether I could have improved memory usage at all. Not -sure this would be worth the effort -- much lower hanging fruit available. - -[struct padding]: http://www.catb.org/esr/structure-packing/ - ## Differences in MultiMarkdown Itself ## @@ -627,47 +318,6 @@ There are a few at [syntax page]: https://daringfireball.net/projects/markdown/syntax -### Performance ### - -Basic tests show that currently MMD 6 takes about 20-25% longer the CommonMark -0.27.0 to process long files (e.g. 0.2 MB). However, it is around 5% *faster* -than CommonMark when parsing a shorter file (27 kB) (measured by parsing the -same file 200 times over). This test suite is performed by using the Markdown -[syntax page], modified to avoid the use of the Setext header at the top. The -longer files tested are created by copying the same syntax page onto itself, -thereby doubling the length of the file with each iteration. - -The largest file I test is approximately 108 MB (4096 copies of the syntax -page). On my machine (2012 Mac mini with 2.3 GHz Intel Core i7, 16 GB RAM), -it takes approximately 4.4 seconds to parse with MMD 6 and 3.7 seconds with -CommonMark. MMD 6 processes approximately 25 MB/s on this test file. -CommonMark 0.27.0 gets about 29 MB/s on the same machine. - -There are some slight variations with the smaller test files (8-32 copies), -but overall the performance of both programs (MMD 6 and CommonMark) are -roughly linear as the test file gets bigger (double the file size and it takes -twice as long to parse, aka O(n)). - -Out of curiosity, I ran the same tests on the original Markdown.pl by Gruber -(v 1.0.2b8). It took approximately 178 seconds to parse 128 copies of the -file (3.4 MB) and was demonstrating quadratic performance characteristics -(double the file size and it takes 2^2 or 4 times longer to process, aka -O(n^2)). I didn't bother running it on larger versions of the test file. For -comparison, MMD 6 can process 128 copies in approximately 140 msec. - -Of note, the throughput speed drops when testing more complicated files -containing more advanced MultiMarkdown features, though it still seems to -maintain linear performance characteristics. A second test file is created by -concatenating all of the test suite files (including the Markdown syntax -file). In this case, MMD gets about 13 MB/s. CommonMark doesn't support -these additional features, so testing it with that file is not relevant. I -will work to see whether there are certain features in particular that are -more challenging and see whether they can be reworked to improve performance. - -As above, I have done some high level optimization of the parse strategy, but -I'm sure there's still a lot of room for further improvement to be made. -Suggestions welcome! - ## License ## diff --git a/tests/MMD6Tests/What Is MMD.text b/tests/Disabled/What Is MMD.text similarity index 100% rename from tests/MMD6Tests/What Is MMD.text rename to tests/Disabled/What Is MMD.text diff --git a/tests/MMD6Tests/Fuzz.fodt b/tests/MMD6Tests/Fuzz.fodt new file mode 100644 index 00000000..b0be3a5f --- /dev/null +++ b/tests/MMD6Tests/Fuzz.fodt @@ -0,0 +1,322 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Bibliography + + + + Fuzz Testing + + + +Collection of test cases identified by American fuzzy lop. + +>bar~~} + + + + +list + + +tems + + + +:Escapes + +[>MM]: MultiMarkdown + +foo1 + +foo2 + +]: And aÄe footn.IThi1. $ + +[MMD]: + +f F O O (o o) f o o + + + + +foo + + + foo + + + +(This must be at end of file without trailing newline) + +A + + + diff --git a/tests/MMD6Tests/Fuzz.html b/tests/MMD6Tests/Fuzz.html new file mode 100644 index 00000000..b625f30a --- /dev/null +++ b/tests/MMD6Tests/Fuzz.html @@ -0,0 +1,43 @@ + + + + + Fuzz Testing + + + +

Collection of test cases identified by American fuzzy lop.

+ +

>bar~~}

+ +
    +
  • list
  • +
  • tems
  • +
+ +

:Escapes

+ +

[>MM]: MultiMarkdown

+ +

foo1

+ +

foo2

+ +

]: And aÄe footn.IThi1. $

+ +

[MMD]:

+ +

f F O O (o o) f o o

+ +
    +
  • foo
  • +
  • Â foo
  • +
+ +

(This must be at end of file without trailing newline)

+ +

A

+ + + + diff --git a/tests/MMD6Tests/Fuzz.htmlc b/tests/MMD6Tests/Fuzz.htmlc new file mode 100644 index 00000000..88d697b1 --- /dev/null +++ b/tests/MMD6Tests/Fuzz.htmlc @@ -0,0 +1,38 @@ +

Title: Fuzz Testing +latex config: article

+ +

Collection of test cases identified by American fuzzy lop.

+ +

û~~foo~>bar~~}

+ +
    +
  • list
  • +
  • tems
  • +
+ +

:Escapes [escaped]

+ +

[>MM]: MultiMarkdown

+ +

[?terí¢ıı[?term]: A term to be defined.

+ +

foo1

+ +

foo2

+ +

]: And aÄe footn.I^Thi1. $

+ +

[MMD]:

+ +

f o o f o o

+ +

[> o o]: F O O

+ +
    +
  • foo
  • +
  • Â foo
  • +
+ +

(This must be at end of file without trailing newline)

+ +

A

diff --git a/tests/MMD6Tests/Fuzz.tex b/tests/MMD6Tests/Fuzz.tex new file mode 100644 index 00000000..e0ba52dd --- /dev/null +++ b/tests/MMD6Tests/Fuzz.tex @@ -0,0 +1,46 @@ +\input{mmd6-article-leader} +\def\mytitle{Fuzz Testing} +\newacronym{o o}{o o}{F O O} + +\input{mmd6-article-begin} + +Collection of test cases identified by \href{http://lcamtuf.coredump.cx/afl/}{American fuzzy lop}\footnote{\href{http://lcamtuf.coredump.cx/afl/}{http:\slash \slash lcamtuf.coredump.cx\slash afl\slash }}. + +>bar~~} + +\begin{itemize} +\item{} list + +\item{} tems + +\end{itemize} + +\chapter{:Escapes } +\label{escaped} + +[>MM]: MultiMarkdown + +foo1 (\autoref{ba\}) + +foo2 (\autoref{bar}) + +]: And aÄe footn.I\textsuperscript{Thi1}. \$ + +[MMD]: + +f \gls{o o} f \gls{o o} + +\begin{itemize} +\item{} foo + +\item{}  foo + +\end{itemize} + +(This must be at end of file without trailing newline) + +\part{A} +\label{a} + +\input{mmd6-article-footer} +\end{document} diff --git a/tests/MMD6Tests/Fuzz.text b/tests/MMD6Tests/Fuzz.text new file mode 100644 index 00000000..67e0fc30 --- /dev/null +++ b/tests/MMD6Tests/Fuzz.text @@ -0,0 +1,40 @@ +Title: Fuzz Testing +latex config: article + +Collection of test cases identified by [American fuzzy lop](http://lcamtuf.coredump.cx/afl/). + +û~~foo~>bar~~} + +* list +* tems + +:Escapes [escaped] +---------------- + +[>MM\]: MultiMarkdown + +[?terí¢ıı[?term]: A term to be defined. + +[foo1] + +[foo2] + +[foo1]: #ba\ +[foo2]: #bar + +]: And aÄe footn.I^Thi1. \$ + +[MMD]: + +f o o f o o + +[> o o]: F O O + +* foo +*   foo + + + +(This must be at end of file without trailing newline) + +# A \ No newline at end of file From c8d3ff055c220ef12e22bcf013d05132456a9ce8 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Wed, 15 Mar 2017 11:35:06 -0400 Subject: [PATCH 26/29] CHANGED: Update documentation --- DevelopmentNotes/DevelopmentNotes.epub | Bin 0 -> 13645 bytes DevelopmentNotes/DevelopmentNotes.fodt | 1311 ++++++++++++++++++++++++ DevelopmentNotes/DevelopmentNotes.html | 599 +++++++++++ DevelopmentNotes/DevelopmentNotes.pdf | Bin 0 -> 103994 bytes DevelopmentNotes/DevelopmentNotes.txt | 184 +++- README.md | 305 +----- templates/README.md.in | 305 +----- 7 files changed, 2198 insertions(+), 506 deletions(-) create mode 100644 DevelopmentNotes/DevelopmentNotes.epub create mode 100644 DevelopmentNotes/DevelopmentNotes.fodt create mode 100644 DevelopmentNotes/DevelopmentNotes.html create mode 100644 DevelopmentNotes/DevelopmentNotes.pdf diff --git a/DevelopmentNotes/DevelopmentNotes.epub b/DevelopmentNotes/DevelopmentNotes.epub new file mode 100644 index 0000000000000000000000000000000000000000..1c2e6680623101d2a8162b0fadd025cdb62116cc GIT binary patch literal 13645 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 literal 0 HcmV?d00001 diff --git a/DevelopmentNotes/DevelopmentNotes.fodt b/DevelopmentNotes/DevelopmentNotes.fodt new file mode 100644 index 00000000..092949d3 --- /dev/null +++ b/DevelopmentNotes/DevelopmentNotes.fodt @@ -0,0 +1,1311 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Bibliography + + + + MultiMarkdown v6 Development Notes + Fletcher T. Penney + 2017-03-14 + + + +Introduction + +This document includes some notes on the development of MultiMarkdown (MMD) v6. Most of it +will be interesting only to other developers or those needing to choose the +absolute “best” Markdown (MD) implementation for their needs – it is not required +reading to understand how the software works. + +Why a New Version? + +MultiMarkdown version 5 was released in November of 2015, but the codebase was +essentially the same as that of v4 – and that was released in beta in April +of 2013. A few key things prompted work on a new version: + + + +Accuracy – MMD v4 and v5 were the most accurate versions yet, and a lot of +effort went into finding and resolving various edge cases. However, it began +to feel like a game of whack-a-mole where new bugs would creep in every time I +fixed an old one. The PEGParsing Expression Grammar https://en.wikipedia.org/wiki/Parsing_expression_grammar began to feel rather convoluted in spots, even +though it did allow for a precise (if not always accurate) specification of +the grammar. + + +Performance – “Back in the day” peg-markdown was one of the fastest +Markdown parsers around. MMD v3 was based on peg-markdown, and would leap- +frog with it in terms of performance. Then CommonMark was released, which +was a bit faster. Then a couple of years went by and CommonMark became much +faster – in one of my test suites, MMD v 5.4.0 takes about 25 times longer to +process a long document than CommonMark 0.27.0. + + + +In the spring of 2016, I decided I wanted to rewrite MultiMarkdown from scratch, +building the parser myself rather than relying on a pre-rolled solution. (I +had been using greg to compile the PEG +into parser code. It worked well overall, but lacked some features I needed, +requiring a lot of workarounds.) + +First Attempt + +My first attempt started by hand-crafting a parser that scanned through the +document a line at a time, deciding what to do with each line as it found +them. I used regex parsers made with re2c to +help classify each line, and then a separate parser layer to process groups of +lines into blocks. Initially this approach worked well, and was really +efficient. But I quickly began to code my way into a dead-end – the strategy +was not elegant enough to handle things like nested lists, etc. + +One thing that did turn out well from the first attempt, however, was an +approach for handling <emph> and <strong> parsing. I’ve learned over the +years that this can be one of the hardest parts of coding accurately for +Markdown. There are many examples that are obvious to a person, but difficult +to properly “explain” how to parse to a computer. + +No solution is perfect, but I developed an approach that seems to accurately +handle a wide range of situations without a great deal of complexity: + + + +Scan the documents for asterisks (*). Each one will be handled one at a +time. + + +Unlike brackets ([ and ]), an asterisk is “ambidextrous”, in that it +may be able to open a matched pair of asterisks, close a pair, or both. For +example, in foo *bar* foo: + + + +The first asterisk can open a pair, but not close one. + + +The second asterisk can close a pair, but not open one. + + + + +So, once the asterisks have been identified, each has to be examined to +determine whether it can open/close/both. The algorithm is not that complex, +but I’ll describe it in general terms. Check the code for more specifics. +This approach seems to work, but might still need some slight tweaking. In +the future, I’ll codify this better in language rather than just in code. + + + +If there is whitespace to the left of an asterisk, it can’t close. + + +If there is whitespace or punctuation to the right it can’t open. + + +“Runs” of asterisks, e.g. **bar are treated as a unit in terms of +looking left/right. + + +Asterisks inside a word are a bit trickier – we look at the number of +asterisks before the word, the number in the current run, and the number +of asterisks after the word to determine which combinations, if any, are +permitted. + + + + +Once all asterisks have been tagged as able to open/close/both, we proceed +through them in order: + + + +When we encounter a tag that can close, we look to see if there is a +previous opener that has not been paired off. If so, pair the two and +remove the opener from the list of available asterisks. + + +When we encounter an opener, add it to the stack of available openers. + + +When encounter an asterisk that can do both, see if it can close an +existing opener. If not, then add it to the stack. + + + + +After all tokens in the block have been paired, then we look for nesting +pairs of asterisks in order to create <emph> and <strong> sets. For +example, assume we have six asterisks wrapped around a word, three in front, +and three after. The asterisks are indicated with numbers: 123foo456. We +proceed in the following manner: + + + +Based on the pairing algorithm above, these asterisks would be paired as +follows, with matching asterisks sharing numbers – 123foo321. + + +Moving forwards, we come to asterisk “1”. It is followed by an +asterisk, so we check to see if they should be grouped as a <strong>. +Since the “1” asterisks are wrapped immediately outside the “2” asterisks, +they are joined together. More than two pairs can’t be joined, so we now +get the following – 112foo211, where the “11” represents the opening +and closing of a <strong>, and the “2” represents a <emph>. + + + + +When matching a pair, any unclosed openers that are on the stack are +removed, preventing pairs from “crossing” or “intersecting”. Pairs can wrap +around each other, e.g. [(foo)], but not intersect like [(foo]). In the +second case, the brackets would close, removing the ( from the stack. + + +This same approach is used in all tokens that are matched in pairs– +[foo], (foo), _foo_, etc. There’s slightly more to it, but once you +figure out how to assign opening/closing ability, the rest is easy. By using +a stack to track available openers, it can be performed efficiently. + + + +In my testing, this approach has worked quite well. It handles all the basic +scenarios I’ve thrown at it, and all of the “basic” and “devious” edge cases I +have thought of (some of these don’t necessarily have a “right” answer – but +v6 gives consistency answers that seem as reasonable as any others to me). +There are also three more edge cases I’ve come up can still stump it, and +ironically they are handled correctly by most implementations. They just +don’t follow the rules above. I’ll continue to work on this. + +In the end, I scrapped this effort, but kept the lessons learned in the token +pairing algorithm. + +Second Attempt + +I tried again this past Fall. This time, I approached the problem with lots +of reading. Lots and lots of reading – tons of websites, computer science +journal articles, PhD theses, etc. Learned a lot about lexers, and a lot +about parsers, including hand-crafting vs using parser generators. In brief: + + + +I learned about the Aho–Corasick algorithm, which is a great way to +efficiently search a string for multiple target strings at once. I used this +to create a custom lexer to identify tokens in a MultiMarkdown text document +(e.g. *, [, {++, etc.). I learned a lot, and had a good time working +out the implementation. This code efficiently allowed me to break a string of +text into the tokens that mattered for Markdown parsing. + + +However, in a few instances I really needed some features of regular +expressions to simplify more complex structures. After a quick bit of testing, +using re2c to create a tokenizer was just as efficient, and allowed me to +incorporate some regex functionality that simplified later parsing. I’ll keep +the Aho-Corasick stuff around, and will probably experiment more with it +later. But I didn’t need it for MMD now. lexer.re contains the source for +the tokenizer. + + + +I looked long and hard for a way to simplify the parsing algorithm to try and +“touch” each token only once. Ideally, the program could step through each +token, and decide when to create a new block, when to pair things together, +etc. But I’m not convinced it’s possible. Since Markdown’s grammar varies +based on context, it seems to work best when handled in distinct phases: + + + +Tokenize the string to identify key sections of text. This includes line +breaks, allowing the text to be examined one line at time. + + +Join series of lines together into blocks, such as paragraphs, code blocks, +lists, etc. + + +The tokens inside each block can then be paired together to create more +complex syntax such as links, strong, emphasis, etc. + + + +To handle the block parsing, I started off using the Aho-Corasick code to +handle my first attempt. I had actually implemented some basic regex +functionality, and used that to group lines together to create blocks. But +this quickly fell apart in the face of more complex structures such as +recursive lists. After a lot of searching, and tons more reading, I +ultimately decided to use a parser generator to handle the task of group lines +into blocks. parser.y has the source for this, and it is processed by the +lemon parser generator to create the actual +code. + +I chose to do this because hand-crafting the block parser would be complex. +The end result would likely be difficult to read and understand, which would +make it difficult to update later on. Using the parser generator allows me to +write things out in a way that can more easily be understood by a person. In +all likelihood, the performance is probably as good as anything I could do +anyway, if not better. + +Because lemon is a LALR(1) parser, it does require a bit of thinking ahead +about how to create the grammar used. But so far, it has been able to handle +everything I have thrown at it. + +Optimization + +One of my goals for MMD 6 was performance. So I’ve paid attention to speed +along the way, and have tried to use a few tricks to keep things fast. Here +are some things I’ve learned along the way. In no particular order: + +Memory Allocation + +When parsing a long document, a lot of token structures are created. Each +one requires a small bit of memory to be allocated. In aggregate, that time +added up and slowed down performance. + +After reading for a bit, I ended up coming up with an approach that uses +larger chunks of memory. I allocate pools of of memory in large slabs for +smaller “objects”". For example, I allocate memory for 1024 tokens at a +single time, and then dole that memory out as needed. When the slab is empty, +a new one is allocated. This dramatically improved performance. + +When pairing tokens, I created a new stack for each block. I realized that an +empty stack didn’t have any “leftover” cruft to interfere with re-use, so I +just used one for the entire document. Again a sizeable improvement in +performance from only allocating one object instead of many. When recursing +to a deeper level, the stack just gets deeper, but earlier levels aren’t +modified. + +Speaking of tokens, I realized that the average document contains a lot of +single spaces (there’s one between every two words I have written, for +example.) The vast majority of the time, these single spaces have no effect +on the output of Markdown documents. I changed my whitespace token search to +only flag runs of 2 or more spaces, dramatically reducing the number of +tokens. This gives the benefit of needing fewer memory allocations, and also +reduces the number of tokens that need to be processed later on. The only +downside is remember to check for a single space character in a few instances +where it matters. + +Proper input buffering + +When I first began last spring, I was amazed to see how much time was being +spent by MultiMarkdown simply reading the input file. Then I discovered it +was because I was reading it one character at a time. I switched to using a +buffered read approach and the time to read the file went to almost nothing. I +experimented with different buffer sizes, but they did not seem to make a +measurable difference. + +Output Buffering + +I experimented with different approaches to creating the output after parsing. +I tried printing directly to stdout, and even played with different +buffering settings. None of those seemed to work well, and all were slower +than using the d_string approach (formerly call GString in MMD 5). + +Fast Searches + +After getting basic Markdown functionality complete, I discovered during +testing that the time required to parse a document grew exponentially as the +document grew longer. Performance was on par with CommonMark for shorter +documents, but fell increasingly behind in larger tests. Time profiling found +that the culprit was searching for link definitions when they didn’t exist. +My first approach was to keep a stack of used link definitions, and to iterate +through them when necessary. In long documents, this performs very poorly. +More research and I ended up using +uthash. This allows me to search for +a link (or footnote, etc.) by “name” rather than searching through an array. +This allowed me to get MMD’s performance back to O(n), taking roughly twice as +much time to process a document that is twice as long. + +Efficient Utility Functions + +It is frequently necessary when parsing Markdown to check what sort of +character we are dealing with at a certain position – a letter, whitespace, +punctuation, etc. I created a lookup table for this via char_lookup.c and +hard-coded it in char.c. These routines allow me to quickly, and +consistently, classify any byte within a document. This saved a lot of +programming time, and saved time tracking down bugs from handling things +slightly differently under different circumstances. I also suspect it +improved performance, but don’t have the data to back it up. + +Testing While Writing + +I developed several chunks of code in parallel while creating MMD 6. The vast +majority of it was developed largely in a test-driven development approach. +The other code was largely created with extensive unit testing to accomplish +this. + +MMD isn’t particularly amenable to this approach at the small level, but +instead I relied more on integration testing with an ever-growing collection +of text files and the corresponding HTML files in the MMD 6 test suite. This +allowed me to ensure new features work properly and that old features aren’t +broken. At this time, there are 29 text files in the test suite, and many +more to come. + +Other Lessons + +Some things that didn’t do me any good…. + +I considered differences between using malloc and calloc when initializing +tokens. The time saved by using malloc was basically exactly offset by the +initial time required to initialize the token to default null values as +compared to using calloc. When trying calloc failed to help me out +(thinking that clearing a single slab in the object pool would be faster), I +stuck with malloc as it makes more sense to me in my workflow. + +I read a bit about struct padding and reordered some of my structs. It was +until later that I discovered the -Wpadded option, and it’s not clear +whether my changes modified anything. Since the structs were being padded +automatically, there was no noticeable performance change, and I didn’t have +the tools to measure whether I could have improved memory usage at all. Not +sure this would be worth the effort – much lower hanging fruit available. + +Performance + +Basic tests show that currently MMD 6 takes about 20–25% longer the CommonMark +0.27.0 to process long files (e.g. 0.2 MB). However, it is around 5% faster +than CommonMark when parsing a shorter file (27 kB) (measured by parsing the +same file 200 times over). This test suite is performed by using the Markdown +[syntax page], modified to avoid the use of the Setext header at the top. The +longer files tested are created by copying the same syntax page onto itself, +thereby doubling the length of the file with each iteration. + +The largest file I test is approximately 108 MB (4096 copies of the syntax +page). On my machine (2012 Mac mini with 2.3 GHz Intel Core i7, 16 GB RAM), +it takes approximately 4.4 seconds to parse with MMD 6 and 3.7 seconds with +CommonMark. MMD 6 processes approximately 25 MB/s on this test file. +CommonMark 0.27.0 gets about 29 MB/s on the same machine. + +There are some slight variations with the smaller test files (8–32 copies), +but overall the performance of both programs (MMD 6 and CommonMark) are +roughly linear as the test file gets bigger (double the file size and it takes +twice as long to parse, aka O(n)). + +Out of curiosity, I ran the same tests on the original Markdown.pl by Gruber +(v 1.0.2b8). It took approximately 178 seconds to parse 128 copies of the +file (3.4 MB) and was demonstrating quadratic performance characteristics +(double the file size and it takes 22 or 4 times longer to process, aka +O(n2)). I didn’t bother running it on larger versions of the test file. For +comparison, MMD 6 can process 128 copies in approximately 140 msec. + +Of note, the throughput speed drops when testing more complicated files +containing more advanced MultiMarkdown features, though it still seems to +maintain linear performance characteristics. A second test file is created by +concatenating all of the test suite files (including the Markdown syntax +file). In this case, MMD gets about 13 MB/s. CommonMark doesn’t support +these additional features, so testing it with that file is not relevant. I +will work to see whether there are certain features in particular that are +more challenging and see whether they can be reworked to improve performance. + +As above, I have done some high level optimization of the parse strategy, but +I’m sure there’s still a lot of room for further improvement to be made. +Suggestions welcome! + +Testing + +Test Suite + +The development of MMD v6 was heavily, but not absolutely, influenced by the +philosophy of test-driven development. While coding, I made use of test +suites to verify successful implementation of new features, to avoid +regression problems when adding new features, and to identify known edge cases +in need of proper handling. + +The test suite (located in tests/MMD6Tests) is a “living” collection of +documents that will continue to be updated as new bugs and edge cases are +identified. This helps make proper integration testing of the entire +application with every release. + +Fuzz Testing + +I was not familiar with the concept of Fuzz Testing +(https://en.wikipedia.org/wiki/Fuzzing) until a user mentioned something about +it to me a year or two ago. I had never used it before, but it seemed like a +good idea. I implement it in two ways. + +The first is that I created a simplified version of the line parser that +simply accepts various combinations of line type identifiers to see if they +would successfully parse. The line parser is responsible for taking a series +of line types (e.g. plain text, indented line, etc.) and determining what sort +of block they should become. The file test/parser_text.y is run through the +lemon program, compiled (with or without the -DNDEBUG flag) and then run. +It sequentially throws every combination of line types at the simplified line +parser to make sure that it doesn’t choke. When I first did this, I found +several combinations of lines that did not pass. + +NOTE: This does not verify accurate parsing, simply that the parser does +not crash by an unacceptable combination of lines. + +The second form of fuzz testing I have started using more recently. This is +using the American fuzzy lop program to try +to find text input that crashes MMD. This works by taking sample input (e.g. +files from the test suite), modifying them slightly, and trying the modified +versions. Do this over and over and over, and some interesting edge cases are +sometimes identified. I have found some interesting edge cases this way. +Definitely a very useful tool! + +Unit Testing + +Some of the original development was done with unit testing in some other +tools I developed. This code formed the basis of a few parts of MMD. +Otherwise, it was hard to see how to really create very good unit tests for +the development of MMD. So there is really not much unit testing built into +the code or used during the development. + +Changelog + + + +2017–03–13 – v 6.0.0-b2: + + + + +ADDED: Add CriticMarkup preprocessor that works across empty lines when accepting/rejecting markup + + + +ADDED: Add back the mmd6 latex title file + + + +ADDED: Basic EPUB 3 support – uses ‘miniz’ library to zip creation + + + +ADDED: Update QuickStart and EPUB code + + + +CHANGED: Update QuickStart guide + + + +CHANGED: Update test suite + + + +FIXED: Don't duplicate LaTeX glossary definitions + + + +FIXED: Fix abbreviations in ODF; Improve test suite + + + +FIXED: Improve glossaries and abbreviations; Update QuickStart + + + +FIXED: Tidy up some compiler warnings in code + + +FIXED: Use custom UUID code to minimize external dependencies + + + + +2017–03–09 – v 6.0.0-b1: + + + + +ADDED: Add French translations; fix typo in German + + + +ADDED: Add Quick Start guide + + + +ADDED: Add functionality to automatically identify abbreviations and glossary terms in source + + + +ADDED: Improve LaTeX configuration files + + + +ADDED: Update German translations + + + +ADDED: Use native ODF table of contents instead of a manual list + + + +ADDED: Use native command for table of contents in LaTeX + + + +CHANGED: Bring HTML and ODF into line with LaTeX as to output of abbreviatinos on first and subsequent uses + + + +CHANGED: Slight performance tweak + + + +CHANGED: Update German test suite + + + +FIXED: Allow {{TOC}} in latex verbatim + + + +FIXED: Don't free token_pool if never initialized + + + +FIXED: Fix German typo + + + +FIXED: Fix missing token type + + + +FIXED: Improve performance of checking document for metadata, which improves performance when checking for possible transclusion + + +FIXED: Update test suite for abbreviation changes + + + + +2017–03–05 – v 0.4.2-b: + + + + +ADDED: Add and utility functions; fix memory leak + + + +ADDED: Initial abbreviation support + + + +ADDED: Keep working on Abbreviations/Glossaries + + + +ADDED: Refactor abbreviation code; Add inline abbreviations; Fix abbreviations in ODF + + + +ADDED: Update Inline Footnote test + + + +CHANGED: Add comments to i18n.h + + + +CHANGED: Finish refactoring note–related code + + + +CHANGED: Refactor footnotes + + + +CHANGED: Refactor glossary code + + + +CHANGED: Remove offset from html export functions + + + +FIXED: latex list items need to block optional argument to allow ‘[’ as first character + + +Merge branch ‘release/0.4.1-b’ into develop + + + + +2017–03–04 – v 0.4.1-b: + + + +FIXED: Add glossary localization + + + + +2017–03–04 – v 0.4.0-b: + + + + +ADDED: Add TOC support to ODF + + + +ADDED: Add glossary support to ODF + + + +ADDED: Add prelim code for handling abbreviations + + + +ADDED: Add support for Swift Package Maker; CHANGED: Restructure source directory + + + +ADDED: Added LaTeX support for escaped characters, fenced code blocks, images, links + + + +ADDED: Basic ODF Support + + + +ADDED: Better document strong/emph algorithm + + + +ADDED: Continue ODF progress + + + +ADDED: Continue to work on ODF export + + + +ADDED: Continue work on ODF + + + +ADDED: Finish ODF support for lists + + + +ADDED: Improve performance when exporting + + + +ADDED: Improve token_pool memory handling + + + +ADDED: Prototype support for Glossaries + + + +ADDED: Support ‘latexconfig’ metadata + + + +CHANGED: Use multiple cases in glossary tests + + + +FIXED: Don't force glossary terms into lowercase + + + +FIXED: Fix Makefile for new source file location + + + +FIXED: Fix algorithm for creating TOC to properly handle ‘incorrect’ levels + + + +FIXED: Fix linebreaks in LaTeX; ADDED: Add Linebreaks test file + + + +FIXED: Fix new_source script for new directory structure + + + +FIXED: Fix non–breaking space in ODF + + + +FIXED: Fix padding at end of document body in ODF + + + +FIXED: Fix underscores in raw latex + + + +FIXED: Potential bug + + +NOTE: Add shared library build option + + + + +2017–02–17 – v 0.3.1.a: + + + + +ADDED: ‘finalize’ beamer support + + + +ADDED: Add escaped newline as linebreak; start on beamer/memoir support + + + +ADDED: CriticMarkup test for LaTeX + + + +ADDED: Custom LaTeX output for CriticMarkup comments + + + +ADDED: Support mmd export format + + + +ADDED: Work on cpack installer – change project name for compatibility + + + +CHANGED: Adjust latex metadata configuration for consistency + + + +CHANGED: Configure cmake to use C99 + + + +FIXED: Add custom implementation for cross–platform support + + + +FIXED: Fix German HTML tests + + + +FIXED: Fix cpack destination directory issue + + + +FIXED: Fix memory leaks etc + + + +FIXED: Fix warning in custom vasprintf + + + +FIXED: Modify CMakeLists.txt to test for use of clang compiler + + + +FIXED: Work on memory leaks + + +NOTE: Adjust license width to improve display on smaller terminal windows + + + + +2017–02–14 – v 0.3.0a: + + + + +ADDED: Add basic image support to LaTeX + + + +ADDED: Add file transclusion + + + +ADDED: Add support for citation ‘locators’ + + + +ADDED: Add support for manual labels on ATX Headers + + + +ADDED: Add support for manual labels on Setext Headers + + + +ADDED: Add support for tables in LaTeX + + + +ADDED: HTML Comments appear as raw LaTeX + + + +ADDED: Improved citation support in LaTeX + + + +ADDED: Support \autoref{} in LaTeX + + + +ADDED: Support combined options in LaTeX citations that use the ‘][’ syntax + + + +ADDED: Support language specifier in fenced code blocks + + + +ADDED: Support metadata in LaTeX + + + +ADDED: Update Citations test suite + + + +FIXED: Escaped LaTeX characters + + + +FIXED: Fix bug in URL parsing + + + +FIXED: Fix bug in citation links + + + +FIXED: Fix bug when no closing divider or newline at end of last table cell + + + +FIXED: Fix issue printing ‘–’ + + + +FIXED: Fix scan_url test suite + + + +FIXED: Get Math working in LaTeX + + + +FIXED: Improve reliability or link scanner + + + +FIXED: Properly add id attribute to new instances of citation only + + + +FIXED: Properly handle manual labels with TOC + + + +FIXED: Properly print hash characters in LaTeX + + + +FIXED: Separate LaTeX verbatim and texttt character handling + + + +FIXED: Update Escapes test LaTeX result + + +FIXED: Work on escaping LaTeX characters + + + + +2017–02–08 – v 0.1.4a: + + + +ADDED: Add smart quote support for other languages (resolves #15) + + + + +2017–02–08 – v 0.1.3a: + + + + +ADDED: Add support for reference image id attributes + + + +ADDED: Add support for table captions + + + +ADDED: Metadata support for base header level + + + +ADDED: Support distinction between 3 and 5 backticks in fenced code blocks + + + +ADDED: Support Setext headers + + +FIXED: Fix issue with metadata disrupting smart quotes + + + + +2017–02–07 – v 0.1.2a: + + + +“pathologic” test suite – fix handling of nested brackets, e.g. +[[[[foo]]]] to avoid bogging down checking for reference links that +don’t exist. + + +Table support – a single blank line separates sections of tables, so +at least two blank lines are needed between adjacent tables. + + + +Definition list support + + + +“fuzz testing” – stress test the parser for unexpected failures + + + +Table of Contents support + + +Improved compatibility mode parsing + + + + +2017–01–28 – v 0.1.1a includes a few updates: + + + + +Metadata support + + + +Metadata variables support + + + +Extended ASCII range character checking + + + +Rudimentary language translations, including German + + + +Improved performance + + +Additional testing: + + + + +CriticMarkup + + + +HTML Blokcs + + + +Metadata/Variables + + +“pathologic” test cases from CommonMark + + + + + + + + + diff --git a/DevelopmentNotes/DevelopmentNotes.html b/DevelopmentNotes/DevelopmentNotes.html new file mode 100644 index 00000000..493aa2b6 --- /dev/null +++ b/DevelopmentNotes/DevelopmentNotes.html @@ -0,0 +1,599 @@ + + + + + MultiMarkdown v6 Development Notes + + + + + +

Introduction

+ +

This document includes some notes on the development of MultiMarkdown (MMD) v6. Most of it +will be interesting only to other developers or those needing to choose the +absolute “best” Markdown (MD) implementation for their needs – it is not required +reading to understand how the software works.

+ +

Why a New Version?

+ +

MultiMarkdown version 5 was released in November of 2015, but the codebase was +essentially the same as that of v4 – and that was released in beta in April +of 2013. A few key things prompted work on a new version:

+ +
    +
  • Accuracy – MMD v4 and v5 were the most accurate versions yet, and a lot of +effort went into finding and resolving various edge cases. However, it began +to feel like a game of whack-a-mole where new bugs would creep in every time I +fixed an old one. The PEG began to feel rather convoluted in spots, even +though it did allow for a precise (if not always accurate) specification of +the grammar.

  • +
  • Performance – “Back in the day” peg-markdown was one of the fastest +Markdown parsers around. MMD v3 was based on peg-markdown, and would leap- +frog with it in terms of performance. Then CommonMark was released, which +was a bit faster. Then a couple of years went by and CommonMark became much +faster – in one of my test suites, MMD v 5.4.0 takes about 25 times longer to +process a long document than CommonMark 0.27.0.

  • +
+ +

In the spring of 2016, I decided I wanted to rewrite MultiMarkdown from scratch, +building the parser myself rather than relying on a pre-rolled solution. (I +had been using greg to compile the PEG +into parser code. It worked well overall, but lacked some features I needed, +requiring a lot of workarounds.)

+ +

First Attempt

+ +

My first attempt started by hand-crafting a parser that scanned through the +document a line at a time, deciding what to do with each line as it found +them. I used regex parsers made with re2c to +help classify each line, and then a separate parser layer to process groups of +lines into blocks. Initially this approach worked well, and was really +efficient. But I quickly began to code my way into a dead-end – the strategy +was not elegant enough to handle things like nested lists, etc.

+ +

One thing that did turn out well from the first attempt, however, was an +approach for handling <emph> and <strong> parsing. I’ve learned over the +years that this can be one of the hardest parts of coding accurately for +Markdown. There are many examples that are obvious to a person, but difficult +to properly “explain” how to parse to a computer.

+ +

No solution is perfect, but I developed an approach that seems to accurately +handle a wide range of situations without a great deal of complexity:

+ +
    +
  1. Scan the documents for asterisks (*). Each one will be handled one at a +time.

  2. +
  3. Unlike brackets ([ and ]), an asterisk is “ambidextrous”, in that it +may be able to open a matched pair of asterisks, close a pair, or both. For +example, in foo *bar* foo:

    + +
      +
    1. The first asterisk can open a pair, but not close one.

    2. +
    3. The second asterisk can close a pair, but not open one.

    4. +
  4. +
  5. So, once the asterisks have been identified, each has to be examined to +determine whether it can open/close/both. The algorithm is not that complex, +but I’ll describe it in general terms. Check the code for more specifics. +This approach seems to work, but might still need some slight tweaking. In +the future, I’ll codify this better in language rather than just in code.

    + +
      +
    1. If there is whitespace to the left of an asterisk, it can’t close.

    2. +
    3. If there is whitespace or punctuation to the right it can’t open.

    4. +
    5. “Runs” of asterisks, e.g. **bar are treated as a unit in terms of +looking left/right.

    6. +
    7. Asterisks inside a word are a bit trickier – we look at the number of +asterisks before the word, the number in the current run, and the number +of asterisks after the word to determine which combinations, if any, are +permitted.

    8. +
  6. +
  7. Once all asterisks have been tagged as able to open/close/both, we proceed +through them in order:

    + +
      +
    1. When we encounter a tag that can close, we look to see if there is a +previous opener that has not been paired off. If so, pair the two and +remove the opener from the list of available asterisks.

    2. +
    3. When we encounter an opener, add it to the stack of available openers.

    4. +
    5. When encounter an asterisk that can do both, see if it can close an +existing opener. If not, then add it to the stack.

    6. +
  8. +
  9. After all tokens in the block have been paired, then we look for nesting +pairs of asterisks in order to create <emph> and <strong> sets. For +example, assume we have six asterisks wrapped around a word, three in front, +and three after. The asterisks are indicated with numbers: 123foo456. We +proceed in the following manner:

    + +
      +
    1. Based on the pairing algorithm above, these asterisks would be paired as +follows, with matching asterisks sharing numbers – 123foo321.

    2. +
    3. Moving forwards, we come to asterisk “1”. It is followed by an +asterisk, so we check to see if they should be grouped as a <strong>. +Since the “1” asterisks are wrapped immediately outside the “2” asterisks, +they are joined together. More than two pairs can’t be joined, so we now +get the following – 112foo211, where the “11” represents the opening +and closing of a <strong>, and the “2” represents a <emph>.

    4. +
  10. +
  11. When matching a pair, any unclosed openers that are on the stack are +removed, preventing pairs from “crossing” or “intersecting”. Pairs can wrap +around each other, e.g. [(foo)], but not intersect like [(foo]). In the +second case, the brackets would close, removing the ( from the stack.

  12. +
  13. This same approach is used in all tokens that are matched in pairs– +[foo], (foo), _foo_, etc. There’s slightly more to it, but once you +figure out how to assign opening/closing ability, the rest is easy. By using +a stack to track available openers, it can be performed efficiently.

  14. +
+ +

In my testing, this approach has worked quite well. It handles all the basic +scenarios I’ve thrown at it, and all of the “basic” and “devious” edge cases I +have thought of (some of these don’t necessarily have a “right” answer – but +v6 gives consistency answers that seem as reasonable as any others to me). +There are also three more edge cases I’ve come up can still stump it, and +ironically they are handled correctly by most implementations. They just +don’t follow the rules above. I’ll continue to work on this.

+ +

In the end, I scrapped this effort, but kept the lessons learned in the token +pairing algorithm.

+ +

Second Attempt

+ +

I tried again this past Fall. This time, I approached the problem with lots +of reading. Lots and lots of reading – tons of websites, computer science +journal articles, PhD theses, etc. Learned a lot about lexers, and a lot +about parsers, including hand-crafting vs using parser generators. In brief:

+ +
    +
  1. I learned about the Aho–Corasick algorithm, which is a great way to +efficiently search a string for multiple target strings at once. I used this +to create a custom lexer to identify tokens in a MultiMarkdown text document +(e.g. *, [, {++, etc.). I learned a lot, and had a good time working +out the implementation. This code efficiently allowed me to break a string of +text into the tokens that mattered for Markdown parsing.

  2. +
  3. However, in a few instances I really needed some features of regular +expressions to simplify more complex structures. After a quick bit of testing, +using re2c to create a tokenizer was just as efficient, and allowed me to +incorporate some regex functionality that simplified later parsing. I’ll keep +the Aho-Corasick stuff around, and will probably experiment more with it +later. But I didn’t need it for MMD now. lexer.re contains the source for +the tokenizer.

  4. +
+ +

I looked long and hard for a way to simplify the parsing algorithm to try and +“touch” each token only once. Ideally, the program could step through each +token, and decide when to create a new block, when to pair things together, +etc. But I’m not convinced it’s possible. Since Markdown’s grammar varies +based on context, it seems to work best when handled in distinct phases:

+ +
    +
  1. Tokenize the string to identify key sections of text. This includes line +breaks, allowing the text to be examined one line at time.

  2. +
  3. Join series of lines together into blocks, such as paragraphs, code blocks, +lists, etc.

  4. +
  5. The tokens inside each block can then be paired together to create more +complex syntax such as links, strong, emphasis, etc.

  6. +
+ +

To handle the block parsing, I started off using the Aho-Corasick code to +handle my first attempt. I had actually implemented some basic regex +functionality, and used that to group lines together to create blocks. But +this quickly fell apart in the face of more complex structures such as +recursive lists. After a lot of searching, and tons more reading, I +ultimately decided to use a parser generator to handle the task of group lines +into blocks. parser.y has the source for this, and it is processed by the +lemon parser generator to create the actual +code.

+ +

I chose to do this because hand-crafting the block parser would be complex. +The end result would likely be difficult to read and understand, which would +make it difficult to update later on. Using the parser generator allows me to +write things out in a way that can more easily be understood by a person. In +all likelihood, the performance is probably as good as anything I could do +anyway, if not better.

+ +

Because lemon is a LALR(1) parser, it does require a bit of thinking ahead +about how to create the grammar used. But so far, it has been able to handle +everything I have thrown at it.

+ +

Optimization

+ +

One of my goals for MMD 6 was performance. So I’ve paid attention to speed +along the way, and have tried to use a few tricks to keep things fast. Here +are some things I’ve learned along the way. In no particular order:

+ +

Memory Allocation

+ +

When parsing a long document, a lot of token structures are created. Each +one requires a small bit of memory to be allocated. In aggregate, that time +added up and slowed down performance.

+ +

After reading for a bit, I ended up coming up with an approach that uses +larger chunks of memory. I allocate pools of of memory in large slabs for +smaller “objects”". For example, I allocate memory for 1024 tokens at a +single time, and then dole that memory out as needed. When the slab is empty, +a new one is allocated. This dramatically improved performance.

+ +

When pairing tokens, I created a new stack for each block. I realized that an +empty stack didn’t have any “leftover” cruft to interfere with re-use, so I +just used one for the entire document. Again a sizeable improvement in +performance from only allocating one object instead of many. When recursing +to a deeper level, the stack just gets deeper, but earlier levels aren’t +modified.

+ +

Speaking of tokens, I realized that the average document contains a lot of +single spaces (there’s one between every two words I have written, for +example.) The vast majority of the time, these single spaces have no effect +on the output of Markdown documents. I changed my whitespace token search to +only flag runs of 2 or more spaces, dramatically reducing the number of +tokens. This gives the benefit of needing fewer memory allocations, and also +reduces the number of tokens that need to be processed later on. The only +downside is remember to check for a single space character in a few instances +where it matters.

+ +

Proper input buffering

+ +

When I first began last spring, I was amazed to see how much time was being +spent by MultiMarkdown simply reading the input file. Then I discovered it +was because I was reading it one character at a time. I switched to using a +buffered read approach and the time to read the file went to almost nothing. I +experimented with different buffer sizes, but they did not seem to make a +measurable difference.

+ +

Output Buffering

+ +

I experimented with different approaches to creating the output after parsing. +I tried printing directly to stdout, and even played with different +buffering settings. None of those seemed to work well, and all were slower +than using the d_string approach (formerly call GString in MMD 5).

+ +

Fast Searches

+ +

After getting basic Markdown functionality complete, I discovered during +testing that the time required to parse a document grew exponentially as the +document grew longer. Performance was on par with CommonMark for shorter +documents, but fell increasingly behind in larger tests. Time profiling found +that the culprit was searching for link definitions when they didn’t exist. +My first approach was to keep a stack of used link definitions, and to iterate +through them when necessary. In long documents, this performs very poorly. +More research and I ended up using +uthash. This allows me to search for +a link (or footnote, etc.) by “name” rather than searching through an array. +This allowed me to get MMD’s performance back to O(n), taking roughly twice as +much time to process a document that is twice as long.

+ +

Efficient Utility Functions

+ +

It is frequently necessary when parsing Markdown to check what sort of +character we are dealing with at a certain position – a letter, whitespace, +punctuation, etc. I created a lookup table for this via char_lookup.c and +hard-coded it in char.c. These routines allow me to quickly, and +consistently, classify any byte within a document. This saved a lot of +programming time, and saved time tracking down bugs from handling things +slightly differently under different circumstances. I also suspect it +improved performance, but don’t have the data to back it up.

+ +

Testing While Writing

+ +

I developed several chunks of code in parallel while creating MMD 6. The vast +majority of it was developed largely in a test-driven development approach. +The other code was largely created with extensive unit testing to accomplish +this.

+ +

MMD isn’t particularly amenable to this approach at the small level, but +instead I relied more on integration testing with an ever-growing collection +of text files and the corresponding HTML files in the MMD 6 test suite. This +allowed me to ensure new features work properly and that old features aren’t +broken. At this time, there are 29 text files in the test suite, and many +more to come.

+ +

Other Lessons

+ +

Some things that didn’t do me any good….

+ +

I considered differences between using malloc and calloc when initializing +tokens. The time saved by using malloc was basically exactly offset by the +initial time required to initialize the token to default null values as +compared to using calloc. When trying calloc failed to help me out +(thinking that clearing a single slab in the object pool would be faster), I +stuck with malloc as it makes more sense to me in my workflow.

+ +

I read a bit about struct padding and reordered some of my structs. It was +until later that I discovered the -Wpadded option, and it’s not clear +whether my changes modified anything. Since the structs were being padded +automatically, there was no noticeable performance change, and I didn’t have +the tools to measure whether I could have improved memory usage at all. Not +sure this would be worth the effort – much lower hanging fruit available.

+ +

Performance

+ +

Basic tests show that currently MMD 6 takes about 20–25% longer the CommonMark +0.27.0 to process long files (e.g. 0.2 MB). However, it is around 5% faster +than CommonMark when parsing a shorter file (27 kB) (measured by parsing the +same file 200 times over). This test suite is performed by using the Markdown +[syntax page], modified to avoid the use of the Setext header at the top. The +longer files tested are created by copying the same syntax page onto itself, +thereby doubling the length of the file with each iteration.

+ +

The largest file I test is approximately 108 MB (4096 copies of the syntax +page). On my machine (2012 Mac mini with 2.3 GHz Intel Core i7, 16 GB RAM), +it takes approximately 4.4 seconds to parse with MMD 6 and 3.7 seconds with +CommonMark. MMD 6 processes approximately 25 MB/s on this test file. +CommonMark 0.27.0 gets about 29 MB/s on the same machine.

+ +

There are some slight variations with the smaller test files (8–32 copies), +but overall the performance of both programs (MMD 6 and CommonMark) are +roughly linear as the test file gets bigger (double the file size and it takes +twice as long to parse, aka O(n)).

+ +

Out of curiosity, I ran the same tests on the original Markdown.pl by Gruber +(v 1.0.2b8). It took approximately 178 seconds to parse 128 copies of the +file (3.4 MB) and was demonstrating quadratic performance characteristics +(double the file size and it takes 22 or 4 times longer to process, aka +O(n2)). I didn’t bother running it on larger versions of the test file. For +comparison, MMD 6 can process 128 copies in approximately 140 msec.

+ +

Of note, the throughput speed drops when testing more complicated files +containing more advanced MultiMarkdown features, though it still seems to +maintain linear performance characteristics. A second test file is created by +concatenating all of the test suite files (including the Markdown syntax +file). In this case, MMD gets about 13 MB/s. CommonMark doesn’t support +these additional features, so testing it with that file is not relevant. I +will work to see whether there are certain features in particular that are +more challenging and see whether they can be reworked to improve performance.

+ +

As above, I have done some high level optimization of the parse strategy, but +I’m sure there’s still a lot of room for further improvement to be made. +Suggestions welcome!

+ +

Testing

+ +

Test Suite

+ +

The development of MMD v6 was heavily, but not absolutely, influenced by the +philosophy of test-driven development. While coding, I made use of test +suites to verify successful implementation of new features, to avoid +regression problems when adding new features, and to identify known edge cases +in need of proper handling.

+ +

The test suite (located in tests/MMD6Tests) is a “living” collection of +documents that will continue to be updated as new bugs and edge cases are +identified. This helps make proper integration testing of the entire +application with every release.

+ +

Fuzz Testing

+ +

I was not familiar with the concept of Fuzz Testing +(https://en.wikipedia.org/wiki/Fuzzing) until a user mentioned something about +it to me a year or two ago. I had never used it before, but it seemed like a +good idea. I implement it in two ways.

+ +

The first is that I created a simplified version of the line parser that +simply accepts various combinations of line type identifiers to see if they +would successfully parse. The line parser is responsible for taking a series +of line types (e.g. plain text, indented line, etc.) and determining what sort +of block they should become. The file test/parser_text.y is run through the +lemon program, compiled (with or without the -DNDEBUG flag) and then run. +It sequentially throws every combination of line types at the simplified line +parser to make sure that it doesn’t choke. When I first did this, I found +several combinations of lines that did not pass.

+ +

NOTE: This does not verify accurate parsing, simply that the parser does +not crash by an unacceptable combination of lines.

+ +

The second form of fuzz testing I have started using more recently. This is +using the American fuzzy lop program to try +to find text input that crashes MMD. This works by taking sample input (e.g. +files from the test suite), modifying them slightly, and trying the modified +versions. Do this over and over and over, and some interesting edge cases are +sometimes identified. I have found some interesting edge cases this way. +Definitely a very useful tool!

+ +

Unit Testing

+ +

Some of the original development was done with unit testing in some other +tools I developed. This code formed the basis of a few parts of MMD. +Otherwise, it was hard to see how to really create very good unit tests for +the development of MMD. So there is really not much unit testing built into +the code or used during the development.

+ +

Changelog

+ +
    +
  • 2017–03–13 – v 6.0.0-b2:

    + +
      +
    • ADDED: Add CriticMarkup preprocessor that works across empty lines when accepting/rejecting markup
    • +
    • ADDED: Add back the mmd6 latex title file
    • +
    • ADDED: Basic EPUB 3 support – uses ‘miniz’ library to zip creation
    • +
    • ADDED: Update QuickStart and EPUB code
    • +
    • CHANGED: Update QuickStart guide
    • +
    • CHANGED: Update test suite
    • +
    • FIXED: Don't duplicate LaTeX glossary definitions
    • +
    • FIXED: Fix abbreviations in ODF; Improve test suite
    • +
    • FIXED: Improve glossaries and abbreviations; Update QuickStart
    • +
    • FIXED: Tidy up some compiler warnings in code
    • +
    • FIXED: Use custom UUID code to minimize external dependencies
    • +
  • +
  • 2017–03–09 – v 6.0.0-b1:

    + +
      +
    • ADDED: Add French translations; fix typo in German
    • +
    • ADDED: Add Quick Start guide
    • +
    • ADDED: Add functionality to automatically identify abbreviations and glossary terms in source
    • +
    • ADDED: Improve LaTeX configuration files
    • +
    • ADDED: Update German translations
    • +
    • ADDED: Use native ODF table of contents instead of a manual list
    • +
    • ADDED: Use native command for table of contents in LaTeX
    • +
    • CHANGED: Bring HTML and ODF into line with LaTeX as to output of abbreviatinos on first and subsequent uses
    • +
    • CHANGED: Slight performance tweak
    • +
    • CHANGED: Update German test suite
    • +
    • FIXED: Allow {{TOC}} in latex verbatim
    • +
    • FIXED: Don't free token_pool if never initialized
    • +
    • FIXED: Fix German typo
    • +
    • FIXED: Fix missing token type
    • +
    • FIXED: Improve performance of checking document for metadata, which improves performance when checking for possible transclusion
    • +
    • FIXED: Update test suite for abbreviation changes
    • +
  • +
  • 2017–03–05 – v 0.4.2-b:

    + +
      +
    • ADDED: Add and utility functions; fix memory leak
    • +
    • ADDED: Initial abbreviation support
    • +
    • ADDED: Keep working on Abbreviations/Glossaries
    • +
    • ADDED: Refactor abbreviation code; Add inline abbreviations; Fix abbreviations in ODF
    • +
    • ADDED: Update Inline Footnote test
    • +
    • CHANGED: Add comments to i18n.h
    • +
    • CHANGED: Finish refactoring note–related code
    • +
    • CHANGED: Refactor footnotes
    • +
    • CHANGED: Refactor glossary code
    • +
    • CHANGED: Remove offset from html export functions
    • +
    • FIXED: latex list items need to block optional argument to allow ‘[’ as first character
    • +
    • Merge branch ‘release/0.4.1-b’ into develop
    • +
  • +
  • 2017–03–04 – v 0.4.1-b:

    + +
      +
    • FIXED: Add glossary localization
    • +
  • +
  • 2017–03–04 – v 0.4.0-b:

    + +
      +
    • ADDED: Add TOC support to ODF
    • +
    • ADDED: Add glossary support to ODF
    • +
    • ADDED: Add prelim code for handling abbreviations
    • +
    • ADDED: Add support for Swift Package Maker; CHANGED: Restructure source directory
    • +
    • ADDED: Added LaTeX support for escaped characters, fenced code blocks, images, links
    • +
    • ADDED: Basic ODF Support
    • +
    • ADDED: Better document strong/emph algorithm
    • +
    • ADDED: Continue ODF progress
    • +
    • ADDED: Continue to work on ODF export
    • +
    • ADDED: Continue work on ODF
    • +
    • ADDED: Finish ODF support for lists
    • +
    • ADDED: Improve performance when exporting
    • +
    • ADDED: Improve token_pool memory handling
    • +
    • ADDED: Prototype support for Glossaries
    • +
    • ADDED: Support ‘latexconfig’ metadata
    • +
    • CHANGED: Use multiple cases in glossary tests
    • +
    • FIXED: Don't force glossary terms into lowercase
    • +
    • FIXED: Fix Makefile for new source file location
    • +
    • FIXED: Fix algorithm for creating TOC to properly handle ‘incorrect’ levels
    • +
    • FIXED: Fix linebreaks in LaTeX; ADDED: Add Linebreaks test file
    • +
    • FIXED: Fix new_source script for new directory structure
    • +
    • FIXED: Fix non–breaking space in ODF
    • +
    • FIXED: Fix padding at end of document body in ODF
    • +
    • FIXED: Fix underscores in raw latex
    • +
    • FIXED: Potential bug
    • +
    • NOTE: Add shared library build option
    • +
  • +
  • 2017–02–17 – v 0.3.1.a:

    + +
      +
    • ADDED: ‘finalize’ beamer support
    • +
    • ADDED: Add escaped newline as linebreak; start on beamer/memoir support
    • +
    • ADDED: CriticMarkup test for LaTeX
    • +
    • ADDED: Custom LaTeX output for CriticMarkup comments
    • +
    • ADDED: Support mmd export format
    • +
    • ADDED: Work on cpack installer – change project name for compatibility
    • +
    • CHANGED: Adjust latex metadata configuration for consistency
    • +
    • CHANGED: Configure cmake to use C99
    • +
    • FIXED: Add custom implementation for cross–platform support
    • +
    • FIXED: Fix German HTML tests
    • +
    • FIXED: Fix cpack destination directory issue
    • +
    • FIXED: Fix memory leaks etc
    • +
    • FIXED: Fix warning in custom vasprintf
    • +
    • FIXED: Modify CMakeLists.txt to test for use of clang compiler
    • +
    • FIXED: Work on memory leaks
    • +
    • NOTE: Adjust license width to improve display on smaller terminal windows
    • +
  • +
  • 2017–02–14 – v 0.3.0a:

    + +
      +
    • ADDED: Add basic image support to LaTeX
    • +
    • ADDED: Add file transclusion
    • +
    • ADDED: Add support for citation ‘locators’
    • +
    • ADDED: Add support for manual labels on ATX Headers
    • +
    • ADDED: Add support for manual labels on Setext Headers
    • +
    • ADDED: Add support for tables in LaTeX
    • +
    • ADDED: HTML Comments appear as raw LaTeX
    • +
    • ADDED: Improved citation support in LaTeX
    • +
    • ADDED: Support \autoref{} in LaTeX
    • +
    • ADDED: Support combined options in LaTeX citations that use the ‘][’ syntax
    • +
    • ADDED: Support language specifier in fenced code blocks
    • +
    • ADDED: Support metadata in LaTeX
    • +
    • ADDED: Update Citations test suite
    • +
    • FIXED: Escaped LaTeX characters
    • +
    • FIXED: Fix bug in URL parsing
    • +
    • FIXED: Fix bug in citation links
    • +
    • FIXED: Fix bug when no closing divider or newline at end of last table cell
    • +
    • FIXED: Fix issue printing ‘–’
    • +
    • FIXED: Fix scan_url test suite
    • +
    • FIXED: Get Math working in LaTeX
    • +
    • FIXED: Improve reliability or link scanner
    • +
    • FIXED: Properly add id attribute to new instances of citation only
    • +
    • FIXED: Properly handle manual labels with TOC
    • +
    • FIXED: Properly print hash characters in LaTeX
    • +
    • FIXED: Separate LaTeX verbatim and texttt character handling
    • +
    • FIXED: Update Escapes test LaTeX result
    • +
    • FIXED: Work on escaping LaTeX characters
    • +
  • +
  • 2017–02–08 – v 0.1.4a:

    + +
      +
    • ADDED: Add smart quote support for other languages (resolves #15)
    • +
  • +
  • 2017–02–08 – v 0.1.3a:

    + +
      +
    • ADDED: Add support for reference image id attributes
    • +
    • ADDED: Add support for table captions
    • +
    • ADDED: Metadata support for base header level
    • +
    • ADDED: Support distinction between 3 and 5 backticks in fenced code blocks
    • +
    • ADDED: Support Setext headers
    • +
    • FIXED: Fix issue with metadata disrupting smart quotes
    • +
  • +
  • 2017–02–07 – v 0.1.2a:

    + +
      +
    • “pathologic” test suite – fix handling of nested brackets, e.g. +[[[[foo]]]] to avoid bogging down checking for reference links that +don’t exist.
    • +
    • Table support – a single blank line separates sections of tables, so +at least two blank lines are needed between adjacent tables.
    • +
    • Definition list support
    • +
    • “fuzz testing” – stress test the parser for unexpected failures
    • +
    • Table of Contents support
    • +
    • Improved compatibility mode parsing
    • +
  • +
  • 2017–01–28 – v 0.1.1a includes a few updates:

    + +
      +
    • Metadata support
    • +
    • Metadata variables support
    • +
    • Extended ASCII range character checking
    • +
    • Rudimentary language translations, including German
    • +
    • Improved performance
    • +
    • Additional testing: + +
        +
      • CriticMarkup
      • +
      • HTML Blokcs
      • +
      • Metadata/Variables
      • +
      • “pathologic” test cases from CommonMark
      • +
    • +
  • +
+ +
+
+
    + +
  1. +PEG:

    Parsing Expression Grammar https://en.wikipedia.org/wiki/Parsing_expression_grammar  ↩

    +
  2. + +
+
+ + + + diff --git a/DevelopmentNotes/DevelopmentNotes.pdf b/DevelopmentNotes/DevelopmentNotes.pdf new file mode 100644 index 0000000000000000000000000000000000000000..611a80d9429c4c58d22691398db49a2409a5ec43 GIT binary patch literal 103994 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 literal 0 HcmV?d00001 diff --git a/DevelopmentNotes/DevelopmentNotes.txt b/DevelopmentNotes/DevelopmentNotes.txt index 0dbb37ab..072d63d0 100644 --- a/DevelopmentNotes/DevelopmentNotes.txt +++ b/DevelopmentNotes/DevelopmentNotes.txt @@ -163,7 +163,7 @@ the Aho-Corasick stuff around, and will probably experiment more with it later. But I didn't need it for MMD now. `lexer.re` contains the source for the tokenizer. -[Aho–Corasick algorithm]: https://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_algorithm +[Aho–Corasick algorithm]: https://en.wikipedia.org/wiki/Aho-Corasick_algorithm I looked long and hard for a way to simplify the parsing algorithm to try and "touch" each token only once. Ideally, the program could step through each @@ -180,7 +180,7 @@ lists, etc. 3. The tokens inside each block can then be paired together to create more complex syntax such as links, strong, emphasis, etc. -To handle the block parsing, I started off using the [Aho-Corasick] code to +To handle the block parsing, I started off using the Aho-Corasick code to handle my first attempt. I had actually implemented some basic regex functionality, and used that to group lines together to create blocks. But this quickly fell apart in the face of more complex structures such as @@ -429,3 +429,183 @@ the code or used during the development. [?AST]: Abstract Syntax Tree + +# Changelog # + + +* 2017-03-13 -- v 6.0.0-b2: + + * ADDED: Add CriticMarkup preprocessor that works across empty lines when accepting/rejecting markup + * ADDED: Add back the mmd6 latex title file + * ADDED: Basic EPUB 3 support -- uses 'miniz' library to zip creation + * ADDED: Update QuickStart and EPUB code + * CHANGED: Update QuickStart guide + * CHANGED: Update test suite + * FIXED: Don't duplicate LaTeX glossary definitions + * FIXED: Fix abbreviations in ODF; Improve test suite + * FIXED: Improve glossaries and abbreviations; Update QuickStart + * FIXED: Tidy up some compiler warnings in code + * FIXED: Use custom UUID code to minimize external dependencies + + +* 2017-03-09 -- v 6.0.0-b1: + + * ADDED: Add French translations; fix typo in German + * ADDED: Add Quick Start guide + * ADDED: Add functionality to automatically identify abbreviations and glossary terms in source + * ADDED: Improve LaTeX configuration files + * ADDED: Update German translations + * ADDED: Use native ODF table of contents instead of a manual list + * ADDED: Use native command for table of contents in LaTeX + * CHANGED: Bring HTML and ODF into line with LaTeX as to output of abbreviatinos on first and subsequent uses + * CHANGED: Slight performance tweak + * CHANGED: Update German test suite + * FIXED: Allow `{{TOC}}` in latex verbatim + * FIXED: Don't free token_pool if never initialized + * FIXED: Fix German typo + * FIXED: Fix missing token type + * FIXED: Improve performance of checking document for metadata, which improves performance when checking for possible transclusion + * FIXED: Update test suite for abbreviation changes + + +* 2017-03-05 -- v 0.4.2-b: + + * ADDED: Add and utility functions; fix memory leak + * ADDED: Initial abbreviation support + * ADDED: Keep working on Abbreviations/Glossaries + * ADDED: Refactor abbreviation code; Add inline abbreviations; Fix abbreviations in ODF + * ADDED: Update Inline Footnote test + * CHANGED: Add comments to i18n.h + * CHANGED: Finish refactoring note-related code + * CHANGED: Refactor footnotes + * CHANGED: Refactor glossary code + * CHANGED: Remove offset from html export functions + * FIXED: latex list items need to block optional argument to allow '[' as first character + * Merge branch 'release/0.4.1-b' into develop + + +* 2017-03-04 -- v 0.4.1-b: + + * FIXED: Add glossary localization + + +* 2017-03-04 -- v 0.4.0-b: + + * ADDED: Add TOC support to ODF + * ADDED: Add glossary support to ODF + * ADDED: Add prelim code for handling abbreviations + * ADDED: Add support for Swift Package Maker; CHANGED: Restructure source directory + * ADDED: Added LaTeX support for escaped characters, fenced code blocks, images, links + * ADDED: Basic ODF Support + * ADDED: Better document strong/emph algorithm + * ADDED: Continue ODF progress + * ADDED: Continue to work on ODF export + * ADDED: Continue work on ODF + * ADDED: Finish ODF support for lists + * ADDED: Improve performance when exporting + * ADDED: Improve token_pool memory handling + * ADDED: Prototype support for Glossaries + * ADDED: Support 'latexconfig' metadata + * CHANGED: Use multiple cases in glossary tests + * FIXED: Don't force glossary terms into lowercase + * FIXED: Fix Makefile for new source file location + * FIXED: Fix algorithm for creating TOC to properly handle 'incorrect' levels + * FIXED: Fix linebreaks in LaTeX; ADDED: Add Linebreaks test file + * FIXED: Fix new_source script for new directory structure + * FIXED: Fix non-breaking space in ODF + * FIXED: Fix padding at end of document body in ODF + * FIXED: Fix underscores in raw latex + * FIXED: Potential bug + * NOTE: Add shared library build option + + +* 2017-02-17 -- v 0.3.1.a: + + * ADDED: 'finalize' beamer support + * ADDED: Add escaped newline as linebreak; start on beamer/memoir support + * ADDED: CriticMarkup test for LaTeX + * ADDED: Custom LaTeX output for CriticMarkup comments + * ADDED: Support mmd export format + * ADDED: Work on cpack installer -- change project name for compatibility + * CHANGED: Adjust latex metadata configuration for consistency + * CHANGED: Configure cmake to use C99 + * FIXED: Add custom implementation for cross-platform support + * FIXED: Fix German HTML tests + * FIXED: Fix cpack destination directory issue + * FIXED: Fix memory leaks etc + * FIXED: Fix warning in custom vasprintf + * FIXED: Modify CMakeLists.txt to test for use of clang compiler + * FIXED: Work on memory leaks + * NOTE: Adjust license width to improve display on smaller terminal windows + + +* 2017-02-14 -- v 0.3.0a: + + * ADDED: Add basic image support to LaTeX + * ADDED: Add file transclusion + * ADDED: Add support for citation 'locators' + * ADDED: Add support for manual labels on ATX Headers + * ADDED: Add support for manual labels on Setext Headers + * ADDED: Add support for tables in LaTeX + * ADDED: HTML Comments appear as raw LaTeX + * ADDED: Improved citation support in LaTeX + * ADDED: Support \autoref{} in LaTeX + * ADDED: Support combined options in LaTeX citations that use the '\]\[' syntax + * ADDED: Support language specifier in fenced code blocks + * ADDED: Support metadata in LaTeX + * ADDED: Update Citations test suite + * FIXED: Escaped LaTeX characters + * FIXED: Fix bug in URL parsing + * FIXED: Fix bug in citation links + * FIXED: Fix bug when no closing divider or newline at end of last table cell + * FIXED: Fix issue printing '-' + * FIXED: Fix scan_url test suite + * FIXED: Get Math working in LaTeX + * FIXED: Improve reliability or link scanner + * FIXED: Properly add id attribute to new instances of citation only + * FIXED: Properly handle manual labels with TOC + * FIXED: Properly print hash characters in LaTeX + * FIXED: Separate LaTeX verbatim and texttt character handling + * FIXED: Update Escapes test LaTeX result + * FIXED: Work on escaping LaTeX characters + + +* 2017-02-08 -- v 0.1.4a: + + * ADDED: Add smart quote support for other languages (resolves #15) + + +* 2017-02-08 -- v 0.1.3a: + + * ADDED: Add support for reference image id attributes + * ADDED: Add support for table captions + * ADDED: Metadata support for base header level + * ADDED: Support distinction between 3 and 5 backticks in fenced code blocks + * ADDED: Support Setext headers + * FIXED: Fix issue with metadata disrupting smart quotes + +* 2017-02-07 -- v 0.1.2a: + + * "pathologic" test suite -- fix handling of nested brackets, e.g. + `[[[[foo]]]]` to avoid bogging down checking for reference links that + don't exist. + * Table support -- a single blank line separates sections of tables, so + at least two blank lines are needed between adjacent tables. + * Definition list support + * "fuzz testing" -- stress test the parser for unexpected failures + * Table of Contents support + * Improved compatibility mode parsing + +* 2017-01-28 -- v 0.1.1a includes a few updates: + + * Metadata support + * Metadata variables support + * Extended ASCII range character checking + * Rudimentary language translations, including German + * Improved performance + * Additional testing: + * CriticMarkup + * HTML Blokcs + * Metadata/Variables + * "pathologic" test cases from CommonMark + diff --git a/README.md b/README.md index 3ce8774a..5d08aa68 100644 --- a/README.md +++ b/README.md @@ -9,222 +9,54 @@ | Version: | 6.0.0-b2 | -## Updates ## - -* 2017-03-13 -- v 6.0.0-b2: - - * ADDED: Add CriticMarkup preprocessor that works across empty lines when accepting/rejecting markup - * ADDED: Add back the mmd6 latex title file - * ADDED: Basic EPUB 3 support -- uses 'miniz' library to zip creation - * ADDED: Update QuickStart and EPUB code - * CHANGED: Update QuickStart guide - * CHANGED: Update test suite - * FIXED: Don't duplicate LaTeX glossary definitions - * FIXED: Fix abbreviations in ODF; Improve test suite - * FIXED: Improve glossaries and abbreviations; Update QuickStart - * FIXED: Tidy up some compiler warnings in code - * FIXED: Use custom UUID code to minimize external dependencies - - -* 2017-03-09 -- v 6.0.0-b1: - - * ADDED: Add French translations; fix typo in German - * ADDED: Add Quick Start guide - * ADDED: Add functionality to automatically identify abbreviations and glossary terms in source - * ADDED: Improve LaTeX configuration files - * ADDED: Update German translations - * ADDED: Use native ODF table of contents instead of a manual list - * ADDED: Use native command for table of contents in LaTeX - * CHANGED: Bring HTML and ODF into line with LaTeX as to output of abbreviatinos on first and subsequent uses - * CHANGED: Slight performance tweak - * CHANGED: Update German test suite - * FIXED: Allow {{TOC}} in latex verbatim - * FIXED: Don't free token_pool if never initialized - * FIXED: Fix German typo - * FIXED: Fix missing token type - * FIXED: Improve performance of checking document for metadata, which improves performance when checking for possible transclusion - * FIXED: Update test suite for abbreviation changes - - -* 2017-03-05 -- v 0.4.2-b: - - * ADDED: Add and utility functions; fix memory leak - * ADDED: Initial abbreviation support - * ADDED: Keep working on Abbreviations/Glossaries - * ADDED: Refactor abbreviation code; Add inline abbreviations; Fix abbreviations in ODF - * ADDED: Update Inline Footnote test - * CHANGED: Add comments to i18n.h - * CHANGED: Finish refactoring note-related code - * CHANGED: Refactor footnotes - * CHANGED: Refactor glossary code - * CHANGED: Remove offset from html export functions - * FIXED: latex list items need to block optional argument to allow '[' as first character - * Merge branch 'release/0.4.1-b' into develop - - -* 2017-03-04 -- v 0.4.1-b: - - * FIXED: Add glossary localization - - -* 2017-03-04 -- v 0.4.0-b: - - * ADDED: Add TOC support to ODF - * ADDED: Add glossary support to ODF - * ADDED: Add prelim code for handling abbreviations - * ADDED: Add support for Swift Package Maker; CHANGED: Restructure source directory - * ADDED: Added LaTeX support for escaped characters, fenced code blocks, images, links - * ADDED: Basic ODF Support - * ADDED: Better document strong/emph algorithm - * ADDED: Continue ODF progress - * ADDED: Continue to work on ODF export - * ADDED: Continue work on ODF - * ADDED: Finish ODF support for lists - * ADDED: Improve performance when exporting - * ADDED: Improve token_pool memory handling - * ADDED: Prototype support for Glossaries - * ADDED: Support 'latexconfig' metadata - * CHANGED: Use multiple cases in glossary tests - * FIXED: Don't force glossary terms into lowercase - * FIXED: Fix Makefile for new source file location - * FIXED: Fix algorithm for creating TOC to properly handle 'incorrect' levels - * FIXED: Fix linebreaks in LaTeX; ADDED: Add Linebreaks test file - * FIXED: Fix new_source script for new directory structure - * FIXED: Fix non-breaking space in ODF - * FIXED: Fix padding at end of document body in ODF - * FIXED: Fix underscores in raw latex - * FIXED: Potential bug - * NOTE: Add shared library build option - - -* 2017-02-17 -- v 0.3.1.a: - - * ADDED: 'finalize' beamer support - * ADDED: Add escaped newline as linebreak; start on beamer/memoir support - * ADDED: CriticMarkup test for LaTeX - * ADDED: Custom LaTeX output for CriticMarkup comments - * ADDED: Support mmd export format - * ADDED: Work on cpack installer -- change project name for compatibility - * CHANGED: Adjust latex metadata configuration for consistency - * CHANGED: Configure cmake to use C99 - * FIXED: Add custom implementation for cross-platform support - * FIXED: Fix German HTML tests - * FIXED: Fix cpack destination directory issue - * FIXED: Fix memory leaks etc - * FIXED: Fix warning in custom vasprintf - * FIXED: Modify CMakeLists.txt to test for use of clang compiler - * FIXED: Work on memory leaks - * NOTE: Adjust license width to improve display on smaller terminal windows - - -* 2017-02-14 -- v 0.3.0a: - - * ADDED: Add basic image support to LaTeX - * ADDED: Add file transclusion - * ADDED: Add support for citation 'locators' - * ADDED: Add support for manual labels on ATX Headers - * ADDED: Add support for manual labels on Setext Headers - * ADDED: Add support for tables in LaTeX - * ADDED: HTML Comments appear as raw LaTeX - * ADDED: Improved citation support in LaTeX - * ADDED: Support \autoref{} in LaTeX - * ADDED: Support combined options in LaTeX citations that use the '\]\[' syntax - * ADDED: Support language specifier in fenced code blocks - * ADDED: Support metadata in LaTeX - * ADDED: Update Citations test suite - * FIXED: Escaped LaTeX characters - * FIXED: Fix bug in URL parsing - * FIXED: Fix bug in citation links - * FIXED: Fix bug when no closing divider or newline at end of last table cell - * FIXED: Fix issue printing '-' - * FIXED: Fix scan_url test suite - * FIXED: Get Math working in LaTeX - * FIXED: Improve reliability or link scanner - * FIXED: Properly add id attribute to new instances of citation only - * FIXED: Properly handle manual labels with TOC - * FIXED: Properly print hash characters in LaTeX - * FIXED: Separate LaTeX verbatim and texttt character handling - * FIXED: Update Escapes test LaTeX result - * FIXED: Work on escaping LaTeX characters - - -* 2017-02-08 -- v 0.1.4a: - - * ADDED: Add smart quote support for other languages (resolves #15) - - -* 2017-02-08 -- v 0.1.3a: - - * ADDED: Add support for reference image id attributes - * ADDED: Add support for table captions - * ADDED: Metadata support for base header level - * ADDED: Support distinction between 3 and 5 backticks in fenced code blocks - * ADDED: Support Setext headers - * FIXED: Fix issue with metadata disrupting smart quotes - -* 2017-02-07 -- v 0.1.2a: - - * "pathologic" test suite -- fix handling of nested brackets, e.g. - `[[[[foo]]]]` to avoid bogging down checking for reference links that - don't exist. - * Table support -- a single blank line separates sections of tables, so - at least two blank lines are needed between adjacent tables. - * Definition list support - * "fuzz testing" -- stress test the parser for unexpected failures - * Table of Contents support - * Improved compatibility mode parsing - -* 2017-01-28 -- v 0.1.1a includes a few updates: - - * Metadata support - * Metadata variables support - * Extended ASCII range character checking - * Rudimentary language translations, including German - * Improved performance - * Additional testing: - * CriticMarkup - * HTML Blokcs - * Metadata/Variables - * "pathologic" test cases from CommonMark +## An Announcement! ## +MultiMarkdown v6 is finally here! It's technically still in "beta" as I would +like to hear back from a few more users to make sure I'm not missing anything, +but it has been subjected to much more rigorous testing than any previous +versions of MultiMarkdown in the past. If you want more information about +testing, see `DevelopmentNotes`. It's basically feature complete as a +replacement for MMD v5, and included additional features beyond that. -## An Announcement! ## -I would like to officially announce that MultiMarkdown version 6 is in public -alpha. It's finally at a point where it is usable, but there are quite a few -caveats. +## Obtaining MultiMarkdown ## + +You can download the latest installer for MacOS or Windows at Github: + + -This post is a way for me to organize some of my thoughts, provide some -history for those who are interested, and to provide some tips and tricks from -my experiences for those who are working on their own products. +To build from source, download from Github. Then: -But first, some background... + make release + (OR) + make debug + cd build + make + +You can optionally test using the test suite: + + ctest ## Differences in MultiMarkdown Itself ## -MultiMarkdown v6 is mostly about making a better MMD parser, but it will -likely involve a few changes to the MultiMarkdown language itself. +MultiMarkdown v6 is mostly about making a better MMD parser, but it involves a +few changes to the MultiMarkdown syntax itself. +1. Setext headers can consist of more than one line to be included in the +header: -1. {--I am thinking about removing Setext headers from the language. I almost -never use them, much preferring to use ATX style headers (`# foo #`). -Additionally, I have never liked the fact that Setext headers allow the -meaning of a line to be completely changed by the following line. It makes -the parsing slightly more difficult on a technical level (requiring some -backtracking at times). I'm not 100% certain on this, but right now I believe -it's the only Markdown feature that doesn't exist in MMD 6 yet.--}{++I decided -to go ahead and implement Setext headers, as it can be done with the new -parser without backtracking. One difference with older versions of MMD, as -well as Markdown itself, is that a setext header can consist of more than one -line to be included in the header.++} + This is + a header + ======== 2. Whitespace is not allowed between the text brackets and label brackets in reference links, images, footnotes, etc. For example `[foo] [bar]` will no longer be the same as `[foo][bar]`. 3. Link and image titles can be quoted with `'foo'`, `"foo"`, or `(foo)`. +Link attributes can be used in both reference and inline links/images. 4. HTML elements are handled slightly differently. There is no longer a `markdown="1"` feature. Instead, HTML elements that are on a line by @@ -232,7 +64,8 @@ themselves will open an HTML block that will cause the rest of the "paragraph" to be treated as HTML such that Markdown will not be parsed in side of it. HTML block-level tags are even "stronger" at starting an HTML block. It is not quite as complex as the approach used in CommonMark, but is similar under -most circumstances. +most circumstances. Leaving a blank line after the opening tag will allow +MultiMarkdown parsing inside of the HTML block. For example, this would not be parsed: @@ -249,9 +82,10 @@ most circumstances. 5. "Malformed" reference link definitions are handled slightly differently. -For example, `Reference Footnotes.text` is parsed differently in compatibility -mode than MMD-5. This started as a side-effect of the parsing algorithm, but -I actually think it makes sense. This may or may not change in the future. +For example, the test suite file `Reference Footnotes.text` is parsed +differently in compatibility mode than MMD-5. This started as a side-effect +of the parsing algorithm, but I actually think it makes sense. This may or +may not change in the future. 6. Table captions in MMD-6 must come immediately *after* the table, not before it. @@ -261,61 +95,28 @@ before it. feature in MMD, but I don't see a problem with just making it default behavior. +8. Escaped spaces (`\ `) will be interpreted as a non-breaking space, if the +output format supports it. -## Where Does MultiMarkdown 6 Stand? ## - - -### Features ### - -I *think* that all basic Markdown features have been implemented. -Additionally, the following MultiMarkdown features have been implemented: - -* Automatic cross-reference targets -* Basic Citation support -* CriticMarkup support -* Definition lists -* Figures -* Footnotes -* Inline and reference footnotes -* Image and Link attributes (attributes can now be used with inline links as - well as reference links) -* Math support -* Smart quotes (support for languages other than english is not fully - implemented yet) -* Superscripts/subscripts -* Table of Contents -* Tables - - -Things that are partially completed: - -* Citations -- still need: - * Syntax for "not cited" entries - * Output format - * HTML --> separate footnotes and citations? - * Locators required? -* CriticMarkup -- need to decide: - * How to handle CM stretches that include blank lines -* Fenced code blocks -* Headers -- need support for manual labels -* Metadata -* Full/Snippet modes - - -Things yet to be completed: - -* Abbreviations -* Glossaries -* File Transclusion +9. CriticMarkup, Abbreviations, Glossary Terms, and Citations are handled +slightly differently. See the QuickStart guide for more information. +10. Fenced code blocks can use leading/trailing "fences" of 3, 4, or 5 +backticks in length. That should be sufficient for complex documents without +requiring a more complex parser. If there is no trailing fence, then the +fenced block is considered to go through the end of the document. -### Accuracy ### +11. Emph and Strong parsing is conceptually the same, but the implementation +is different. It is designed for speed, accuracy, and consistency. In +general, it seems to handle edge cases much more reliably, but there are still +a couple of situations that I would like to take into account, if possible. +These are not situations that should occur often in "real life." -MultiMarkdown v6 successfully parses the Markdown [syntax page], except for -the Setext header at the top. It passes the 29 test files currently in place. -There are a few at +12. EPUB 3 output is supported without need of any external tools. -[syntax page]: https://daringfireball.net/projects/markdown/syntax +13. Internationalization support for HTML phrases, such as "see footnote". See +[Github](https://github.com/fletcher/MultiMarkdown-6/issues/37) for more +information. diff --git a/templates/README.md.in b/templates/README.md.in index 5e388ded..cada7c72 100644 --- a/templates/README.md.in +++ b/templates/README.md.in @@ -9,222 +9,54 @@ | Version: | @My_Project_Version@ | -## Updates ## - -* 2017-03-13 -- v 6.0.0-b2: - - * ADDED: Add CriticMarkup preprocessor that works across empty lines when accepting/rejecting markup - * ADDED: Add back the mmd6 latex title file - * ADDED: Basic EPUB 3 support -- uses 'miniz' library to zip creation - * ADDED: Update QuickStart and EPUB code - * CHANGED: Update QuickStart guide - * CHANGED: Update test suite - * FIXED: Don't duplicate LaTeX glossary definitions - * FIXED: Fix abbreviations in ODF; Improve test suite - * FIXED: Improve glossaries and abbreviations; Update QuickStart - * FIXED: Tidy up some compiler warnings in code - * FIXED: Use custom UUID code to minimize external dependencies - - -* 2017-03-09 -- v 6.0.0-b1: - - * ADDED: Add French translations; fix typo in German - * ADDED: Add Quick Start guide - * ADDED: Add functionality to automatically identify abbreviations and glossary terms in source - * ADDED: Improve LaTeX configuration files - * ADDED: Update German translations - * ADDED: Use native ODF table of contents instead of a manual list - * ADDED: Use native command for table of contents in LaTeX - * CHANGED: Bring HTML and ODF into line with LaTeX as to output of abbreviatinos on first and subsequent uses - * CHANGED: Slight performance tweak - * CHANGED: Update German test suite - * FIXED: Allow {{TOC}} in latex verbatim - * FIXED: Don't free token_pool if never initialized - * FIXED: Fix German typo - * FIXED: Fix missing token type - * FIXED: Improve performance of checking document for metadata, which improves performance when checking for possible transclusion - * FIXED: Update test suite for abbreviation changes - - -* 2017-03-05 -- v 0.4.2-b: - - * ADDED: Add and utility functions; fix memory leak - * ADDED: Initial abbreviation support - * ADDED: Keep working on Abbreviations/Glossaries - * ADDED: Refactor abbreviation code; Add inline abbreviations; Fix abbreviations in ODF - * ADDED: Update Inline Footnote test - * CHANGED: Add comments to i18n.h - * CHANGED: Finish refactoring note-related code - * CHANGED: Refactor footnotes - * CHANGED: Refactor glossary code - * CHANGED: Remove offset from html export functions - * FIXED: latex list items need to block optional argument to allow '[' as first character - * Merge branch 'release/0.4.1-b' into develop - - -* 2017-03-04 -- v 0.4.1-b: - - * FIXED: Add glossary localization - - -* 2017-03-04 -- v 0.4.0-b: - - * ADDED: Add TOC support to ODF - * ADDED: Add glossary support to ODF - * ADDED: Add prelim code for handling abbreviations - * ADDED: Add support for Swift Package Maker; CHANGED: Restructure source directory - * ADDED: Added LaTeX support for escaped characters, fenced code blocks, images, links - * ADDED: Basic ODF Support - * ADDED: Better document strong/emph algorithm - * ADDED: Continue ODF progress - * ADDED: Continue to work on ODF export - * ADDED: Continue work on ODF - * ADDED: Finish ODF support for lists - * ADDED: Improve performance when exporting - * ADDED: Improve token_pool memory handling - * ADDED: Prototype support for Glossaries - * ADDED: Support 'latexconfig' metadata - * CHANGED: Use multiple cases in glossary tests - * FIXED: Don't force glossary terms into lowercase - * FIXED: Fix Makefile for new source file location - * FIXED: Fix algorithm for creating TOC to properly handle 'incorrect' levels - * FIXED: Fix linebreaks in LaTeX; ADDED: Add Linebreaks test file - * FIXED: Fix new_source script for new directory structure - * FIXED: Fix non-breaking space in ODF - * FIXED: Fix padding at end of document body in ODF - * FIXED: Fix underscores in raw latex - * FIXED: Potential bug - * NOTE: Add shared library build option - - -* 2017-02-17 -- v 0.3.1.a: - - * ADDED: 'finalize' beamer support - * ADDED: Add escaped newline as linebreak; start on beamer/memoir support - * ADDED: CriticMarkup test for LaTeX - * ADDED: Custom LaTeX output for CriticMarkup comments - * ADDED: Support mmd export format - * ADDED: Work on cpack installer -- change project name for compatibility - * CHANGED: Adjust latex metadata configuration for consistency - * CHANGED: Configure cmake to use C99 - * FIXED: Add custom implementation for cross-platform support - * FIXED: Fix German HTML tests - * FIXED: Fix cpack destination directory issue - * FIXED: Fix memory leaks etc - * FIXED: Fix warning in custom vasprintf - * FIXED: Modify CMakeLists.txt to test for use of clang compiler - * FIXED: Work on memory leaks - * NOTE: Adjust license width to improve display on smaller terminal windows - - -* 2017-02-14 -- v 0.3.0a: - - * ADDED: Add basic image support to LaTeX - * ADDED: Add file transclusion - * ADDED: Add support for citation 'locators' - * ADDED: Add support for manual labels on ATX Headers - * ADDED: Add support for manual labels on Setext Headers - * ADDED: Add support for tables in LaTeX - * ADDED: HTML Comments appear as raw LaTeX - * ADDED: Improved citation support in LaTeX - * ADDED: Support \autoref{} in LaTeX - * ADDED: Support combined options in LaTeX citations that use the '\]\[' syntax - * ADDED: Support language specifier in fenced code blocks - * ADDED: Support metadata in LaTeX - * ADDED: Update Citations test suite - * FIXED: Escaped LaTeX characters - * FIXED: Fix bug in URL parsing - * FIXED: Fix bug in citation links - * FIXED: Fix bug when no closing divider or newline at end of last table cell - * FIXED: Fix issue printing '-' - * FIXED: Fix scan_url test suite - * FIXED: Get Math working in LaTeX - * FIXED: Improve reliability or link scanner - * FIXED: Properly add id attribute to new instances of citation only - * FIXED: Properly handle manual labels with TOC - * FIXED: Properly print hash characters in LaTeX - * FIXED: Separate LaTeX verbatim and texttt character handling - * FIXED: Update Escapes test LaTeX result - * FIXED: Work on escaping LaTeX characters - - -* 2017-02-08 -- v 0.1.4a: - - * ADDED: Add smart quote support for other languages (resolves #15) - - -* 2017-02-08 -- v 0.1.3a: - - * ADDED: Add support for reference image id attributes - * ADDED: Add support for table captions - * ADDED: Metadata support for base header level - * ADDED: Support distinction between 3 and 5 backticks in fenced code blocks - * ADDED: Support Setext headers - * FIXED: Fix issue with metadata disrupting smart quotes - -* 2017-02-07 -- v 0.1.2a: - - * "pathologic" test suite -- fix handling of nested brackets, e.g. - `[[[[foo]]]]` to avoid bogging down checking for reference links that - don't exist. - * Table support -- a single blank line separates sections of tables, so - at least two blank lines are needed between adjacent tables. - * Definition list support - * "fuzz testing" -- stress test the parser for unexpected failures - * Table of Contents support - * Improved compatibility mode parsing - -* 2017-01-28 -- v 0.1.1a includes a few updates: - - * Metadata support - * Metadata variables support - * Extended ASCII range character checking - * Rudimentary language translations, including German - * Improved performance - * Additional testing: - * CriticMarkup - * HTML Blokcs - * Metadata/Variables - * "pathologic" test cases from CommonMark +## An Announcement! ## +MultiMarkdown v6 is finally here! It's technically still in "beta" as I would +like to hear back from a few more users to make sure I'm not missing anything, +but it has been subjected to much more rigorous testing than any previous +versions of MultiMarkdown in the past. If you want more information about +testing, see `DevelopmentNotes`. It's basically feature complete as a +replacement for MMD v5, and included additional features beyond that. -## An Announcement! ## -I would like to officially announce that MultiMarkdown version 6 is in public -alpha. It's finally at a point where it is usable, but there are quite a few -caveats. +## Obtaining MultiMarkdown ## + +You can download the latest installer for MacOS or Windows at Github: + + -This post is a way for me to organize some of my thoughts, provide some -history for those who are interested, and to provide some tips and tricks from -my experiences for those who are working on their own products. +To build from source, download from Github. Then: -But first, some background... + make release + (OR) + make debug + cd build + make + +You can optionally test using the test suite: + + ctest ## Differences in MultiMarkdown Itself ## -MultiMarkdown v6 is mostly about making a better MMD parser, but it will -likely involve a few changes to the MultiMarkdown language itself. +MultiMarkdown v6 is mostly about making a better MMD parser, but it involves a +few changes to the MultiMarkdown syntax itself. +1. Setext headers can consist of more than one line to be included in the +header: -1. {--I am thinking about removing Setext headers from the language. I almost -never use them, much preferring to use ATX style headers (`# foo #`). -Additionally, I have never liked the fact that Setext headers allow the -meaning of a line to be completely changed by the following line. It makes -the parsing slightly more difficult on a technical level (requiring some -backtracking at times). I'm not 100% certain on this, but right now I believe -it's the only Markdown feature that doesn't exist in MMD 6 yet.--}{++I decided -to go ahead and implement Setext headers, as it can be done with the new -parser without backtracking. One difference with older versions of MMD, as -well as Markdown itself, is that a setext header can consist of more than one -line to be included in the header.++} + This is + a header + ======== 2. Whitespace is not allowed between the text brackets and label brackets in reference links, images, footnotes, etc. For example `[foo] [bar]` will no longer be the same as `[foo][bar]`. 3. Link and image titles can be quoted with `'foo'`, `"foo"`, or `(foo)`. +Link attributes can be used in both reference and inline links/images. 4. HTML elements are handled slightly differently. There is no longer a `markdown="1"` feature. Instead, HTML elements that are on a line by @@ -232,7 +64,8 @@ themselves will open an HTML block that will cause the rest of the "paragraph" to be treated as HTML such that Markdown will not be parsed in side of it. HTML block-level tags are even "stronger" at starting an HTML block. It is not quite as complex as the approach used in CommonMark, but is similar under -most circumstances. +most circumstances. Leaving a blank line after the opening tag will allow +MultiMarkdown parsing inside of the HTML block. For example, this would not be parsed: @@ -249,9 +82,10 @@ most circumstances. 5. "Malformed" reference link definitions are handled slightly differently. -For example, `Reference Footnotes.text` is parsed differently in compatibility -mode than MMD-5. This started as a side-effect of the parsing algorithm, but -I actually think it makes sense. This may or may not change in the future. +For example, the test suite file `Reference Footnotes.text` is parsed +differently in compatibility mode than MMD-5. This started as a side-effect +of the parsing algorithm, but I actually think it makes sense. This may or +may not change in the future. 6. Table captions in MMD-6 must come immediately *after* the table, not before it. @@ -261,61 +95,28 @@ before it. feature in MMD, but I don't see a problem with just making it default behavior. +8. Escaped spaces (`\ `) will be interpreted as a non-breaking space, if the +output format supports it. -## Where Does MultiMarkdown 6 Stand? ## - - -### Features ### - -I *think* that all basic Markdown features have been implemented. -Additionally, the following MultiMarkdown features have been implemented: - -* Automatic cross-reference targets -* Basic Citation support -* CriticMarkup support -* Definition lists -* Figures -* Footnotes -* Inline and reference footnotes -* Image and Link attributes (attributes can now be used with inline links as - well as reference links) -* Math support -* Smart quotes (support for languages other than english is not fully - implemented yet) -* Superscripts/subscripts -* Table of Contents -* Tables - - -Things that are partially completed: - -* Citations -- still need: - * Syntax for "not cited" entries - * Output format - * HTML --> separate footnotes and citations? - * Locators required? -* CriticMarkup -- need to decide: - * How to handle CM stretches that include blank lines -* Fenced code blocks -* Headers -- need support for manual labels -* Metadata -* Full/Snippet modes - - -Things yet to be completed: - -* Abbreviations -* Glossaries -* File Transclusion +9. CriticMarkup, Abbreviations, Glossary Terms, and Citations are handled +slightly differently. See the QuickStart guide for more information. +10. Fenced code blocks can use leading/trailing "fences" of 3, 4, or 5 +backticks in length. That should be sufficient for complex documents without +requiring a more complex parser. If there is no trailing fence, then the +fenced block is considered to go through the end of the document. -### Accuracy ### +11. Emph and Strong parsing is conceptually the same, but the implementation +is different. It is designed for speed, accuracy, and consistency. In +general, it seems to handle edge cases much more reliably, but there are still +a couple of situations that I would like to take into account, if possible. +These are not situations that should occur often in "real life." -MultiMarkdown v6 successfully parses the Markdown [syntax page], except for -the Setext header at the top. It passes the 29 test files currently in place. -There are a few at +12. EPUB 3 output is supported without need of any external tools. -[syntax page]: https://daringfireball.net/projects/markdown/syntax +13. Internationalization support for HTML phrases, such as "see footnote". See +[Github](https://github.com/fletcher/MultiMarkdown-6/issues/37) for more +information. From a05ac160f20d92d17c41ca2fddd3123111919fab Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Wed, 15 Mar 2017 11:35:30 -0400 Subject: [PATCH 27/29] FIXED: Fix printing raw CriticMarkup tokens in LaTeX --- Sources/libMultiMarkdown/latex.c | 58 ++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/Sources/libMultiMarkdown/latex.c b/Sources/libMultiMarkdown/latex.c index 85bfba09..ae05e4a6 100644 --- a/Sources/libMultiMarkdown/latex.c +++ b/Sources/libMultiMarkdown/latex.c @@ -788,37 +788,37 @@ void mmd_export_token_latex(DString * out, const char * source, token * t, scrat print_const(":"); break; case CRITIC_ADD_OPEN: - print_const("{++"); + print_const("\\{++"); break; case CRITIC_ADD_CLOSE: - print_const("++}"); + print_const("++\\}"); break; case CRITIC_COM_OPEN: - print_const("{>>"); + print_const("\\{>>"); break; case CRITIC_COM_CLOSE: - print_const("<<}"); + print_const("<<\\}"); break; case CRITIC_DEL_OPEN: - print_const("{--"); + print_const("\\{--"); break; case CRITIC_DEL_CLOSE: - print_const("--}"); + print_const("--\\}"); break; case CRITIC_HI_OPEN: - print_const("{=="); + print_const("\\{=="); break; case CRITIC_HI_CLOSE: - print_const("==}"); + print_const("==\\}"); break; case CRITIC_SUB_OPEN: - print_const("{~~"); + print_const("\\{~~"); break; case CRITIC_SUB_DIV: print_const("~>"); break; case CRITIC_SUB_CLOSE: - print_const("~~}"); + print_const("~~\\}"); break; case DASH_M: if (!(scratch->extensions & EXT_SMART)) { @@ -1454,7 +1454,7 @@ void mmd_export_token_latex(DString * out, const char * source, token * t, scrat break; case QUOTE_DOUBLE: if ((t->mate == NULL) || (!(scratch->extensions & EXT_SMART))) - print_const("""); + print_const("''"); else (t->start < t->mate->start) ? ( print_localized(QUOTE_LEFT_DOUBLE) ) : ( print_localized(QUOTE_RIGHT_DOUBLE) ); break; @@ -1572,6 +1572,9 @@ void mmd_export_token_latex(DString * out, const char * source, token * t, scrat case TEXT_PLAIN: print_token(t); break; + case TOC: + print_const("\\{\\{TOC\\}\\}"); + break; case UL: print_const("\\_"); break; @@ -1659,6 +1662,39 @@ void mmd_export_token_latex_tt(DString * out, const char * source, token * t, sc case ANGLE_RIGHT: print_const("$>$"); break; + case CRITIC_ADD_OPEN: + print_const("\\{++"); + break; + case CRITIC_ADD_CLOSE: + print_const("++\\}"); + break; + case CRITIC_COM_OPEN: + print_const("\\{>>"); + break; + case CRITIC_COM_CLOSE: + print_const("<<\\}"); + break; + case CRITIC_DEL_OPEN: + print_const("\\{--"); + break; + case CRITIC_DEL_CLOSE: + print_const("--\\}"); + break; + case CRITIC_HI_OPEN: + print_const("\\{=="); + break; + case CRITIC_HI_CLOSE: + print_const("==\\}"); + break; + case CRITIC_SUB_OPEN: + print_const("\\{~~"); + break; + case CRITIC_SUB_DIV: + print_const("~>"); + break; + case CRITIC_SUB_CLOSE: + print_const("~~\\}"); + break; case DASH_N: if (t->len == 1) { print_const("-"); From 5675e85687e1a435db1e151fccda8ac26046fd1a Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Wed, 15 Mar 2017 11:37:33 -0400 Subject: [PATCH 28/29] CHANGED: Update documentation --- README.md | 2 +- templates/README.md.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5d08aa68..812a3caf 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ You can optionally test using the test suite: ctest -## Differences in MultiMarkdown Itself ## +## Differences in the MultiMarkdown Syntax ## MultiMarkdown v6 is mostly about making a better MMD parser, but it involves a few changes to the MultiMarkdown syntax itself. diff --git a/templates/README.md.in b/templates/README.md.in index cada7c72..e4999a6f 100644 --- a/templates/README.md.in +++ b/templates/README.md.in @@ -39,7 +39,7 @@ You can optionally test using the test suite: ctest -## Differences in MultiMarkdown Itself ## +## Differences in the MultiMarkdown Syntax ## MultiMarkdown v6 is mostly about making a better MMD parser, but it involves a few changes to the MultiMarkdown syntax itself. From bc2d9047657fbb4f349e0d09b4503050b8b91d42 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Wed, 15 Mar 2017 11:44:22 -0400 Subject: [PATCH 29/29] Version bump --- CMakeLists.txt | 4 +- DevelopmentNotes/DevelopmentNotes.epub | Bin 13645 -> 14008 bytes DevelopmentNotes/DevelopmentNotes.fodt | 99 ++++++++++++++++++++++++- DevelopmentNotes/DevelopmentNotes.html | 29 +++++++- DevelopmentNotes/DevelopmentNotes.pdf | Bin 103994 -> 105192 bytes DevelopmentNotes/DevelopmentNotes.txt | 28 ++++++- QuickStart/QuickStart.epub | Bin 7845 -> 7842 bytes QuickStart/QuickStart.fodt | 11 ++- QuickStart/QuickStart.html | 11 ++- QuickStart/QuickStart.pdf | Bin 88710 -> 89792 bytes QuickStart/QuickStart.txt | 2 +- README.md | 4 +- 12 files changed, 168 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f7843638..54cd14d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,10 +8,10 @@ cmake_minimum_required (VERSION 2.6) set (My_Project_Title "MultiMarkdown") set (My_Project_Description "Lightweight markup processor to produce HTML, LaTeX, and more.") set (My_Project_Author "Fletcher T. Penney") -set (My_Project_Revised_Date "2017-03-13") +set (My_Project_Revised_Date "2017-03-15") set (My_Project_Version_Major 6) set (My_Project_Version_Minor 0) -set (My_Project_Version_Patch 0-b2) +set (My_Project_Version_Patch 0-rc1) set (My_Project_Version "${My_Project_Version_Major}.${My_Project_Version_Minor}.${My_Project_Version_Patch}") diff --git a/DevelopmentNotes/DevelopmentNotes.epub b/DevelopmentNotes/DevelopmentNotes.epub index 1c2e6680623101d2a8162b0fadd025cdb62116cc..58c0acebb97a33b56d9eda5b7dfaa8445a1c244d 100644 GIT binary patch delta 12780 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
^fi>t%{m^OEO;g4maw_Ka?5o=OINbdJl@lI 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 diff --git a/DevelopmentNotes/DevelopmentNotes.fodt b/DevelopmentNotes/DevelopmentNotes.fodt index 092949d3..f02814d3 100644 --- a/DevelopmentNotes/DevelopmentNotes.fodt +++ b/DevelopmentNotes/DevelopmentNotes.fodt @@ -274,7 +274,7 @@ MultiMarkdown v6 Development Notes Fletcher T. Penney - 2017-03-14 + 2017-03-15 @@ -719,6 +719,103 @@ the code or used during the development. Changelog + +2017–03–15 – v 6.0.0-rc1: + + + + +FIXED: Add missing CriticMarkup tokens to LaTeX + + + +FIXED: Don‘t let labels end on ’' that is escaping the closing ‘]’ + + + +FIXED: Fix NULL pointer dereference + + + +FIXED: Fix bug in Aho–Corasick implementation + + + +FIXED: Fix bug with ATX Headers without newline + + + +FIXED: Fix bug with Setext header starting with ‘:’ + + + +FIXED: Fix bug with leading spaces in abbreviation references + + + +FIXED: Fix crash with empty definition + + + +FIXED: Fix edge case with URL definitions + + + +FIXED: Fix edge case with superscripts + + + +FIXED: Fix null dereference error in CriticMarkup substitution + + + +FIXED: Fix potential bug in Aho–Corasick search: + + + +FIXED: Fix potential bug in storing items to hash + + + +FIXED: Fix potential bug with line–>block parser + + + +FIXED: Fix potential crash in attribute parsing + + + +FIXED: Fix printing raw CriticMarkup tokens in LaTeX + + + +FIXED: Fix signedness bug in Aho–Corasick + + + +FIXED: Improve metadata edge cases; Fix NULL pointer dereference + + + +FIXED: Include non–breaking space (ASCII 160) in re2c patterns + + + +FIXED: Keep ‘:’ in false positive definitions + + + +FIXED: Lex space followed by tab as space, not text + + + +FIXED: Limit lines treated as ATX headers + + +FIXED: Update test code + + + 2017–03–13 – v 6.0.0-b2: diff --git a/DevelopmentNotes/DevelopmentNotes.html b/DevelopmentNotes/DevelopmentNotes.html index 493aa2b6..b7edd230 100644 --- a/DevelopmentNotes/DevelopmentNotes.html +++ b/DevelopmentNotes/DevelopmentNotes.html @@ -4,7 +4,7 @@ MultiMarkdown v6 Development Notes - + @@ -399,6 +399,33 @@

Unit Testing

Changelog

    +
  • 2017–03–15 – v 6.0.0-rc1:

    + +
      +
    • FIXED: Add missing CriticMarkup tokens to LaTeX
    • +
    • FIXED: Don‘t let labels end on ’' that is escaping the closing ‘]’
    • +
    • FIXED: Fix NULL pointer dereference
    • +
    • FIXED: Fix bug in Aho–Corasick implementation
    • +
    • FIXED: Fix bug with ATX Headers without newline
    • +
    • FIXED: Fix bug with Setext header starting with ‘:’
    • +
    • FIXED: Fix bug with leading spaces in abbreviation references
    • +
    • FIXED: Fix crash with empty definition
    • +
    • FIXED: Fix edge case with URL definitions
    • +
    • FIXED: Fix edge case with superscripts
    • +
    • FIXED: Fix null dereference error in CriticMarkup substitution
    • +
    • FIXED: Fix potential bug in Aho–Corasick search:
    • +
    • FIXED: Fix potential bug in storing items to hash
    • +
    • FIXED: Fix potential bug with line–>block parser
    • +
    • FIXED: Fix potential crash in attribute parsing
    • +
    • FIXED: Fix printing raw CriticMarkup tokens in LaTeX
    • +
    • FIXED: Fix signedness bug in Aho–Corasick
    • +
    • FIXED: Improve metadata edge cases; Fix NULL pointer dereference
    • +
    • FIXED: Include non–breaking space (ASCII 160) in re2c patterns
    • +
    • FIXED: Keep ‘:’ in false positive definitions
    • +
    • FIXED: Lex space followed by tab as space, not text
    • +
    • FIXED: Limit lines treated as ATX headers
    • +
    • FIXED: Update test code
    • +
  • 2017–03–13 – v 6.0.0-b2:

      diff --git a/DevelopmentNotes/DevelopmentNotes.pdf b/DevelopmentNotes/DevelopmentNotes.pdf index 611a80d9429c4c58d22691398db49a2409a5ec43..6f092a30711b47205f755d7b8e4ae6483b9d2f4d 100644 GIT binary patch delta 17732 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�UrQ*L7DBq^T5Yj!VG>0fgE$qxZhx_n}9(OdEo#2X^w|f)dAUnVK8nQyhhRW zQy}wT2*i_C8IzHj0nnsQNgMJcp3;iPpcjsUk&5|tC=oVu#rP%}g&A?WxxKZzH{RY@ z=nq2HJP}7skr^yhAOcBoL}whbe;N$45bh zfmVX{3sgQiHobOqZ*n9Ca9uc7RAkm=U9;sI6I=AKFrr~#V~@sI`zDCPOGg>7B`4D! zl{HZ5nfyPyQW8?nDVxc{dhwh9=c2WW${oQR%!1vEGUhs;niNrTh3Ur96{k0Q28yTm zFVZ_J=9+6PE#e&LwQc!>bMKyg`1YsApSLXJ?GDye=?@vekjEf0t zr0rRy$i9`!6t2I#=LuZsY1}pY<(bK!j?A=3oMt;WOgQ*0i*S7Vo#pq>vp&5dspWIx z;pWZLZ+M(BNz{uyf4XvuDyP!f`s75XZFW<(oD}3Jvpc9-Gvn}E!C8BgmpxL`?Cut1 zobqhy6OCtQ!*|FSZ(gCWX1QeKf#rWq-Gi?`WGG!5czaXnbwBpfv%$AF=+;y&^H2BB zTj_81_v*Ls>+yfP&tKn^b$j*OvVW?f`UP{Y_RDCkUHtFU|J~~oKj+=f$>+2F`Q&|t zL3PH9U;FG#&42F}ldNhe`@iJvo9LF<+PWR<%1`DQ@)Z4 z$#llkZ%txUsyB({(htt8N>wm21x`SRD?}SA7%Lb81%vYQf%(nU5V#;Eh)dryFD)O) zGlKG56rydM9bL>_O$?o#%uQX5T@8($98E1<3{9MjEKS{<4J}OV6bLJc<%JLVm>HTt zmbu7I@$?UI6mfg+>Q$H{bK#gE`xP;ls6Yo+Q5V;c9H|Y34hzKdVkA6bwDWp96`%cP z-&K}-=zc-&qeBt<4=y}^cg~&i_|UyoU*~>5bLOAv%$H(2c;A^!IFnm&cZHSo3EdFB zSqC($X0I@7NHg%uR}N(gJbR)0w8R;$TYma!Ic(AOFWxQ{_s(U#{X%xRxPP+SEywp( zdvCZgZn-4AP~7@1XIbOj1pb7lAuMkb>@67h8V^6yAAL;F{Q?bx6B4=;8gQ-@89bi2qWk@15Z0p}a(J---uj zpHz>z?sL)pBKS+=(@{mBHjjsHyKf(f@^RK&IHjWa;nW`mS6+twm2nPm-Lb4KZR`Gv z+Ke^<({KMN_;N@nC7?gLR-=kT$uB5l;ilW&_Jz!$Ez+-wtAE;6{aD1=Q{kK<}8v^! zx4)OKSa!EAe9^2z`QKuqt1>vR+`V3R>GYG?oF>8i1&q%BVKp*LOFDC8MyH{0 svf6f;{bGksyMFJ_KO4LHo4k(c^cT|wr!mTLn*di>aH*=g`nz!f0D&%zg8%>k delta 16550 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 diff --git a/DevelopmentNotes/DevelopmentNotes.txt b/DevelopmentNotes/DevelopmentNotes.txt index 072d63d0..da5c2b23 100644 --- a/DevelopmentNotes/DevelopmentNotes.txt +++ b/DevelopmentNotes/DevelopmentNotes.txt @@ -1,6 +1,6 @@ Title: MultiMarkdown v6 Development Notes Author: Fletcher T. Penney -Date: 2017-03-14 +Date: 2017-03-15 LaTeX Config: tufte-handout Base Header Level: 3 @@ -432,6 +432,32 @@ the code or used during the development. # Changelog # +* 2017-03-15 -- v 6.0.0-rc1: + + * FIXED: Add missing CriticMarkup tokens to LaTeX + * FIXED: Don't let labels end on '\' that is escaping the closing ']' + * FIXED: Fix NULL pointer dereference + * FIXED: Fix bug in Aho-Corasick implementation + * FIXED: Fix bug with ATX Headers without newline + * FIXED: Fix bug with Setext header starting with ':' + * FIXED: Fix bug with leading spaces in abbreviation references + * FIXED: Fix crash with empty definition + * FIXED: Fix edge case with URL definitions + * FIXED: Fix edge case with superscripts + * FIXED: Fix null dereference error in CriticMarkup substitution + * FIXED: Fix potential bug in Aho-Corasick search: + * FIXED: Fix potential bug in storing items to hash + * FIXED: Fix potential bug with line->block parser + * FIXED: Fix potential crash in attribute parsing + * FIXED: Fix printing raw CriticMarkup tokens in LaTeX + * FIXED: Fix signedness bug in Aho-Corasick + * FIXED: Improve metadata edge cases; Fix NULL pointer dereference + * FIXED: Include non-breaking space (ASCII 160) in re2c patterns + * FIXED: Keep ':' in false positive definitions + * FIXED: Lex space followed by tab as space, not text + * FIXED: Limit lines treated as ATX headers + * FIXED: Update test code + * 2017-03-13 -- v 6.0.0-b2: diff --git a/QuickStart/QuickStart.epub b/QuickStart/QuickStart.epub index c18779b93c7bc9485eec60eb50e0ddf4f6e0e26c..ec826597e43267bbc3eb0bd79e3667a491377ac1 100644 GIT binary patch delta 5710 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 delta 5697 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 diff --git a/QuickStart/QuickStart.fodt b/QuickStart/QuickStart.fodt index 10238a14..ed5c9487 100644 --- a/QuickStart/QuickStart.fodt +++ b/QuickStart/QuickStart.fodt @@ -274,7 +274,7 @@ MultiMarkdown v6 Quick Start Guide Fletcher T. Penney - 6.0-b + 6.0.0-rc1 0d6313fa-9135-477e-9c14-7d62c1977833 @@ -308,7 +308,7 @@ Introduction -Version: 6.0-b +Version: 6.0.0-rc1 This document serves as a description of MultiMarkdown (MMD) v6, as well as a sample document to demonstrate the various features. Specifically, differences from @@ -503,10 +503,9 @@ older versions of the EPUB format, but other tools can convert to other document formats you need. Same goes for Amazon’s ebook formats – the Calibre program can also be used to interconvert between formats. -**NOTE: Because EPUB documents are binary files, MMD only creates them when -**run in batch mode (using the -b\--batch options). Otherwise, it simply -**outputs the HTML 5 file that would serve as the primary content for the -**EPUB. +NOTE: Because EPUB documents are binary files, MMD only creates them when +run in batch mode (using the -b\--batch options). Otherwise, it simply +outputs the HTML 5 file that would serve as the primary content for the EPUB. Fenced Code Blocks diff --git a/QuickStart/QuickStart.html b/QuickStart/QuickStart.html index 4d1ec694..9dc59695 100644 --- a/QuickStart/QuickStart.html +++ b/QuickStart/QuickStart.html @@ -4,7 +4,7 @@ MultiMarkdown v6 Quick Start Guide - + @@ -35,7 +35,7 @@

      Introduction

      -

      Version: 6.0-b

      +

      Version: 6.0.0-rc1

      This document serves as a description of MultiMarkdown (MMD) v6, as well as a sample document to demonstrate the various features. Specifically, differences from @@ -217,10 +217,9 @@

      EPUB 3 Support

      document formats you need. Same goes for Amazon’s ebook formats – the Calibre program can also be used to interconvert between formats.

      -

      **NOTE: Because EPUB documents are binary files, MMD only creates them when -**run in batch mode (using the -b\--batch options). Otherwise, it simply -**outputs the HTML 5 file that would serve as the primary content for the -**EPUB.

      +

      NOTE: Because EPUB documents are binary files, MMD only creates them when +run in batch mode (using the -b\--batch options). Otherwise, it simply +outputs the HTML 5 file that would serve as the primary content for the EPUB.

      Fenced Code Blocks

      diff --git a/QuickStart/QuickStart.pdf b/QuickStart/QuickStart.pdf index 6926d2906aabfc6e810c6f618c0ce30b8f685547..ad3bcd81b542df5f422775618886236f0dd47cb7 100644 GIT binary patch delta 16606 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 LNhzTy3HSd2rc&LF diff --git a/QuickStart/QuickStart.txt b/QuickStart/QuickStart.txt index 81159351..c3583aec 100644 --- a/QuickStart/QuickStart.txt +++ b/QuickStart/QuickStart.txt @@ -1,6 +1,6 @@ Title: MultiMarkdown v6 Quick Start Guide Author: Fletcher T. Penney -Version: 6.0-b +Version: 6.0.0-rc1 LaTeX Config: tufte-handout Base Header Level: 3 uuid: 0d6313fa-9135-477e-9c14-7d62c1977833 diff --git a/README.md b/README.md index 812a3caf..b7fa26cd 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ | ---------- | ------------------------- | | Title: | MultiMarkdown | | Author: | Fletcher T. Penney | -| Date: | 2017-03-13 | +| Date: | 2017-03-15 | | Copyright: | Copyright © 2016 - 2017 Fletcher T. Penney. | -| Version: | 6.0.0-b2 | +| Version: | 6.0.0-rc1 | ## An Announcement! ##